/* Ċ Ġ* ĠĠ ĠThe ĠMIT ĠLicense Ġ( MIT ) Ċ Ġ* Ċ Ġ* ĠĠ ĠCopyright Ġ( c ) Ġ 2 0 1 5 ĠShop ify ĠInc . Ċ Ġ* Ċ Ġ* ĠĠ ĠPermission Ġis Ġhereby Ġgranted , Ġfree Ġof Ġcharge , Ġto Ġany Ġperson Ġobtaining Ġa Ġcopy Ċ Ġ* ĠĠ Ġof Ġthis Ġsoftware Ġand Ġassociated Ġdocumentation Ġfiles Ġ( the Ġ" Software "), Ġto Ġdeal Ċ Ġ* ĠĠ Ġin Ġthe ĠSoftware Ġwithout Ġrestriction , Ġincluding Ġwithout Ġlimitation Ġthe Ġrights Ċ Ġ* ĠĠ Ġto Ġuse , Ġcopy , Ġmodify , Ġmerge , Ġpublish , Ġdistribute , Ġsublicense , Ġand / or Ġsell Ċ Ġ* ĠĠ Ġcopies Ġof Ġthe ĠSoftware , Ġand Ġto Ġpermit Ġpersons Ġto Ġwhom Ġthe ĠSoftware Ġis Ċ Ġ* ĠĠ Ġfurnished Ġto Ġdo Ġso , Ġsubject Ġto Ġthe Ġfollowing Ġconditions : Ċ Ġ* Ċ Ġ* ĠĠ ĠThe Ġabove Ġcopyright Ġnotice Ġand Ġthis Ġpermission Ġnotice Ġshall Ġbe Ġincluded Ġin Ċ Ġ* ĠĠ Ġall Ġcopies Ġor Ġsubstantial Ġportions Ġof Ġthe ĠSoftware . Ċ Ġ* Ċ Ġ* ĠĠ ĠTHE ĠSOFTWARE ĠIS ĠPROVIDED Ġ" AS ĠIS ", ĠWITHOUT ĠWARRANTY ĠOF ĠANY ĠKIND , ĠEXPRESS ĠOR Ċ Ġ* ĠĠ ĠIMPLIED , ĠINCLUDING ĠBUT ĠNOT ĠLIMITED ĠTO ĠTHE ĠWARRANTIES ĠOF ĠMERCHANTABILITY , Ċ Ġ* ĠĠ ĠFITNESS ĠFOR ĠA ĠPARTICULAR ĠPURPOSE ĠAND ĠNONINFRINGEMENT . ĠIN ĠNO ĠEVENT ĠSHALL ĠTHE Ċ Ġ* ĠĠ ĠAUTHORS ĠOR ĠCOPYRIGHT ĠHOLDERS ĠBE ĠLIABLE ĠFOR ĠANY ĠCLAIM , ĠDAMAGES ĠOR ĠOTHER Ċ Ġ* ĠĠ ĠLIABILITY , ĠWHETHER ĠIN ĠAN ĠACTION ĠOF ĠCONTRACT , ĠTORT ĠOR ĠOTHERWISE , ĠARISING ĠFROM , Ċ Ġ* ĠĠ ĠOUT ĠOF ĠOR ĠIN ĠCONNECTION ĠWITH ĠTHE ĠSOFTWARE ĠOR ĠTHE ĠUSE ĠOR ĠOTHER ĠDEALINGS ĠIN Ċ Ġ* ĠĠ ĠTHE ĠSOFTWARE . Ċ Ġ*/ Ċ package Ġcom . shop ify . buy 3 . internal . cache Ċ Ċ import Ġokhttp 3 . Interceptor Ċ import Ġokhttp 3 . Request Ċ import Ġokhttp 3 . Response Ċ import Ġtim ber . log . Tim ber Ċ import Ġjava . io . IOException Ċ Ċ internal Ġclass ĠHttp Cache Interceptor ( private Ġval Ġcache : ĠHttp Cache ) Ġ: ĠInter ceptor Ġ{ ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġoverride Ġfun Ġintercept ( chain : ĠInter ceptor . Chain ): ĠResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġrequest Ġ= Ġchain . request () ĊĠĠĠĠĠĠĠ Ġreturn Ġwhen Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest . should Skip Cache Ġ-> Ġchain . proceed ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest . should Skip Network Ġ-> Ġcache Only Response ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġrequest . is Network First Ġ-> Ġnetwork First ( request , Ġchain ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġelse Ġ-> Ġcache First ( request , Ġchain ) ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġcache Only Response ( request : ĠRequest ): ĠResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Response Ġ= Ġcached Response ( request ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cache Response Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog Cache Miss ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġrequest . uns atisf iable Cache Request ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlog Cache Hit ( request ) ĊĠĠĠĠĠĠĠ Ġreturn Ġcache Response . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. cache Response ( cache Response . strip ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġnetwork First ( request : ĠRequest , Ġchain : ĠInter ceptor . Chain ): ĠResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġnetwork Response Ġ= Ġchain . proceed ( request ). with Ser ved Date Header () ĊĠĠĠĠĠĠĠ Ġif Ġ( network Response . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcache Key Ġ= Ġrequest . header ( HTTP _ CACHE _ KEY _ HEADER ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcache . proxy Response ( network Response , Ġcache Key ) ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcache Response Ġ= Ġcached Response ( request ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cache Response Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog Cache Miss ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnetwork Response ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlog Cache Hit ( request ) ĊĠĠĠĠĠĠĠ Ġreturn Ġcache Response . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. cache Response ( cache Response . strip ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. network Response ( network Response . strip ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. request ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġ@ Throws ( IOException :: class ) ĊĠĠĠ Ġprivate Ġfun Ġcache First ( request : ĠRequest , Ġchain : ĠInter ceptor . Chain ): ĠResponse Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Response Ġ= Ġcached Response ( request ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cache Response Ġ== Ġnull ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġlog Cache Miss ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġnetwork Response Ġ= Ġchain . proceed ( request ). with Ser ved Date Header () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġif Ġ( network Response . is Successful ) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġval Ġcache Key Ġ= Ġrequest . header ( HTTP _ CACHE _ KEY _ HEADER ) ĊĠĠĠĠĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġcache . proxy Response ( network Response , Ġcache Key ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnetwork Response ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġlog Cache Hit ( request ) ĊĠĠĠĠĠĠĠ Ġreturn Ġcache Response . newBuilder () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. cache Response ( cache Response . strip ()) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. request ( request ) ĊĠĠĠĠĠĠĠĠĠĠĠ Ġ. build () ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġcached Response ( request : ĠRequest ): ĠResponse ? Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Key Ġ= Ġrequest . header ( HTTP _ CACHE _ KEY _ HEADER ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cacheKey Ġ== Ġnull Ġ|| Ġcache Key . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġval Ġcached Response Ġ= Ġcache . read ( cacheKey ) Ġ?: Ġreturn Ġnull ĊĊĠĠĠĠĠĠĠ Ġif Ġ( is St ale ( request , Ġcached Response )) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġcached Response . close Quiet ly () ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn Ġnull ĊĠĠĠĠĠĠĠ Ġ} ĊĊĠĠĠĠĠĠĠ Ġreturn Ġcached Response ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġlog Cache Hit ( request : ĠRequest ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Key Ġ= Ġrequest . header ( HTTP _ CACHE _ KEY _ HEADER ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cacheKey Ġ== Ġnull Ġ|| Ġcache Key . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠTim ber . d (" cache ĠH IT Ġfor Ġkey : Ġ% s ", Ġcache Key ) ĊĠĠĠ Ġ} ĊĊĠĠĠ Ġprivate Ġfun Ġlog Cache Miss ( request : ĠRequest ) Ġ{ ĊĠĠĠĠĠĠĠ Ġval Ġcache Key Ġ= Ġrequest . header ( HTTP _ CACHE _ KEY _ HEADER ) ĊĠĠĠĠĠĠĠ Ġif Ġ( cacheKey Ġ== Ġnull Ġ|| Ġcache Key . isEmpty ()) Ġ{ ĊĠĠĠĠĠĠĠĠĠĠĠ Ġreturn ĊĠĠĠĠĠĠĠ Ġ} ĊĠĠĠĠĠĠĠ ĠTim ber . d (" cache ĠM ISS Ġfor Ġkey : Ġ% s ", Ġcache Key ) ĊĠĠĠ Ġ} Ċ }