Für ein Hobbyprojekt wurde eine Wetterprognose auf Basis der Openweathermap-API erstellt.
Die von der API gelieferten Informationen werden serverseitig für die Zeit $maxCacheTime in einer Cache-Datei gespeichert.
Erst wenn die Cache-Datei älter als $maxCacheTime ist, wird die API erneut angesprochen. Soweit zum Hintergrund.
Die Idee ist jetzt, per PHP-Header den Browsercache soweit zu bringen, bis zum erneuten Ansprechen der API die Informationen komplett aus dem Cache zu holen.
Dazu nutze ich aktuell folgenden Code:
Last-Modified wird auf die Zeit der letzten Änderung des Cachefiles gesetzt.
Die dafür genutzte Klasse dt ist eine Erweiterung für DateTime. Ich hoffe,
es ist auch ohne große Klassenbeschreibung ersichtlich was gemacht wird.
Anmerkung zu Last-Modified:
Im Web kursiert viel folgender Code (z.B. hier)
Da PHP überwiegend dynamischen Content erzeugt, führen die obigen Zeilen dazu das der Nutzer fast immer alten Inhalt zu sehen bekommt,
da getlastmod() die Zeit der letzten Änderung des auseführten Skripts liefert! (Bin auch darauf reingefallen ).
Expires wird auf die frühest mögliche Zeit gesetzt zu der die API erneut angesprochen wird und max-age wird auf die Sekundenzahl bis zu Expires gesetzt.
Dies funktioniert soweit ganz gut.
Beim ersten Zugriff liefert html bei einem API-zugriff ein Status 200 (Ok) mit Zeiten von 0,5..1,5 Sekunden, ohne API-Zugriff bei 0,4 Sekunden.
Die folgenden Zugriffe mit Status 304 (not Modified) liegen dann unter 0,2 Sekunden.
Nun endlich zum Problem:
Den obigen Code wollte ich erweitern mit einem sog. ETag-Header:
Wenn die Wetter-API erneut angesprochen wird, müssen nicht unbedingt neue Informationen vorliegen.
Der ETag sollte dafür sorgen, daß nur bei echt neuen Informationen diese geholt werden.
Die Wirkung vom ETag ist jedoch nicht wie erhofft. Bei einem konstanten ETag wird mit jeder Anfrage der Server angesprochen, der jedesmal mit 200 (Ok) bei Zeiten von 0,4 Sekunden antwortet.
Hab ich nun noch ein Verständnisproblem zum ETag oder liege ich mit meiner obigen Variante schon richtig?
LG jspit
Die von der API gelieferten Informationen werden serverseitig für die Zeit $maxCacheTime in einer Cache-Datei gespeichert.
Erst wenn die Cache-Datei älter als $maxCacheTime ist, wird die API erneut angesprochen. Soweit zum Hintergrund.
Die Idee ist jetzt, per PHP-Header den Browsercache soweit zu bringen, bis zum erneuten Ansprechen der API die Informationen komplett aus dem Cache zu holen.
Dazu nutze ich aktuell folgenden Code:
PHP-Code:
$lastModify = dt::create($cacheFileTimeStamp,'GMT');
$expires = dt::create($lastModify)->modify($maxCacheTime);
$maxAgeSec = Max(dt::create('now')->diff_total($expires,'Sec'), 0);
header("Last-Modified: " . $lastModify->format('D, d M Y H:i:s','en') .' GMT');
header('Expires: ' . $expires->format('D, d M Y H:i:s','en') . ' GMT');
header("Cache-Control: public, max-age=" . $maxAgeSec);
Die dafür genutzte Klasse dt ist eine Erweiterung für DateTime. Ich hoffe,
es ist auch ohne große Klassenbeschreibung ersichtlich was gemacht wird.
Anmerkung zu Last-Modified:
Im Web kursiert viel folgender Code (z.B. hier)
PHP-Code:
$mod_gmt = gmdate("D, d M Y H:i:s", getlastmod()) ." GMT";
header("Last-Modified: " . $mod_gmt);
da getlastmod() die Zeit der letzten Änderung des auseführten Skripts liefert! (Bin auch darauf reingefallen ).
Expires wird auf die frühest mögliche Zeit gesetzt zu der die API erneut angesprochen wird und max-age wird auf die Sekundenzahl bis zu Expires gesetzt.
Dies funktioniert soweit ganz gut.
Beim ersten Zugriff liefert html bei einem API-zugriff ein Status 200 (Ok) mit Zeiten von 0,5..1,5 Sekunden, ohne API-Zugriff bei 0,4 Sekunden.
Die folgenden Zugriffe mit Status 304 (not Modified) liegen dann unter 0,2 Sekunden.
Nun endlich zum Problem:
Den obigen Code wollte ich erweitern mit einem sog. ETag-Header:
PHP-Code:
header('ETag: "' . md5($htmlContent) . '"');
Der ETag sollte dafür sorgen, daß nur bei echt neuen Informationen diese geholt werden.
Die Wirkung vom ETag ist jedoch nicht wie erhofft. Bei einem konstanten ETag wird mit jeder Anfrage der Server angesprochen, der jedesmal mit 200 (Ok) bei Zeiten von 0,4 Sekunden antwortet.
Hab ich nun noch ein Verständnisproblem zum ETag oder liege ich mit meiner obigen Variante schon richtig?
LG jspit
Kommentar