Browser negeert Expires-header
Echter, de gegenereerde HTML van een van die pagina's bevat een verwijzing naar een PNG-image die elke twee minuten wordt ververst. De webserver geeft een Expires-header mee van "modification plus 110 seconds", maar de doorsnee browser (Chrome/Firefox) trekt zich daar niets van aan (verrassende uitzondering hierop is Edge) en laat vrolijk het oude plaatje zien.
De gemiddelde oplossing die ik tegenkom als ik met google ga zitten spelen is het helemaal uitzetten van de caching door een parameter met een timestamp mee te geven, maar dat is nou juist iets waar ik vanaf wil. Zo moeilijk moet het toch niet zijn voor een browser om zich aan een Expires-header te houden?
Is er hier iemand die dit probleem herkent, of misschien zelfs tips heeft om het op te lossen? ;-)
Willem, post eens alle HTTP-headers van de PNG?
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
Request headers:
GET /dynamic/plaatje.png HTTP/1.1
Host: img.xxx.nl
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en-GB;q=0.8,en-CA;q=0.7,en;q=0.5,nl;q=0.3,nl-BE;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Cookie: [meuk gewist]
Connection: keep-alive
Response headers:
HTTP/1.1 200 OK
Date: Fri, 11 Sep 2015 09:43:35 GMT
Server: Apache
Last-Modified: Fri, 11 Sep 2015 09:42:18 GMT
Etag: "5a2802-321e0-51f75881db16a"
Accept-Ranges: bytes
Content-Length: 205280
Cache-Control: max-age=33
Expires: Fri, 11 Sep 2015 09:44:08 GMT
Access-Control-Allow-Origin: *
Connection: close
Content-Type: image/png
GET /dynamic/plaatje.png HTTP/1.1
Host: img.xxx.nl
User-Agent: Mozilla/5.0 (Windows NT 10.0; WOW64; rv:40.0) Gecko/20100101 Firefox/40.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-US,en-GB;q=0.8,en-CA;q=0.7,en;q=0.5,nl;q=0.3,nl-BE;q=0.2
Accept-Encoding: gzip, deflate
DNT: 1
Cookie: [meuk gewist]
Connection: keep-alive
Response headers:
HTTP/1.1 200 OK
Date: Fri, 11 Sep 2015 09:43:35 GMT
Server: Apache
Last-Modified: Fri, 11 Sep 2015 09:42:18 GMT
Etag: "5a2802-321e0-51f75881db16a"
Accept-Ranges: bytes
Content-Length: 205280
Cache-Control: max-age=33
Expires: Fri, 11 Sep 2015 09:44:08 GMT
Access-Control-Allow-Origin: *
Connection: close
Content-Type: image/png
no-cache maakt geen verschil, het plaatje blijft gecachet worden.
Je zou een "hack" kunnen proberen. Wellicht niet helemaal mooi, maar wel functioneel.
Je kunt een paramater aan je plaatje meegeven. Je browser zal dan denken dat het om een ander plaatje gaat en het plaatje opnieuw binnenhalen. Als parameter kun je dan de huidige timestamp gebruiken:
plaatje.jpg?time=1441978086
Willem vp op 11/09/2015 01:16:04:
De gemiddelde oplossing die ik tegenkom als ik met google ga zitten spelen is het helemaal uitzetten van de caching door een parameter met een timestamp mee te geven, maar dat is nou juist iets waar ik vanaf wil.
Ik denk inmiddels alleen wel dat het hierop uitdraait. Laat die random URL-parameter bijvoorbeeld genereren door JavaScript met een timer.
Zo werkt het nu ook, maar eigenlijk wil ik daar vanaf. Het plaatje wordt elke 24 seconden getoond; dat betekent dat in de twee minuten die het 'leeft', het 4 of 5 keer wordt opgevraagd. Het zou mooi zijn als dat 3 of 4 keer vanuit de cache zou kunnen, aangezien dat heel wat belasting op de server zou schelen.
Daarnaast kan het zijn dat e.e.a. bekeken wordt via een trage verbinding. De pagina met het plaatje wordt 16 seconden getoond (en daarna komt 8 seconden de andere pagina in beeld). Als de verbinding traag is, kan het dus gebeuren dat het plaatje te kort in beeld staat om te bekijken. Wanneer de caching goed zou werken komt dit hoogstens 1x per 2 minuten voor; de andere keren wordt het plaatje dan uit de cache getoond.
In ieder geval bedankt voor het meedenken (Ward ook, natuurlijk ;-) ) en als iemand nog met een lumineuze ingeving komt, hou ik me aanbevolen.
Kun je dat niet met de servertijd oplossen? Dus die parameter ?time=1441978086 pas vernieuwen op het moment dat de actuele timestamp meer dan 2 minuten groter is dan de laatste timestamp?
Dus gedurende de 1e 2 minuten gebruik je telkens ?time=1441978086 en pas na 2 minuten vervang je die parameter dan. Is dat een optie?
Hmm, daar breng je me op een idee... Het mooiste zou zelfs zijn om als timestamp de modtime van het plaatje te gebruiken. Die staat weliswaar op een andere server, maar daar moet iets op te vinden zijn.
Intussen ben ik zelf ook weer een stapje verder. Ik heb nog wat zitten experimenteren met de HTML-code.
Oude situatie (vereenvoudigd):
(Het script wordt generiek gebruikt en afhankelijk van de website is het plaatje anders, vandaar de $url.)
Dit werkt goed in Edge, maar niet in Chrome en Firefox (andere browsers heb ik niet geprobeerd). Elk kwartier wordt de hoofdpagina gerefresht door middel van een <meta> tag; dan wordt bij Chrome en Firefox het plaatje wél bijgewerkt.
Nieuwe situatie (vereenvoudigd):
Dit werkt goed in Edge en Safari (iPhone 6, alhoewel de pagina niet is ontworpen voor mobiel gebruik). In Chrome lijkt het te werken, alhoewel het plaatje net een tijd stopte met verversen; mogelijk na de <meta> refresh van de hoofdpagina. In Firefox nog steeds geen verandering.
Ik ga toch eens kijken of ik iets met de modtime van het plaatje kan doen. Als het niet kan zoals het moet...
Als je goed naar de response headers kijkt zie je dat de Max-Age op 33 staat, wat inhoudt dat er geen validatie tegen de server gedaan hoeft te worden "gedurende 33 seconden vanaf de request". Het is aan te raden om te kijken wat meerdere opvolgende requests teruggeven als Max-Age. Als je niet wilt dat er caching plaatsvindt of de cache met enige regelmaat wilt laten verversen moet je de controle krijgen over deze header.
De max-age klopt; die is bij elke call het verschil tussen de tijden in de Expires en Date headers.
Als je expires inderdaad iedere request verandert kun je ook niet spreken van van negeren, dan is het gedrag dus correct. Je bent vermoedelijk beter af met het gebruiken van ETags gebaseerd op de bestandsinhoud, en de expires header gewoon te laten zitten. ETags zijn gemaakt om direct op veranderende content in te kunnen spelen.
Dat heb je mij niet horen zeggen. De Expires verandert elke keer als het bestand wijzigt. Wat wel elke request verandert is de max-age, want dat is feitelijk het verschil tussen Date en Expires (en Date wijzigt wel bij elke request).
Het probleem hier is dat Firefox (en in zekere mate ook Chrome) het bestand uit de cache blijft halen als het tijdstip dat in de Expires-header staat gepasseerd is. En m.i. is dat zeker geen correct gedrag.
Overigens wordt ook een Etag-header meegestuurd die net zo vrolijk genegeerd wordt... ;-(
Gewijzigd op 11/09/2015 22:19:41 door Willem vp
HTML5 History API. De "photo swap" die hier wordt beschreven, lijkt op wat je wilt bereiken.
Dat is inderdaad geen correct gedrag, maar gelukkig hebben we nu de Die photo swap is exact hoe mijn pagina in elkaar zit ;-) maar dan zonder het aanpassen van de URL. Die History API kende ik nog niet, ga ik onthouden.