├── example ├── www │ ├── script.js │ ├── un.gif │ ├── AD_24x24.png │ ├── AD_48x48.png │ ├── eu_trade.jpg │ ├── flags │ │ ├── AD.png │ │ ├── AE.png │ │ ├── AF.png │ │ ├── AG.png │ │ ├── AI.png │ │ ├── AL.png │ │ ├── AM.png │ │ ├── AO.png │ │ ├── AR.png │ │ ├── AS.png │ │ ├── AT.png │ │ ├── AU.png │ │ ├── AW.png │ │ ├── AX.png │ │ ├── AZ.png │ │ ├── BA.png │ │ ├── BB.png │ │ ├── BD.png │ │ ├── BE.png │ │ ├── BF.png │ │ ├── BG.png │ │ ├── BH.png │ │ ├── BI.png │ │ ├── BJ.png │ │ ├── BL.png │ │ ├── BM.png │ │ ├── BN.png │ │ ├── BO.png │ │ ├── BQ.png │ │ ├── BR.png │ │ ├── BS.png │ │ ├── BT.png │ │ ├── BV.png │ │ ├── BW.png │ │ ├── BY.png │ │ ├── BZ.png │ │ ├── CA.png │ │ ├── CC.png │ │ ├── CD.png │ │ ├── CF.png │ │ ├── CG.png │ │ ├── CH.png │ │ ├── CI.png │ │ ├── CK.png │ │ ├── CL.png │ │ ├── CM.png │ │ ├── CN.png │ │ ├── CO.png │ │ ├── CR.png │ │ ├── CU.png │ │ ├── CV.png │ │ ├── CW.png │ │ ├── CX.png │ │ ├── CY.png │ │ ├── CZ.png │ │ ├── DE.png │ │ ├── DJ.png │ │ ├── DK.png │ │ ├── DM.png │ │ ├── DO.png │ │ ├── DZ.png │ │ ├── EC.png │ │ ├── EE.png │ │ ├── EG.png │ │ ├── ER.png │ │ ├── ES.png │ │ ├── ET.png │ │ ├── FI.png │ │ ├── FJ.png │ │ ├── FK.png │ │ ├── FM.png │ │ ├── FO.png │ │ ├── FR.png │ │ ├── GA.png │ │ ├── GB.png │ │ ├── GD.png │ │ ├── GE.png │ │ ├── GF.png │ │ ├── GG.png │ │ ├── GH.png │ │ ├── GI.png │ │ ├── GL.png │ │ ├── GM.png │ │ ├── GN.png │ │ ├── GP.png │ │ ├── GQ.png │ │ ├── GR.png │ │ ├── GS.png │ │ ├── GT.png │ │ ├── GU.png │ │ ├── GW.png │ │ ├── GY.png │ │ ├── HK.png │ │ ├── HN.png │ │ ├── HR.png │ │ ├── HT.png │ │ ├── HU.png │ │ ├── ID.png │ │ ├── IE.png │ │ ├── IL.png │ │ ├── IM.png │ │ ├── IN.png │ │ ├── IO.png │ │ ├── IQ.png │ │ ├── IR.png │ │ ├── IS.png │ │ ├── IT.png │ │ ├── JE.png │ │ ├── JM.png │ │ ├── JO.png │ │ ├── JP.png │ │ ├── KE.png │ │ ├── KG.png │ │ ├── KH.png │ │ ├── KI.png │ │ ├── KM.png │ │ ├── KN.png │ │ ├── KP.png │ │ ├── KR.png │ │ ├── KW.png │ │ ├── KY.png │ │ ├── KZ.png │ │ ├── LA.png │ │ ├── LB.png │ │ ├── LC.png │ │ ├── LI.png │ │ ├── LK.png │ │ ├── LR.png │ │ ├── LS.png │ │ ├── LT.png │ │ ├── LU.png │ │ ├── LV.png │ │ ├── LY.png │ │ ├── MA.png │ │ ├── MC.png │ │ ├── MD.png │ │ ├── ME.png │ │ ├── MG.png │ │ ├── MH.png │ │ ├── MK.png │ │ ├── ML.png │ │ ├── MM.png │ │ ├── MN.png │ │ ├── MO.png │ │ ├── MP.png │ │ ├── MQ.png │ │ ├── MR.png │ │ ├── MS.png │ │ ├── MT.png │ │ ├── MU.png │ │ ├── MV.png │ │ ├── MW.png │ │ ├── MX.png │ │ ├── MY.png │ │ ├── MZ.png │ │ ├── NA.png │ │ ├── NC.png │ │ ├── NE.png │ │ ├── NF.png │ │ ├── NG.png │ │ ├── NI.png │ │ ├── NL.png │ │ ├── NO.png │ │ ├── NP.png │ │ ├── NR.png │ │ ├── NU.png │ │ ├── NZ.png │ │ ├── OM.png │ │ ├── PA.png │ │ ├── PE.png │ │ ├── PF.png │ │ ├── PG.png │ │ ├── PH.png │ │ ├── PK.png │ │ ├── PL.png │ │ ├── PM.png │ │ ├── PN.png │ │ ├── PR.png │ │ ├── PS.png │ │ ├── PT.png │ │ ├── PW.png │ │ ├── PY.png │ │ ├── QA.png │ │ ├── RE.png │ │ ├── RO.png │ │ ├── RS.png │ │ ├── RU.png │ │ ├── RW.png │ │ ├── SA.png │ │ ├── SB.png │ │ ├── SC.png │ │ ├── SD.png │ │ ├── SE.png │ │ ├── SG.png │ │ ├── SH.png │ │ ├── SI.png │ │ ├── SK.png │ │ ├── SL.png │ │ ├── SM.png │ │ ├── SN.png │ │ ├── SO.png │ │ ├── SR.png │ │ ├── SS.png │ │ ├── ST.png │ │ ├── SV.png │ │ ├── SX.png │ │ ├── SY.png │ │ ├── SZ.png │ │ ├── TC.png │ │ ├── TD.png │ │ ├── TF.png │ │ ├── TG.png │ │ ├── TH.png │ │ ├── TJ.png │ │ ├── TK.png │ │ ├── TL.png │ │ ├── TM.png │ │ ├── TN.png │ │ ├── TO.png │ │ ├── TR.png │ │ ├── TT.png │ │ ├── TV.png │ │ ├── TW.png │ │ ├── TZ.png │ │ ├── UA.png │ │ ├── UG.png │ │ ├── UM.png │ │ ├── US.png │ │ ├── UY.png │ │ ├── UZ.png │ │ ├── VA.png │ │ ├── VC.png │ │ ├── VE.png │ │ ├── VG.png │ │ ├── VI.png │ │ ├── VN.png │ │ ├── VU.png │ │ ├── WF.png │ │ ├── WS.png │ │ ├── YE.png │ │ ├── YT.png │ │ ├── ZA.png │ │ ├── ZM.png │ │ └── ZW.png │ ├── background.jpg │ ├── bbc_flags.jpg │ ├── font │ │ ├── Amble-Regular-webfont.eot │ │ ├── Amble-Regular-webfont.ttf │ │ ├── Amble-Regular-webfont.woff │ │ └── Amble-Regular-webfont.svg │ ├── iframe.html │ ├── style.css │ └── index.html ├── main.go ├── localhost.crt └── localhost.key ├── .travis.yml ├── fileopener.go ├── util_test.go ├── LICENSE.md ├── cache.go ├── handler.go ├── handler_test.go ├── parse_test.go ├── README.md ├── util.go └── parse.go /example/www/script.js: -------------------------------------------------------------------------------- 1 | console.log("test"); -------------------------------------------------------------------------------- /example/www/un.gif: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/un.gif -------------------------------------------------------------------------------- /example/www/AD_24x24.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/AD_24x24.png -------------------------------------------------------------------------------- /example/www/AD_48x48.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/AD_48x48.png -------------------------------------------------------------------------------- /example/www/eu_trade.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/eu_trade.jpg -------------------------------------------------------------------------------- /example/www/flags/AD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AD.png -------------------------------------------------------------------------------- /example/www/flags/AE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AE.png -------------------------------------------------------------------------------- /example/www/flags/AF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AF.png -------------------------------------------------------------------------------- /example/www/flags/AG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AG.png -------------------------------------------------------------------------------- /example/www/flags/AI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AI.png -------------------------------------------------------------------------------- /example/www/flags/AL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AL.png -------------------------------------------------------------------------------- /example/www/flags/AM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AM.png -------------------------------------------------------------------------------- /example/www/flags/AO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AO.png -------------------------------------------------------------------------------- /example/www/flags/AR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AR.png -------------------------------------------------------------------------------- /example/www/flags/AS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AS.png -------------------------------------------------------------------------------- /example/www/flags/AT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AT.png -------------------------------------------------------------------------------- /example/www/flags/AU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AU.png -------------------------------------------------------------------------------- /example/www/flags/AW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AW.png -------------------------------------------------------------------------------- /example/www/flags/AX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AX.png -------------------------------------------------------------------------------- /example/www/flags/AZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/AZ.png -------------------------------------------------------------------------------- /example/www/flags/BA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BA.png -------------------------------------------------------------------------------- /example/www/flags/BB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BB.png -------------------------------------------------------------------------------- /example/www/flags/BD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BD.png -------------------------------------------------------------------------------- /example/www/flags/BE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BE.png -------------------------------------------------------------------------------- /example/www/flags/BF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BF.png -------------------------------------------------------------------------------- /example/www/flags/BG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BG.png -------------------------------------------------------------------------------- /example/www/flags/BH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BH.png -------------------------------------------------------------------------------- /example/www/flags/BI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BI.png -------------------------------------------------------------------------------- /example/www/flags/BJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BJ.png -------------------------------------------------------------------------------- /example/www/flags/BL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BL.png -------------------------------------------------------------------------------- /example/www/flags/BM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BM.png -------------------------------------------------------------------------------- /example/www/flags/BN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BN.png -------------------------------------------------------------------------------- /example/www/flags/BO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BO.png -------------------------------------------------------------------------------- /example/www/flags/BQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BQ.png -------------------------------------------------------------------------------- /example/www/flags/BR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BR.png -------------------------------------------------------------------------------- /example/www/flags/BS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BS.png -------------------------------------------------------------------------------- /example/www/flags/BT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BT.png -------------------------------------------------------------------------------- /example/www/flags/BV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BV.png -------------------------------------------------------------------------------- /example/www/flags/BW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BW.png -------------------------------------------------------------------------------- /example/www/flags/BY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BY.png -------------------------------------------------------------------------------- /example/www/flags/BZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/BZ.png -------------------------------------------------------------------------------- /example/www/flags/CA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CA.png -------------------------------------------------------------------------------- /example/www/flags/CC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CC.png -------------------------------------------------------------------------------- /example/www/flags/CD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CD.png -------------------------------------------------------------------------------- /example/www/flags/CF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CF.png -------------------------------------------------------------------------------- /example/www/flags/CG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CG.png -------------------------------------------------------------------------------- /example/www/flags/CH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CH.png -------------------------------------------------------------------------------- /example/www/flags/CI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CI.png -------------------------------------------------------------------------------- /example/www/flags/CK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CK.png -------------------------------------------------------------------------------- /example/www/flags/CL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CL.png -------------------------------------------------------------------------------- /example/www/flags/CM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CM.png -------------------------------------------------------------------------------- /example/www/flags/CN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CN.png -------------------------------------------------------------------------------- /example/www/flags/CO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CO.png -------------------------------------------------------------------------------- /example/www/flags/CR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CR.png -------------------------------------------------------------------------------- /example/www/flags/CU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CU.png -------------------------------------------------------------------------------- /example/www/flags/CV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CV.png -------------------------------------------------------------------------------- /example/www/flags/CW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CW.png -------------------------------------------------------------------------------- /example/www/flags/CX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CX.png -------------------------------------------------------------------------------- /example/www/flags/CY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CY.png -------------------------------------------------------------------------------- /example/www/flags/CZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/CZ.png -------------------------------------------------------------------------------- /example/www/flags/DE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DE.png -------------------------------------------------------------------------------- /example/www/flags/DJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DJ.png -------------------------------------------------------------------------------- /example/www/flags/DK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DK.png -------------------------------------------------------------------------------- /example/www/flags/DM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DM.png -------------------------------------------------------------------------------- /example/www/flags/DO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DO.png -------------------------------------------------------------------------------- /example/www/flags/DZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/DZ.png -------------------------------------------------------------------------------- /example/www/flags/EC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/EC.png -------------------------------------------------------------------------------- /example/www/flags/EE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/EE.png -------------------------------------------------------------------------------- /example/www/flags/EG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/EG.png -------------------------------------------------------------------------------- /example/www/flags/ER.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ER.png -------------------------------------------------------------------------------- /example/www/flags/ES.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ES.png -------------------------------------------------------------------------------- /example/www/flags/ET.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ET.png -------------------------------------------------------------------------------- /example/www/flags/FI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FI.png -------------------------------------------------------------------------------- /example/www/flags/FJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FJ.png -------------------------------------------------------------------------------- /example/www/flags/FK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FK.png -------------------------------------------------------------------------------- /example/www/flags/FM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FM.png -------------------------------------------------------------------------------- /example/www/flags/FO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FO.png -------------------------------------------------------------------------------- /example/www/flags/FR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/FR.png -------------------------------------------------------------------------------- /example/www/flags/GA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GA.png -------------------------------------------------------------------------------- /example/www/flags/GB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GB.png -------------------------------------------------------------------------------- /example/www/flags/GD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GD.png -------------------------------------------------------------------------------- /example/www/flags/GE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GE.png -------------------------------------------------------------------------------- /example/www/flags/GF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GF.png -------------------------------------------------------------------------------- /example/www/flags/GG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GG.png -------------------------------------------------------------------------------- /example/www/flags/GH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GH.png -------------------------------------------------------------------------------- /example/www/flags/GI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GI.png -------------------------------------------------------------------------------- /example/www/flags/GL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GL.png -------------------------------------------------------------------------------- /example/www/flags/GM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GM.png -------------------------------------------------------------------------------- /example/www/flags/GN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GN.png -------------------------------------------------------------------------------- /example/www/flags/GP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GP.png -------------------------------------------------------------------------------- /example/www/flags/GQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GQ.png -------------------------------------------------------------------------------- /example/www/flags/GR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GR.png -------------------------------------------------------------------------------- /example/www/flags/GS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GS.png -------------------------------------------------------------------------------- /example/www/flags/GT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GT.png -------------------------------------------------------------------------------- /example/www/flags/GU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GU.png -------------------------------------------------------------------------------- /example/www/flags/GW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GW.png -------------------------------------------------------------------------------- /example/www/flags/GY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/GY.png -------------------------------------------------------------------------------- /example/www/flags/HK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/HK.png -------------------------------------------------------------------------------- /example/www/flags/HN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/HN.png -------------------------------------------------------------------------------- /example/www/flags/HR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/HR.png -------------------------------------------------------------------------------- /example/www/flags/HT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/HT.png -------------------------------------------------------------------------------- /example/www/flags/HU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/HU.png -------------------------------------------------------------------------------- /example/www/flags/ID.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ID.png -------------------------------------------------------------------------------- /example/www/flags/IE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IE.png -------------------------------------------------------------------------------- /example/www/flags/IL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IL.png -------------------------------------------------------------------------------- /example/www/flags/IM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IM.png -------------------------------------------------------------------------------- /example/www/flags/IN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IN.png -------------------------------------------------------------------------------- /example/www/flags/IO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IO.png -------------------------------------------------------------------------------- /example/www/flags/IQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IQ.png -------------------------------------------------------------------------------- /example/www/flags/IR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IR.png -------------------------------------------------------------------------------- /example/www/flags/IS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IS.png -------------------------------------------------------------------------------- /example/www/flags/IT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/IT.png -------------------------------------------------------------------------------- /example/www/flags/JE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/JE.png -------------------------------------------------------------------------------- /example/www/flags/JM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/JM.png -------------------------------------------------------------------------------- /example/www/flags/JO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/JO.png -------------------------------------------------------------------------------- /example/www/flags/JP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/JP.png -------------------------------------------------------------------------------- /example/www/flags/KE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KE.png -------------------------------------------------------------------------------- /example/www/flags/KG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KG.png -------------------------------------------------------------------------------- /example/www/flags/KH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KH.png -------------------------------------------------------------------------------- /example/www/flags/KI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KI.png -------------------------------------------------------------------------------- /example/www/flags/KM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KM.png -------------------------------------------------------------------------------- /example/www/flags/KN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KN.png -------------------------------------------------------------------------------- /example/www/flags/KP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KP.png -------------------------------------------------------------------------------- /example/www/flags/KR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KR.png -------------------------------------------------------------------------------- /example/www/flags/KW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KW.png -------------------------------------------------------------------------------- /example/www/flags/KY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KY.png -------------------------------------------------------------------------------- /example/www/flags/KZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/KZ.png -------------------------------------------------------------------------------- /example/www/flags/LA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LA.png -------------------------------------------------------------------------------- /example/www/flags/LB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LB.png -------------------------------------------------------------------------------- /example/www/flags/LC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LC.png -------------------------------------------------------------------------------- /example/www/flags/LI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LI.png -------------------------------------------------------------------------------- /example/www/flags/LK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LK.png -------------------------------------------------------------------------------- /example/www/flags/LR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LR.png -------------------------------------------------------------------------------- /example/www/flags/LS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LS.png -------------------------------------------------------------------------------- /example/www/flags/LT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LT.png -------------------------------------------------------------------------------- /example/www/flags/LU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LU.png -------------------------------------------------------------------------------- /example/www/flags/LV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LV.png -------------------------------------------------------------------------------- /example/www/flags/LY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/LY.png -------------------------------------------------------------------------------- /example/www/flags/MA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MA.png -------------------------------------------------------------------------------- /example/www/flags/MC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MC.png -------------------------------------------------------------------------------- /example/www/flags/MD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MD.png -------------------------------------------------------------------------------- /example/www/flags/ME.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ME.png -------------------------------------------------------------------------------- /example/www/flags/MG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MG.png -------------------------------------------------------------------------------- /example/www/flags/MH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MH.png -------------------------------------------------------------------------------- /example/www/flags/MK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MK.png -------------------------------------------------------------------------------- /example/www/flags/ML.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ML.png -------------------------------------------------------------------------------- /example/www/flags/MM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MM.png -------------------------------------------------------------------------------- /example/www/flags/MN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MN.png -------------------------------------------------------------------------------- /example/www/flags/MO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MO.png -------------------------------------------------------------------------------- /example/www/flags/MP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MP.png -------------------------------------------------------------------------------- /example/www/flags/MQ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MQ.png -------------------------------------------------------------------------------- /example/www/flags/MR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MR.png -------------------------------------------------------------------------------- /example/www/flags/MS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MS.png -------------------------------------------------------------------------------- /example/www/flags/MT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MT.png -------------------------------------------------------------------------------- /example/www/flags/MU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MU.png -------------------------------------------------------------------------------- /example/www/flags/MV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MV.png -------------------------------------------------------------------------------- /example/www/flags/MW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MW.png -------------------------------------------------------------------------------- /example/www/flags/MX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MX.png -------------------------------------------------------------------------------- /example/www/flags/MY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MY.png -------------------------------------------------------------------------------- /example/www/flags/MZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/MZ.png -------------------------------------------------------------------------------- /example/www/flags/NA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NA.png -------------------------------------------------------------------------------- /example/www/flags/NC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NC.png -------------------------------------------------------------------------------- /example/www/flags/NE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NE.png -------------------------------------------------------------------------------- /example/www/flags/NF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NF.png -------------------------------------------------------------------------------- /example/www/flags/NG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NG.png -------------------------------------------------------------------------------- /example/www/flags/NI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NI.png -------------------------------------------------------------------------------- /example/www/flags/NL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NL.png -------------------------------------------------------------------------------- /example/www/flags/NO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NO.png -------------------------------------------------------------------------------- /example/www/flags/NP.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NP.png -------------------------------------------------------------------------------- /example/www/flags/NR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NR.png -------------------------------------------------------------------------------- /example/www/flags/NU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NU.png -------------------------------------------------------------------------------- /example/www/flags/NZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/NZ.png -------------------------------------------------------------------------------- /example/www/flags/OM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/OM.png -------------------------------------------------------------------------------- /example/www/flags/PA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PA.png -------------------------------------------------------------------------------- /example/www/flags/PE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PE.png -------------------------------------------------------------------------------- /example/www/flags/PF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PF.png -------------------------------------------------------------------------------- /example/www/flags/PG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PG.png -------------------------------------------------------------------------------- /example/www/flags/PH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PH.png -------------------------------------------------------------------------------- /example/www/flags/PK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PK.png -------------------------------------------------------------------------------- /example/www/flags/PL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PL.png -------------------------------------------------------------------------------- /example/www/flags/PM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PM.png -------------------------------------------------------------------------------- /example/www/flags/PN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PN.png -------------------------------------------------------------------------------- /example/www/flags/PR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PR.png -------------------------------------------------------------------------------- /example/www/flags/PS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PS.png -------------------------------------------------------------------------------- /example/www/flags/PT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PT.png -------------------------------------------------------------------------------- /example/www/flags/PW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PW.png -------------------------------------------------------------------------------- /example/www/flags/PY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/PY.png -------------------------------------------------------------------------------- /example/www/flags/QA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/QA.png -------------------------------------------------------------------------------- /example/www/flags/RE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/RE.png -------------------------------------------------------------------------------- /example/www/flags/RO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/RO.png -------------------------------------------------------------------------------- /example/www/flags/RS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/RS.png -------------------------------------------------------------------------------- /example/www/flags/RU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/RU.png -------------------------------------------------------------------------------- /example/www/flags/RW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/RW.png -------------------------------------------------------------------------------- /example/www/flags/SA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SA.png -------------------------------------------------------------------------------- /example/www/flags/SB.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SB.png -------------------------------------------------------------------------------- /example/www/flags/SC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SC.png -------------------------------------------------------------------------------- /example/www/flags/SD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SD.png -------------------------------------------------------------------------------- /example/www/flags/SE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SE.png -------------------------------------------------------------------------------- /example/www/flags/SG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SG.png -------------------------------------------------------------------------------- /example/www/flags/SH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SH.png -------------------------------------------------------------------------------- /example/www/flags/SI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SI.png -------------------------------------------------------------------------------- /example/www/flags/SK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SK.png -------------------------------------------------------------------------------- /example/www/flags/SL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SL.png -------------------------------------------------------------------------------- /example/www/flags/SM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SM.png -------------------------------------------------------------------------------- /example/www/flags/SN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SN.png -------------------------------------------------------------------------------- /example/www/flags/SO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SO.png -------------------------------------------------------------------------------- /example/www/flags/SR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SR.png -------------------------------------------------------------------------------- /example/www/flags/SS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SS.png -------------------------------------------------------------------------------- /example/www/flags/ST.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ST.png -------------------------------------------------------------------------------- /example/www/flags/SV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SV.png -------------------------------------------------------------------------------- /example/www/flags/SX.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SX.png -------------------------------------------------------------------------------- /example/www/flags/SY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SY.png -------------------------------------------------------------------------------- /example/www/flags/SZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/SZ.png -------------------------------------------------------------------------------- /example/www/flags/TC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TC.png -------------------------------------------------------------------------------- /example/www/flags/TD.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TD.png -------------------------------------------------------------------------------- /example/www/flags/TF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TF.png -------------------------------------------------------------------------------- /example/www/flags/TG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TG.png -------------------------------------------------------------------------------- /example/www/flags/TH.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TH.png -------------------------------------------------------------------------------- /example/www/flags/TJ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TJ.png -------------------------------------------------------------------------------- /example/www/flags/TK.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TK.png -------------------------------------------------------------------------------- /example/www/flags/TL.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TL.png -------------------------------------------------------------------------------- /example/www/flags/TM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TM.png -------------------------------------------------------------------------------- /example/www/flags/TN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TN.png -------------------------------------------------------------------------------- /example/www/flags/TO.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TO.png -------------------------------------------------------------------------------- /example/www/flags/TR.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TR.png -------------------------------------------------------------------------------- /example/www/flags/TT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TT.png -------------------------------------------------------------------------------- /example/www/flags/TV.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TV.png -------------------------------------------------------------------------------- /example/www/flags/TW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TW.png -------------------------------------------------------------------------------- /example/www/flags/TZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/TZ.png -------------------------------------------------------------------------------- /example/www/flags/UA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/UA.png -------------------------------------------------------------------------------- /example/www/flags/UG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/UG.png -------------------------------------------------------------------------------- /example/www/flags/UM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/UM.png -------------------------------------------------------------------------------- /example/www/flags/US.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/US.png -------------------------------------------------------------------------------- /example/www/flags/UY.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/UY.png -------------------------------------------------------------------------------- /example/www/flags/UZ.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/UZ.png -------------------------------------------------------------------------------- /example/www/flags/VA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VA.png -------------------------------------------------------------------------------- /example/www/flags/VC.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VC.png -------------------------------------------------------------------------------- /example/www/flags/VE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VE.png -------------------------------------------------------------------------------- /example/www/flags/VG.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VG.png -------------------------------------------------------------------------------- /example/www/flags/VI.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VI.png -------------------------------------------------------------------------------- /example/www/flags/VN.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VN.png -------------------------------------------------------------------------------- /example/www/flags/VU.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/VU.png -------------------------------------------------------------------------------- /example/www/flags/WF.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/WF.png -------------------------------------------------------------------------------- /example/www/flags/WS.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/WS.png -------------------------------------------------------------------------------- /example/www/flags/YE.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/YE.png -------------------------------------------------------------------------------- /example/www/flags/YT.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/YT.png -------------------------------------------------------------------------------- /example/www/flags/ZA.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ZA.png -------------------------------------------------------------------------------- /example/www/flags/ZM.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ZM.png -------------------------------------------------------------------------------- /example/www/flags/ZW.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/flags/ZW.png -------------------------------------------------------------------------------- /example/www/background.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/background.jpg -------------------------------------------------------------------------------- /example/www/bbc_flags.jpg: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/bbc_flags.jpg -------------------------------------------------------------------------------- /example/www/font/Amble-Regular-webfont.eot: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/font/Amble-Regular-webfont.eot -------------------------------------------------------------------------------- /example/www/font/Amble-Regular-webfont.ttf: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/font/Amble-Regular-webfont.ttf -------------------------------------------------------------------------------- /example/www/font/Amble-Regular-webfont.woff: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/tdewolff/push/HEAD/example/www/font/Amble-Regular-webfont.woff -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: go 2 | go: 3 | - tip 4 | before_install: 5 | - go get github.com/mattn/goveralls 6 | script: 7 | - goveralls -v -service travis-ci -repotoken $COVERALLS_TOKEN || go test -v ./... -------------------------------------------------------------------------------- /example/www/iframe.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | Push example iframe 9 | 10 | 11 | 12 | 13 | -------------------------------------------------------------------------------- /example/www/style.css: -------------------------------------------------------------------------------- 1 | @font-face { 2 | font-family: 'ambleregular'; 3 | src: url('font/Amble-Regular-webfont.eot'); 4 | src: url('font/Amble-Regular-webfont.eot?#iefix') format('embedded-opentype'), 5 | url('font/Amble-Regular-webfont.woff') format('woff'), 6 | url('font/Amble-Regular-webfont.ttf') format('truetype'), 7 | url('font/Amble-Regular-webfont.svg#ambleregular') format('svg'); 8 | font-weight: normal; 9 | font-style: normal; 10 | } 11 | 12 | body { 13 | font-family: "ambleregular"; 14 | margin:0; 15 | } 16 | 17 | #header { 18 | text-align: center; 19 | } 20 | 21 | h1 { 22 | margin:0; 23 | padding:4em 0; 24 | color:white; 25 | } 26 | 27 | #content { 28 | width:40em; 29 | margin:0 auto; 30 | } -------------------------------------------------------------------------------- /fileopener.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import ( 4 | "io" 5 | "os" 6 | "path" 7 | ) 8 | 9 | // FileOpener is an interface that allows the parser to load embedded resources recursively. 10 | type FileOpener interface { 11 | Open(string) (io.Reader, string, error) 12 | } 13 | 14 | type FileOpenerFunc func(string) (io.Reader, string, error) 15 | 16 | func (f FileOpenerFunc) Open(uri string) (io.Reader, string, error) { 17 | return f(uri) 18 | } 19 | 20 | //////////////// 21 | 22 | type DefaultFileOpener struct { 23 | basePath string 24 | } 25 | 26 | func NewDefaultFileOpener(basePath string) *DefaultFileOpener { 27 | return &DefaultFileOpener{basePath} 28 | } 29 | 30 | func (o *DefaultFileOpener) Open(uri string) (io.Reader, string, error) { 31 | r, err := os.Open(path.Join(o.basePath, uri)) 32 | if err != nil { 33 | return nil, "", err 34 | } 35 | return r, ExtToMimetype[path.Ext(uri)], nil 36 | } 37 | -------------------------------------------------------------------------------- /util_test.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "io/ioutil" 7 | "sort" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/tdewolff/test" 12 | ) 13 | 14 | func TestReader(t *testing.T) { 15 | var r io.Reader 16 | r = bytes.NewBufferString(``) 17 | 18 | parser, err := NewParser("example.com/", nil, URIHandlerFunc(func(uri string) error { 19 | test.String(t, uri, "/res") 20 | return nil 21 | })) 22 | test.Error(t, err, nil) 23 | 24 | r = Reader(r, parser, "text/html", "/request") 25 | _, err = io.Copy(ioutil.Discard, r) 26 | test.Error(t, err, nil) 27 | } 28 | 29 | func TestList(t *testing.T) { 30 | r := bytes.NewBufferString(` 31 | 32 | 33 | 34 | 35 | 36 | 37 | 38 | 39 | `) 40 | 41 | uris, err := List("example.com/", nil, r, "text/html", "/request") 42 | test.Error(t, err, nil) 43 | 44 | sort.Strings(uris) 45 | test.String(t, strings.Join(uris, ","), "/frame.html,/image.svg,/style.css") 46 | } 47 | -------------------------------------------------------------------------------- /LICENSE.md: -------------------------------------------------------------------------------- 1 | Copyright (c) 2015 Taco de Wolff 2 | 3 | Permission is hereby granted, free of charge, to any person 4 | obtaining a copy of this software and associated documentation 5 | files (the "Software"), to deal in the Software without 6 | restriction, including without limitation the rights to use, 7 | copy, modify, merge, publish, distribute, sublicense, and/or sell 8 | copies of the Software, and to permit persons to whom the 9 | Software is furnished to do so, subject to the following 10 | conditions: 11 | 12 | The above copyright notice and this permission notice shall be 13 | included in all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 16 | EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 17 | OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 18 | NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 19 | HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 20 | WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 21 | FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 22 | OTHER DEALINGS IN THE SOFTWARE. -------------------------------------------------------------------------------- /cache.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import "sync" 4 | 5 | // Cache is an interface that allows Middleware and ResponseWriter to cache the results of the list of resources to improve performance. 6 | type Cache interface { 7 | Get(string) ([]string, bool) 8 | Add(string, string) 9 | Del(string) 10 | } 11 | 12 | //////////////// 13 | 14 | type DefaultCache struct { 15 | uris map[string][]string 16 | mutex sync.RWMutex 17 | } 18 | 19 | func NewDefaultCache() *DefaultCache { 20 | return &DefaultCache{make(map[string][]string), sync.RWMutex{}} 21 | } 22 | 23 | func (c *DefaultCache) Get(uri string) ([]string, bool) { 24 | c.mutex.RLock() 25 | defer c.mutex.RUnlock() 26 | 27 | resources, ok := c.uris[uri] 28 | return resources, ok 29 | } 30 | 31 | func (c *DefaultCache) Add(uri string, resource string) { 32 | c.mutex.Lock() 33 | defer c.mutex.Unlock() 34 | 35 | if _, ok := c.uris[uri]; !ok { 36 | c.uris[uri] = []string{resource} 37 | return 38 | } 39 | c.uris[uri] = append(c.uris[uri], resource) 40 | } 41 | 42 | func (c *DefaultCache) Del(uri string) { 43 | c.mutex.Lock() 44 | defer c.mutex.Unlock() 45 | 46 | delete(c.uris, uri) 47 | } 48 | -------------------------------------------------------------------------------- /example/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "log" 5 | "net/http" 6 | "path" 7 | 8 | "github.com/pkg/profile" 9 | "github.com/tdewolff/push" 10 | ) 11 | 12 | func main() { 13 | defer profile.Start(profile.CPUProfile, profile.ProfilePath(".")).Stop() 14 | 15 | fileOpener := push.NewDefaultFileOpener("www") 16 | cache := push.NewDefaultCache() 17 | p := push.New("example.com/", fileOpener, cache) 18 | 19 | http.Handle("/", p.Middleware(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { 20 | //time.Sleep(50 * time.Millisecond) 21 | http.ServeFile(w, r, path.Join("www", r.URL.Path)) 22 | }))) 23 | 24 | // http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) { 25 | // time.Sleep(50 * time.Millisecond) 26 | 27 | // if pushWriter, err := push.ResponseWriter(w, r, "example.com/", fileOpener, cache); err == nil { 28 | // defer func() { 29 | // if err := pushWriter.Close(); err != nil { 30 | // log.Println(err, r.RequestURI) 31 | // } 32 | // }() 33 | // w = pushWriter 34 | // } else if err != push.ErrNoParser && err != push.ErrRecursivePush { 35 | // log.Println(err, r.RequestURI) 36 | // } 37 | 38 | // http.ServeFile(w, r, path.Join("www", r.URL.Path)) 39 | // }) 40 | 41 | go func() { 42 | log.Fatal(http.ListenAndServe(":80", nil)) 43 | }() 44 | log.Fatal(http.ListenAndServeTLS(":443", "localhost.crt", "localhost.key", nil)) 45 | } 46 | -------------------------------------------------------------------------------- /handler.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import ( 4 | "errors" 5 | "net/http" 6 | "sync" 7 | ) 8 | 9 | // ErrNoPusher is returned when the ResponseWriter does not implement the Pusher interface. 10 | var ErrNoPusher = errors.New("ResponseWriter is not a Pusher") 11 | 12 | // URIHandler is a callback definition that is called when a resource URI is found. 13 | type URIHandler interface { 14 | URI(string) error 15 | } 16 | 17 | type URIHandlerFunc func(string) error 18 | 19 | func (f URIHandlerFunc) URI(uri string) error { 20 | return f(uri) 21 | } 22 | 23 | //////////////// 24 | 25 | // PushHandler is a URIHandler that pushes resources to the client. 26 | type PushHandler struct { 27 | pusher http.Pusher 28 | opts *http.PushOptions 29 | } 30 | 31 | func NewPushHandler(pusher http.Pusher, opts *http.PushOptions) *PushHandler { 32 | if opts == nil { 33 | opts = &http.PushOptions{"", http.Header{}} 34 | } 35 | opts.Header.Set("X-Pushed", "1") 36 | return &PushHandler{pusher, opts} 37 | } 38 | 39 | func NewPushHandlerFromResponseWriter(w http.ResponseWriter) (*PushHandler, error) { 40 | pusher, ok := w.(http.Pusher) 41 | if !ok { 42 | return nil, ErrNoPusher 43 | } 44 | opts := &http.PushOptions{"", http.Header{}} 45 | opts.Header.Set("X-Pushed", "1") 46 | return &PushHandler{pusher, opts}, nil 47 | } 48 | 49 | func (p *PushHandler) URI(uri string) error { 50 | return p.pusher.Push(uri, p.opts) 51 | } 52 | 53 | //////////////// 54 | 55 | // ListHandler is a URIHandler that collects all resource URIs in a list. 56 | type ListHandler struct { 57 | URIs []string 58 | mutex sync.Mutex 59 | } 60 | 61 | func NewListHandler() *ListHandler { 62 | return &ListHandler{[]string{}, sync.Mutex{}} 63 | } 64 | 65 | func (h *ListHandler) URI(uri string) error { 66 | h.mutex.Lock() 67 | h.URIs = append(h.URIs, uri) 68 | h.mutex.Unlock() 69 | return nil 70 | } 71 | -------------------------------------------------------------------------------- /example/localhost.crt: -------------------------------------------------------------------------------- 1 | -----BEGIN CERTIFICATE----- 2 | MIIFTTCCAzWgAwIBAgIJAIDohVCCl44MMA0GCSqGSIb3DQEBBQUAME0xCzAJBgNV 3 | BAYTAk5MMRIwEAYDVQQIEwlHcm9uaW5nZW4xEjAQBgNVBAoTCUxvY2FsaG9zdDEW 4 | MBQGA1UEAxMNVGFjbyBkZSBXb2xmZjAeFw0xNjEyMTQxMzIxMjlaFw0yNjEyMTIx 5 | MzIxMjlaME0xCzAJBgNVBAYTAk5MMRIwEAYDVQQIEwlHcm9uaW5nZW4xEjAQBgNV 6 | BAoTCUxvY2FsaG9zdDEWMBQGA1UEAxMNVGFjbyBkZSBXb2xmZjCCAiIwDQYJKoZI 7 | hvcNAQEBBQADggIPADCCAgoCggIBAOrTdX1phxfh0XgiDhPpgmTirsqkxstS9JDq 8 | 2FUGpRclgll+bWNig0PpuXqkJD9dwnVYqDiIJ/ts8UV6XtJwrrOdufJ2vVRRBnDH 9 | WBptqRWqqVvPm/nIatm6cm4QERPiwaLpzkFzVyNmwCeIDHN01brII8edGCwW9eGN 10 | pJ97F4bwwQbRLVKvR54ofUH3/WHWQoFGUhpjbmUwfjYZ6nhcFCu5L9zMoVue37Dw 11 | lX8xn9R7BxTatVmRanTymcUykwAOJ8ksiWICU++TI0fQnZtLj2RxVDFrhdGi0HEl 12 | TlfHFTZ+OsaGn9iQxvDDK/q3gmsjwkLzwZOwf0UYnYN2VlbgAieryweuSyCB9hpy 13 | rebyAlAICmQBAeJyAfItECDfzb17Q0r9T3sid2GGQOpFVk7G2JRDKDdYopD/dgtc 14 | DYWueZ6QPUEriH6NCNxGapY2kueAsC85OM0MCMJnjFEwmLQq34XxNaSFZVdXPzA4 15 | QSV5YhPya0aSy/hXr4o8xhXewGNQFUGR2iIdJsFXA2pkF3BEbk0Xcl17eeb2eQcm 16 | jo/bNDQ1/GVVPmftTF2trE9Z5sG1QGKZliu+KCTSOk3/rwXvSxW8qp1vZZmhCXPI 17 | XdlqZaql3wcmboCOPiCt5VG2pKIxETyS0sDdtt35kWR2xiZkmbscZXzAb8IItUIy 18 | mwIFe9XXAgMBAAGjMDAuMAkGA1UdEwQCMAAwCwYDVR0PBAQDAgWgMBQGA1UdEQQN 19 | MAuCCWxvY2FsaG9zdDANBgkqhkiG9w0BAQUFAAOCAgEAe2ePi6nIVBoxVY3SBjPv 20 | 7JziTpZq2Zt0JT1V8xI1gVzxW/zjgg8c8x1CHAjhy5Ze7HuEeqO2Lemc+/U7Jf/F 21 | ZBXZN8KMQXQFYOR1RUQOykUD5kDKXQ3nEkb+Wlr2kV1FnnB1DiaCK5M+8x5WiMcw 22 | z9yDCgj+pPGjS1+nlGeNb4ht9XH3o4djacYm3h/ubJTU21Ms4cP2CIqYXSVs5vOw 23 | KusK0klPinG2vlN5OYPzuQtqYZqFWnCSFpwLmb1LT2XzXhnbIt7RI9dggvURLzVb 24 | OjuVz4TW/tvFdP3HWA5/9a0LcoDpP3gyqJX4goHhHjvKmy8TQdNXmiG+lIietjzZ 25 | ixnkX4PowK5DfetZT3/yQaAkJ+le0L73JZI8b3A2romSX/PQ/93X2jmIQpgDkNXf 26 | TOXMV0Nt22YyYC5Osm+5OuY7htRLveJ3dLy5fdQHz3HyOvdV2Hk2MVLu1H0g81ka 27 | Gqiom6CmTa4WhtRtBZVQEvFbKiP1Z4cALfpDpWqFVgpAPR2LQDTeHBVHNwNSYija 28 | TZKT7dmKuOnqN0US+OP9F9Qs5/G+8OBdRxxUBih19hMhSBrhiIlJx0aJ5xtzeSp8 29 | FIZgpN7SRk5gGx0RUm30k9FwC09KoQsc36udSWySIumdO5ugtENZyrK/RtzM/fUR 30 | 2g3z2n4WDTY7rmZKi+mQ/bE= 31 | -----END CERTIFICATE----- 32 | -------------------------------------------------------------------------------- /handler_test.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "net/http" 7 | "sort" 8 | "strings" 9 | "testing" 10 | 11 | "github.com/tdewolff/test" 12 | ) 13 | 14 | func TestListHandler(t *testing.T) { 15 | r := bytes.NewBufferString(` 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | `) 25 | 26 | listHandler := NewListHandler() 27 | parser, err := NewParser("example.com/", nil, listHandler) 28 | test.Error(t, err, nil) 29 | 30 | err = parser.Parse(r, "text/html", "/request") 31 | test.Error(t, err, nil) 32 | 33 | sort.Strings(listHandler.URIs) 34 | test.String(t, strings.Join(listHandler.URIs, ","), "/frame.html,/image.svg,/style.css") 35 | } 36 | 37 | func TestRecursiveHandler(t *testing.T) { 38 | r := bytes.NewBufferString(` 39 | 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | `) 48 | 49 | resources := map[string]struct { 50 | mimetype string 51 | content string 52 | }{ 53 | "/frame.html": {"text/html", ``}, 54 | "/style.css": {"text/css", `a { background-image: url("/background.jpg"); }`}, 55 | "/image.svg": {"image/svg+xml", ``}, 56 | } 57 | 58 | fileOpener := FileOpenerFunc(func(uri string) (io.Reader, string, error) { 59 | res := resources[uri] 60 | return bytes.NewBufferString(res.content), res.mimetype, nil 61 | }) 62 | listHandler := NewListHandler() 63 | parser, err := NewParser("example.com/", fileOpener, listHandler) 64 | test.Error(t, err, nil) 65 | 66 | err = parser.Parse(r, "text/html", "/request") 67 | test.Error(t, err, nil) 68 | 69 | sort.Strings(listHandler.URIs) 70 | test.String(t, strings.Join(listHandler.URIs, ","), "/background.jpg,/frame.html,/header.jpg,/image.svg,/img1.jpg,/img2.jpg,/style.css") 71 | } 72 | 73 | type TestPusher struct { 74 | *ListHandler 75 | } 76 | 77 | func (p *TestPusher) Push(uri string, _ *http.PushOptions) error { 78 | return p.URI(uri) 79 | } 80 | 81 | func TestPushHandler(t *testing.T) { 82 | r := bytes.NewBufferString(` 83 | 84 | 85 | 86 | 87 | 88 | 89 | 90 | 91 | `) 92 | 93 | testPusher := &TestPusher{NewListHandler()} 94 | pushHandler := NewPushHandler(testPusher, nil) 95 | parser, err := NewParser("example.com/", nil, pushHandler) 96 | test.Error(t, err, nil) 97 | 98 | err = parser.Parse(r, "text/html", "/request") 99 | test.Error(t, err, nil) 100 | 101 | sort.Strings(testPusher.URIs) 102 | test.String(t, strings.Join(testPusher.URIs, ","), "/frame.html,/image.svg,/style.css") 103 | } 104 | -------------------------------------------------------------------------------- /example/localhost.key: -------------------------------------------------------------------------------- 1 | -----BEGIN RSA PRIVATE KEY----- 2 | MIIJKAIBAAKCAgEA6tN1fWmHF+HReCIOE+mCZOKuyqTGy1L0kOrYVQalFyWCWX5t 3 | Y2KDQ+m5eqQkP13CdVioOIgn+2zxRXpe0nCus5258na9VFEGcMdYGm2pFaqpW8+b 4 | +chq2bpybhARE+LBounOQXNXI2bAJ4gMc3TVusgjx50YLBb14Y2kn3sXhvDBBtEt 5 | Uq9Hnih9Qff9YdZCgUZSGmNuZTB+NhnqeFwUK7kv3MyhW57fsPCVfzGf1HsHFNq1 6 | WZFqdPKZxTKTAA4nySyJYgJT75MjR9Cdm0uPZHFUMWuF0aLQcSVOV8cVNn46xoaf 7 | 2JDG8MMr+reCayPCQvPBk7B/RRidg3ZWVuACJ6vLB65LIIH2GnKt5vICUAgKZAEB 8 | 4nIB8i0QIN/NvXtDSv1PeyJ3YYZA6kVWTsbYlEMoN1iikP92C1wNha55npA9QSuI 9 | fo0I3EZqljaS54CwLzk4zQwIwmeMUTCYtCrfhfE1pIVlV1c/MDhBJXliE/JrRpLL 10 | +FevijzGFd7AY1AVQZHaIh0mwVcDamQXcERuTRdyXXt55vZ5ByaOj9s0NDX8ZVU+ 11 | Z+1MXa2sT1nmwbVAYpmWK74oJNI6Tf+vBe9LFbyqnW9lmaEJc8hd2WplqqXfByZu 12 | gI4+IK3lUbakojERPJLSwN223fmRZHbGJmSZuxxlfMBvwgi1QjKbAgV71dcCAwEA 13 | AQKCAgEAl/d41UxxrLbrBD+ltKUtSXSZgXLZY8OvmgkhLwU52ZzgmmIDEIo0QMME 14 | 0aVf/9IBgkd5tfwHQ+Lg0QG8U5uws3SjXZISPHqjHGElVxUYk3j6WPwmCKP24iiS 15 | 3T9wjdn1TiTY4epuve5E9FBLHnzBxDq5TPkRJ5dEUE+F9d+G/kDX6j18g0IDqwqw 16 | 5PxD8gjiyR5lC8bFLp8PTpu+7V1JgHI70zxqQAy03qETXlkTAkML9icDrY85wa0u 17 | bjuofiSrArnbvp2bDDPAZT1QgauIhIwC3GilFWG0W0S1SoD/7WALUWbWEyS+Whk0 18 | YPBZalSd5w4wfA+AjYq8hNMUVOxq91vPqYlyou65sAOTVykYkggz/DGvStiIF1Xz 19 | /aq9nAb2b4FfJrOiIzXFEQO7XpQZk1dIAHxY78cbF4XgZBl+ddgBA2bMYdVuaNut 20 | aSJWmzZy364CN+RTbv/p1YDJeuXjhNh1ClDVM+S9GB7KgdU54UBhV1XKhUxri/ka 21 | lAKrilk/ZibzEoIWULRI9WI3WMYm1eoNd3uyk6MjRFrUZTaofVZiXfq68gHlpgD/ 22 | p4rjZuy51WXu34QqBpzcVmun7IzeSOdQ/cUIyzQJBf6JYwgsZnYCGCaUMjXN6YU1 23 | CTr75DLuVQUf2zotC452eroscn23rKlWxgaDYx2VErID1VhO5KECggEBAP9Cw8fH 24 | AbXuI4wwKTg08OpK6uCZXmexv1Y0O7hHbAk8gYGrvCSOvN2vrCtu3NRmFWsoSioX 25 | hCoZeTjBRygDUYA/Gf6sml7lYzX3B0o+L9AHsBZIs4xtGBgxZyZlx9QmYOLbhXDQ 26 | jZsJu0UgNCDtpTCt+Hx91Nyh6oX0MTXYf1oTsdKQN2s6A22/HHBx0AVaY/AJxbDe 27 | M9SOngxzDj23qiZaCrzm5SxWjift7BCFZMQn3Qbi0kItWUSQUAT3Wqqx/lXzZ1LD 28 | d+1Mk7woJGq7qJ44L7ChzTjcpY4qMxd6epBUSUbOmYEh01B1uBz4UNUJRcyj5s1S 29 | M3MzqvSBzahsun0CggEBAOuBi4eCCqcQD3KBu4aqqFcy4S15LAk7s3d+aVOwSb1w 30 | FrickydJZUfeV5GC/d2JmtJUbqog1uUuzUj8v/l+S/YLdcP0P7lHlCQwBba1W2eo 31 | b3xbMP/dm15kUmYlVPuvcksQJrkHlsFYdeqKqoIhGKtdyurb2IszVakEqVq0rLbo 32 | MI6VKkiaau+0CIrbbNWkjsb04pU2kGckuL2hh65aWeys4ObzERoy64N9AJglEHPU 33 | 4ZyfRuxcdyb8R5IWPYEJqinina2H4rSCUD9+4NvvKjcdnh0j7a2BjGRt/RXf3kkB 34 | 26OU5URXAUWAWNUWvtP/8P7mppnxVtqCSg8yASD8reMCggEAfNT3zdFi4sftFnfP 35 | EK/DSbENoH0gj/F7MvskYYB8MyAl7XZA8lfjwT5SIoN691xdCSSQ8HjDp5sBj2Hm 36 | HIlS6DbzzXo3nETt+cwvAn3bAA9ia+Nt+zS23c37Nen8iaGjLA5S+dLkDXf631la 37 | ZOgTKvVJWghneuasPIopLr4Luc973Q+uKoAagSc/DzZ5lsSXryH4TgC8tCxy2n/B 38 | 7SjOyyaprav1U3OY3aobEhFKMCuWifGPBdILn947Y9JbwrJ9QSdh1jXFhoU2koPH 39 | G3NeiNHNcMIQDMjLJfU5OzgojEDL/Ra4N1CFeQm42mINlcGNIwDctHiItMQFzMFW 40 | BBH4OQKCAQBpQ40HM5PpWl9dMimMpsj5uM83URriwaGU/pa7hmdfWjN9rtaDT+YK 41 | OpJvgtpP5EqkSoLwXh9Pbxzoy7hPHyl6v2KTBKBbA2huyFw1b1h8u6ehMO104Cur 42 | BDJkX7ldie0PKhf0yjSTFSQXgoV2Bq8NIa4qTbu7dGWMV34PAgTU+HGDuZ6dtw+n 43 | NpQ+5Jb/4z7CJQEF6s6em6ZLdGC+CLp69EbOU8TILgxgyEW0u5RgAb4aEINV8Hp9 44 | nXOsE27IN3aspBMQVlV5k2mlB+QfygXXftCGe+GnlOkYlqTx2w9zGHaA5nOXmUAD 45 | Pbv2+uSuw46HkLbUxi+pGWVa52Hjya07AoIBAD3RebYmhQA+Eydt5GAA51BV5+EN 46 | 1rJRGHT07wOo8O17Yhm4vT5aLDXVL8onhDNp8PS/0F3yG0zJUWsH0rho2awz3VBp 47 | /VsUefDtAeoedszekASUjCQWAJmLAZerMKIWpGGdYkDWaB7bScUtzKMGZAyrtdjd 48 | bUc/tUEzFSjTkUbN9H+WtP+Xrww7SsvfmbDINFLUyC0NLX7GkKkwcscqh5XUcdRi 49 | F5andxZvMU5Nwq7PqNoRb4wUjX6cVEkLTUpyjCN/2OtCD/rA8joauBOGxBiK1uv4 50 | YRjXzZO+AKjaWIyA99MF2MdtSsun/Y5tVfdf+pPf29NywQxPx/RlrJomBWA= 51 | -----END RSA PRIVATE KEY----- 52 | -------------------------------------------------------------------------------- /parse_test.go: -------------------------------------------------------------------------------- 1 | package push 2 | 3 | import ( 4 | "bytes" 5 | "net/url" 6 | "testing" 7 | 8 | "github.com/tdewolff/test" 9 | ) 10 | 11 | func TestURLParser(t *testing.T) { 12 | urlParserTests := []struct { 13 | baseURL string 14 | uri string 15 | input string 16 | expected string 17 | }{ 18 | {"example.com/", "/index.html", "http://example.com/header.jpg", "/header.jpg"}, 19 | {"example.com/", "/index.html", "//example.com/header.jpg", "/header.jpg"}, 20 | {"example.com/", "/index.html", "/header.jpg", "/header.jpg"}, 21 | {"example.com/", "/index.html", "header.jpg", "/header.jpg"}, 22 | {"example.com", "/index.html", "header.jpg", "/header.jpg"}, 23 | {"www.example.com/", "/index.html", "http://example.com/header.jpg", ""}, 24 | {"example.com/dir/", "/index.html", "http://example.com/header.jpg", ""}, 25 | {"example.com/", "/dir/index.html", "http://example.com/header.jpg", "/header.jpg"}, 26 | {"example.com/", "/dir/index.html", "header.jpg", "/dir/header.jpg"}, 27 | {"/", "/index.html", "header.jpg", "/header.jpg"}, 28 | {"/dir/", "/index.html", "header.jpg", ""}, 29 | {"/dir/", "/dir/index.html", "header.jpg", "/dir/header.jpg"}, 30 | {"", "/index.html", "header.jpg", "/header.jpg"}, 31 | } 32 | 33 | for _, tt := range urlParserTests { 34 | uri := "" 35 | parser, err := NewParser(tt.baseURL, nil, URIHandlerFunc(func(_uri string) error { 36 | uri = _uri 37 | return nil 38 | })) 39 | test.Error(t, err, nil) 40 | 41 | reqURL, err := url.Parse(tt.uri) 42 | test.Error(t, err, nil) 43 | 44 | err = parser.parseURL(tt.input, reqURL) 45 | test.Error(t, err, nil) 46 | test.String(t, uri, tt.expected, tt.baseURL, tt.uri) 47 | } 48 | } 49 | 50 | func TestParsers(t *testing.T) { 51 | parserTests := []struct { 52 | mimetype string 53 | input string 54 | }{ 55 | {"text/html", ``}, 56 | {"text/html", ``}, 57 | {"text/html", ``}, 58 | {"text/html", ``}, 59 | {"text/html", ``}, 60 | {"text/html", ``}, 61 | {"text/html", `