Wie füge ich allen 404 Seiten, die von Apache und Nginx bereitgestellt werden, Header ohne Cache hinzu?

9

Nach dem Wechsel zu Cloudflare ist kürzlich ein Problem aufgetreten. Die Lösung besteht darin, Cloudflare grundsätzlich daran zu hindern, 404 Antworten zwischenzuspeichern.

In unserem Multi-Server-Setup mit Lastenausgleich treten gelegentlich 404s auf, die jedoch schnell durch rsync (über lsyncd) behoben werden. Vor Cloudflare würde eine erneute Anforderung an die 404ed-Datei sehr schnell 200 werden, wenn rsync seine Arbeit erledigt.

Da Cloudflare jedoch alle Daten basierend auf dem Caching-Header zwischenspeichert und weder Apache noch Nginx einen No-Cache-Header für 404s senden, speichert Cloudflare die 404-Antwort für eine Weile zwischen.

Ich habe nach einer Lösung gesucht, um einen solchen Header für 404s sowohl in Apache als auch in Nginx global hinzuzufügen (global für alle gehosteten Domains), bin aber bisher leer geblieben.

Kann jemand helfen?

Vielen Dank.

Artem Russakovskii
quelle
Ähnliche Frage, allerdings nur für Apache (auch noch unbeantwortet): serverfault.com/questions/331544/… .
Artem Russakovskii
Bisher bin ich mir ziemlich sicher, dass Sie Header, die standardmäßig von 404-Handlern in Apache und Nginx zurückgegeben werden, nicht überschreiben können (bitte beweisen Sie, dass ich falsch liege!). Ich konnte den 404-Handler überschreiben und auf eine PHP-Datei verweisen, die solche Header in Apache sendet, aber da nginx in meinem Setup keine PHP-Unterstützung hat und die Einstellung "expires -1;" auf dem 404-standort schien eigentlich nichts zu tun, ich bin immer noch ratlos, wie man das in nginx macht.
Artem Russakovskii

Antworten:

6

Können Sie mit der Verwendung einer error_page-Direktive nicht auskommen und dann den Speicherort mit dem hinzugefügten Header separat behandeln?

zB in Nginx:

    server {
      ...
      error_page 404 /404.html;
      location = /404.html {
        root   /usr/share/nginx/html;
        add_header Cache-Control "no-cache" always;
      }
    }
jimmiw
quelle
1
Hier gibt es zwei Probleme, aber das ist die Richtung, in die ich gegangen bin. 1. Ich wollte die Standard-404-Seite nicht überschreiben und musste in jeder Seite Regeln erstellen, listenda locationdies im Inneren nicht httpdirekt unterstützt wird . 2. Noch wichtiger ist, dass Ihr Snippet tatsächlich nicht funktioniert, da add_header nur für 20X und 30X gilt ( nginx.org/en/docs/http/ngx_http_headers_module.html ). Wir haben jedoch Glück, da Sie ab der kürzlich veröffentlichten Version 1.7.5 jetzt einen alwaysModifikator hinzufügen können, der ihn auf alle Antwortcodes anwendet. Ich musste Nginx upgraden, aber es war ein guter Tritt in den Hintern. Es klappt.
Artem Russakovskii
2
Ich habe meine Antwort aktualisiert. Sie sollten vielleicht eine Antwort hinzufügen, aus der hervorgeht, was Sie zur Lösung der Frage getan haben.
Jimmy
Sieht so aus, als würde das Weglassen auch rootfunktionieren. Wenn das entfernt wird, ist es ziemlich genau das, was ich für Nginx getan habe.
Artem Russakovskii
Für Apache habe ich beschlossen, dass ich tatsächlich eine benutzerdefinierte Seite verwenden möchte, also habe ich Folgendes getan: ErrorDocument 404 /path/to/my/404.php. Und dann habe ich in der 404.php <? Php // den 404-Header nicht zwischengespeichert ("Cache-Control: kein Cache, muss erneut validiert werden"); // HTTP / 1.1-Header ("Läuft ab: Sa, 26. Juli 1997, 05:00:00 GMT"); // Datum in der Vergangenheit?>
Artem Russakovskii
Ich markiere Ihre Antwort als akzeptiert. Wenn jemand später eine allgemeinere Apache-Antwort oder eine serverNginx- Antwort geben möchte, die global und nicht per funktioniert , kann er upvoted werden.
Artem Russakovskii
5

Sie können es auch so machen:

map $status $cache_header {
    default <for_other_codes>;
    404     "no-cache";
}


server {

    [ ... ]

    add_header "Cache-Control" $cache_header always;

}
Xavier Lucas
quelle
Klug. Ich werde wahrscheinlich mit der anderen Lösung gehen, da sie bereits funktioniert und nicht jedes Mal ein Standard-Cache-Control-Header angegeben werden muss, aber dies war ein Umdenken.
Artem Russakovskii
404 "no-cache"Nachher fehlt ein Semikolon, aber die blöde Einschränkung für die Bearbeitung von mindestens 6 Zeichen durch stackexchange hindert mich daran, es zu beheben. Offensichtlich keine gute Einschränkung für eine Site, bei der es nur um Codierung und Konfiguration geht ...
nh2
3

In Apache 2.4 können Sie Folgendes ausprobieren:

FileETag None
<IfModule mod_headers.c>
    Header always unset ETag "expr=%{REQUEST_STATUS} == 404"
    Header always set Cache-Control "max-age=0, no-cache, no-store, must-revalidate" "expr=%{REQUEST_STATUS} == 404"
    Header always set Pragma "no-cache" "expr=%{REQUEST_STATUS} == 404"
    Header always set Expires "Wed, 11 Jan 1984 05:00:00 GMT" "expr=%{REQUEST_STATUS} == 404"
</IfModule>

Das alwaysist wichtig, weil dies ein:

Sie fügen einer lokal generierten nicht erfolgreichen (nicht 2xx) Antwort, z. B. einer Umleitung, einen Header hinzu. In diesem Fall wird nur die Tabelle verwendet, die immer der endgültigen Antwort entspricht.

Sie sagten alle 404er, aber als vollständige Referenz könnte es natürlich sinnvoll sein, dies in ein <FilesMatch>oder <LocationMatch>einzuhalten, um den Umfang einzuschränken .

Ich glaube, dies ist eine neue Funktion in Apache 2.4, da die Verwendung von exprBedingungen nicht in der Version 2.2 der Dokumentation zu mod_headers enthalten ist.

curl -I [foo] Test ohne diese Konfiguration:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:29 GMT
Server: Apache/2.4.18 (Ubuntu)
Content-Type: text/html; charset=iso-8859-1

curl -I [foo] Test mit dieser Konfiguration:

HTTP/1.1 404 Not Found
Date: Thu, 24 May 2018 17:44:42 GMT
Server: Apache/2.4.18 (Ubuntu)
Cache-Control: max-age=0, no-cache, no-store, must-revalidate
Pragma: no-cache
Expires: Wed, 11 Jan 1984 05:00:00 GMT
Content-Type: text/html; charset=iso-8859-1

Quellen:

http://httpd.apache.org/docs/current/mod/mod_headers.html

Cayleaf
quelle
0

meine fünf Cent zu diesem Thema -

In unserem PHP-Projekt haben wir nur wenige 404 Seiten, daher entscheide ich mich, dies auf PHP-Ebene mit PHP-Header () -Funktionen zu tun

Nick
quelle