Apache liefert keine 304-Antworten „Nicht geändert“ für statische Dateien

Apache liefert keine 304-Antworten „Nicht geändert“ für statische Dateien

Ich betreibe einen Apache-Webserver, der große statische Bilder aus dem Dateisystem bereitstellt. Ich habe den Server so konfiguriert, dass er einen gültigen Cache-Header zurückgibt, und zwar wie folgt:Header merge Cache-Control "public, max-age=31536000, immutable"

Das ist alles schön und gut, aber wenn der Benutzer das Bild im Browser neu lädt, gibt Apache nie eine 304 Not ModifiedAntwort zurück.

Ich habe diesen Curl-Befehl ausgeführt (ich habe den Hostnamen aus Vertraulichkeitsgründen geändert):

curl -o /tmp/image.png -v -u test:example http://blah.example.com/static/images/covers/436g2gu94kxin4x7

Hier sind die Anforderungsheader von curl.

GET /static/images/covers/436g2gu94kxin4x7 HTTP/1.1
Host: blah.example.com
Authorization: Basic dGVzdDpleGFtcGxl
User-Agent: curl/7.64.1
Accept: */*
If-Modified-Since: Thu, 30 Apr 2020 02:21:47 GMT

Ich habe eine 304-Antwort erwartet, stattdessen bekam ich:

HTTP/1.1 200 OK
Date: Fri, 28 Aug 2020 04:59:54 GMT
Server: Apache/2.4.25 (Debian)
Content-Type: image/png
Content-Length: 3115720
Last-Modified: Thu, 30 Apr 2020 02:21:47 GMT
Vary: Accept-Encoding
Cache-Control: public, max-age=31536000, immutable

Ich habe gelesenApache-Caching-Handbuch, aber nichts davon scheint für diese Situation relevant zu sein. Es geht ausschließlich darum, den Apache-Cache entweder im Speicher oder auf der Festplatte zu konfigurieren, insbesondere um Fälle zu unterstützen, in denen Apache als Reverse-Proxy für einen Ursprungsserver fungiert.

Aber in diesem Fall liegen die Dateien bereits auf der lokalen Festplatte. Es gibt keinen Ursprungsserver. Ich möchte/brauche nicht, dass Apache eine separate „gespeicherte“ Kopie der Datei speichert. Ich möchte nur, dass Apache erkennt, dass das Last-ModifiedDatum der Datei auf der Festplatte mit dem Datum übereinstimmt, und in diesem Fall If-Modified-Sincezurückkehrt .304 Not Modified

Wie richte ich das ein? Muss ich Apache dazu veranlassen, eine eigene separate zwischengespeicherte Kopie der Dateien zu speichern, um bedingte GETs zu ermöglichen? (Das wird ein sehr großer Cache sein, der vermutlich auf der Festplatte gespeichert wird, was reine Verschwendung ist.)

Antwort1

Erstens: Ist es wirklich kein Caching?

Möglicherweise ist curl Ihr Problem. Ich habe Ihren Code auf einer URL ausprobiert, von der ich weiß, dass sie 304 zurückgibt, und mit Ihrem obigen Code gibt sie immer 200 zurück. Haben Sie die Entwicklertools eines Webbrowsers ausprobiert? Solange „Caching deaktivieren“ nicht aktiviert ist, sollten Sie Ihre URL aktualisieren können und sehen, dass sie beim zweiten Aktualisieren 304 zurückgibt.

Zweitens könnte es ein Apache-Fehler sein

Ich sehe in Ihren Ergebnissen keinen ETag-Header. Vorausgesetzt, Apache fügt dies wirklich nicht hinzu, können Sie dies wahrscheinlich ignorieren. Sie können dies aber trotzdem versuchen, nur für den Fall zu Ihren Apache-Einstellungen hinzuzufügen:

<IfModule mod_headers.c>
    Header unset ETag
</IfModule>
FileETag None

(Aktivieren Sie unbedingt den Header-Mod mit a2enmod headers.)

Oder noch besser: Wenn Sie Apache Version 2.4.42 oder höher () verwenden apache2 -v, können Sie stattdessen Folgendes in Ihren Einstellungen versuchen:

<IfModule mod_deflate.c>
    DeflateAlterETag NoChange
</IfModule>

Dieses Problem wurde dadurch verursacht, dass das Deflate-Modul die Komprimierungsmethode am Ende des ETag hinzufügte. Dies führte dazu, dass Apache das Caching ignorierte und immer 200 zurückgab. In ihren eigenen Worten lautete dies:

...verhindert die Bereitstellung von „HTTP Not Modified“-Antworten (304) auf bedingte Anforderungen für komprimierte Inhalte.

Apache-Modul mod_deflate

Durch das Deaktivieren können einige Caching-Probleme behoben werden.

verwandte Informationen