wake-up-neo.net

So verhindern Sie, dass die Anforderung zurückgegeben wird 304

Wann fordert ein Browser KEINE Datei an den Server an?

Mit anderen Worten, ich habe eine JavaScript-Datei, die geliefert wird. Sein HTTP-Antwortheader hat eine ETag, Cache-Control: public und Expires: Tue, 19 Jan 2038 03:14:07 GMT.

Der Server gibt einen 304 zurück, nachdem der Browser-Cache gefüllt wurde.

Meine Frage ist, warum prüft der Browser überhaupt den Server und bekommt überhaupt einen 304? Ich möchte nicht, dass der Browser fragt, ob es eine neue Version gibt - er sollte direkt aus dem Browser-Cache geladen werden, ohne nach Änderungen am Server zu suchen, der das Skript bereitstellt.

Welche Kombination von HTTP-Antwortheatern bewerkstelligt dies?

51
core

Erstens ist die relevante HTTP-Spezifikation RFC 7234 . Wenn Sie sich die Spezifikation ansehen, werden Sie zwei Dinge bemerken:

  • Die Spezifikation verlangt unter keinen Umständen , dass ein Cache eine zwischengespeicherte Version des Inhalts ohne erneute Überprüfung bereitstellt. Es gibt viele Stellen, an denen die Spezifikation feststellt, dass ein Cache KEINEN zwischengespeicherten Inhalt verwenden DARF, um eine Anforderung zu befriedigen. Es gibt jedoch keine Stellen, an denen dies erforderlich ist oder die NICHT erneut überprüft werden dürfen. Browser-Anbieter können also jederzeit eine erneute Validierung durchführen, wenn sie dies möchten.
  • Zweitens machst du nichts falsch an deinem Ende. Es steht den Browsern frei, Antworten zwischenzuspeichern und diese zwischengespeicherten Antworten zu verwenden, wenn die von Ihnen zurückgegebenen Header angegeben werden. Der entscheidende Punkt ist in Abschnitt 4 , wo festgestellt wird, dass eine der Bedingungen für die Zustellung einer zwischengespeicherten Antwort darin besteht, dass die Antwort entweder:

    • frisch (siehe Abschnitt 4.2) oder

    • dürfen abgestanden serviert werden (siehe Abschnitt 4.2.4), oder

    • erfolgreich validiert (siehe Abschnitt 4.3).

    Da Sie einen Expires -Header ausspucken, der weit in der Zukunft liegt und der zu diesem Zeitpunkt noch nicht erreicht wurde, ist die Antwort "frisch" und daher ist keine erneute Validierung erforderlich. Sie tun also alles, was die Spezifikation vorschlägt. (Obwohl die Verwendung von Cache-Control: max-age=foo eine modernere Methode zum Festlegen von Cache-Ablaufzeiten darstellt als die Verwendung des Headers Expires:.)

Wenn Sie also das Caching-Verhalten des Browsers ändern möchten, haben Sie Pech.

Allerdings sind die Dinge möglicherweise nicht so schlimm, wie Sie denken. Sie sehen wahrscheinlich nur eine Anfrage und 304, weil Sie die Seite in Ihrem Browser beim Testen aktualisieren . Browser behandeln zwischengespeicherte Ressourcen unterschiedlich, je nachdem, wie die Anforderung für sie ausgelöst wurde.

In einem einfachen Test habe ich eine HTML-Seite erstellt, die ein <script> -Tag, das auf eine JS-Datei verweist, ein <img> -Tag, das auf ein Bild verweist, und ein <link> -Tag, das auf ein CSS-Stylesheet verweist, enthielt. Alle diese Dateien wurden auf einem Apache-Server gehostet, der so konfiguriert ist, dass sie mit Folgendem bereitgestellt werden:

  • ein E-Tag Header,
  • ein Datum der letzten Änderung,
  • ein Cache-Control: max-age=172800-Header

Natürlich wurden alle Ressourcen beim Laden der ersten Seite mit 200 Codes bedient. Beim Testen in Chrome oder Firefox mit den Standardeinstellungen stellte ich Folgendes fest:

  • Wenn Sie die Seite über die aktualisieren  F5 Taste oder die Schaltfläche Aktualisieren , die Seite und alle Ressourcen werden erneut validiert (d. h. es wird für jede Ressource eine Anforderung an den Server gesendet und eine 304 zurückgegeben).
  • Wenn Sie über einen Link zur Seite zurückkehren oder die URL in einem neuen Tab in die URL-Leiste eingeben, wird keine erneute Validierung durchgeführt (dh es werden keine Anforderungen gestellt) gemacht).
  • Wenn Sie in Chrome die Seite aktualisieren, indem Sie die URL-Leiste auswählen und die Eingabetaste drücken, wird die Seite selbst erneut überprüft, andere Ressourcen jedoch nicht. In Firefox werden weder die Seite noch die Ressourcen erneut überprüft.

Diese Seite gibt an, dass Internet Explorer dasselbe Verhalten aufweist:

Es gibt eine Reihe von Situationen, in denen Internet Explorer überprüfen muss, ob ein zwischengespeicherter Eintrag gültig ist:

  • Der zwischengespeicherte Eintrag hat kein Ablaufdatum und auf den Inhalt wird zum ersten Mal in einer Browsersitzung zugegriffen
  • Der zwischengespeicherte Eintrag hat ein Ablaufdatum, ist jedoch abgelaufen
  • Der Benutzer hat eine Seitenaktualisierung angefordert, indem er auf die Schaltfläche Aktualisieren geklickt oder F5 gedrückt hat

Mit anderen Worten, normalerweise werden diese Verlängerungsanforderungen nur angezeigt, wenn der Benutzer die Seite explizit aktualisiert. Sofern Sie keine besonderen Anforderungen an das Verhalten des Browser-Caches haben, ist dieses Verhalten durchaus vernünftig.

Google und Mozilla haben beide eine Dokumentation zum HTTP-Caching (ich kann auf der MSDN- oder der Apple Developers-Site nichts Vergleichbares finden), aber beide weisen auch nicht auf die Existenz eines Anbieters hin. Spezifische Caching-Header, mit denen die Regeln geändert werden können, die der Browser verwendet, um den Zeitpunkt für die erneute Überprüfung festzulegen. Was Sie tun möchten, ist einfach nicht möglich.

Wenn Sie wirklich mehr Kontrolle über dieses Verhalten benötigen, können Sie in HTML5 Application Cache nachsehen oder Ihre eigene Caching-Logik mit HTML5 Local Storage erstellen, wie dies basket.js tut.

87
Mark Amery

Expires: oder Cache-Control: max-age= sollten funktionieren. Haben Sie in den Serverprotokollen bestätigt, dass der Browser tatsächlich Netzwerkanrufe tätigt? Ich habe festgestellt, dass Firebug zum Beispiel eine verwirrende Ausgabe hat, die besagt, dass Sie Remote-Aufrufe machen, wenn Sie tatsächlich den Cache erreichen. 

0
James Scriven

Wenn Sie sich in meinem Boot befinden und eine Angular-App für IIS bereitgestellt haben, stellen Sie sicher, dass Ihre web.config so konfiguriert ist, dass die URL wie folgt korrekt geschrieben wird:

<?xml version="1.0" encoding="UTF-8"?>
<configuration>
    <system.webServer>
        <httpErrors errorMode="Detailed" />
        <rewrite>
            <rules>
                <rule name="Angular Routes" stopProcessing="true">
                    <match url=".*" />
                    <conditions logicalGrouping="MatchAll">
                        <add input="{REQUEST_FILENAME}" matchType="IsFile" negate="true" />
                        <add input="{REQUEST_FILENAME}" matchType="IsDirectory" negate="true" />
                    </conditions>
                    <action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />
                </rule>
            </rules>
        </rewrite>
  </system.webServer>
</configuration>

Notieren Sie sich speziell den Wert von url in <action type="Rewrite" url="/NameOfYourApp_UnderDefaultWebSite/" />

0
Adam Cox