Frage

Ich schreibe eine Methode zur Ressourcenverwaltung, mit der ich den Zugriff auf verschiedene Dateien kontrolliere, und möchte den Cache des Browsers nutzen können.Meine Frage ist zweifach:

  1. Welche sind die definitiven HTTP-Header, die ich überprüfen muss, um sicher zu wissen, ob ich eine 304-Antwort senden soll, und worauf achte ich, wenn ich sie überprüfe?

  2. Gibt es außerdem Header, die ich senden muss, wenn ich die Datei zum ersten Mal als 200-Antwort sende (z. B. „Zuletzt geändert“)?

Ein Pseudocode wäre wahrscheinlich die nützlichste Antwort.


Was ist mit dem Cache-Control-Header?Können sich die verschiedenen möglichen Werte darauf auswirken, was Sie an den Client senden (nämlich max-age), oder sollten nur if-modified-since befolgt werden?

War es hilfreich?

Lösung

So habe ich es umgesetzt.Der Code funktioniert seit etwas mehr als einem Jahr und mit mehreren Browsern, daher halte ich ihn für ziemlich zuverlässig.Dies basiert auf RFC 2616 und indem wir beobachten, was und wann die verschiedenen Browser senden.

Hier ist der Pseudocode:

server_etag = gen_etag_for_this_file(myfile)
etag_from_browser = get_header("Etag")

if etag_from_browser does not exist:
    etag_from_browser = get_header("If-None-Match")
if the browser has quoted the etag:
    strip the quotes (e.g. "foo" --> foo)

set server_etag into http header

if etag_from_browser matches server_etag
    send 304 return code to browser

Hier ist ein Ausschnitt meiner Serverlogik, die dies erledigt.

/* the client should set either Etag or If-None-Match */
/* some clients quote the parm, strip quotes if so    */
mketag(etag, &sb);

etagin = apr_table_get(r->headers_in, "Etag");
if (etagin == NULL)
    etagin = apr_table_get(r->headers_in, "If-None-Match");
if (etag != NULL && etag[0] == '"') {
    int sl; 
    sl = strlen(etag);
    memmove(etag, etag+1, sl+1);
    etag[sl-2] = 0;
    logit(2,"etag=:%s:",etag);
}   
... 
apr_table_add(r->headers_out, "ETag", etag);
... 
if (etagin != NULL && strcmp(etagin, etag) == 0) {
    /* if the etag matches, we return a 304 */
    rc = HTTP_NOT_MODIFIED;
}   

Wenn Sie Hilfe bei der Etag-Generierung benötigen, stellen Sie eine weitere Frage und ich werde einen Code ausgraben, der dies ebenfalls erledigt.HTH!

Andere Tipps

Die Antwort „304 Not Modified“ kann aus einer GET- oder HEAD-Anfrage mit einem If-Modified-Since („IMS“) oder einem If-Not-Match („INM“)-Header resultieren.

Um zu entscheiden, was zu tun ist, wenn Sie diese Header erhalten, stellen Sie sich vor, dass Sie die GET-Anfrage ohne diese bedingten Header bearbeiten.Bestimmen Sie, welche Werte Ihre ETag- und Last-Modified-Header in dieser Antwort haben würden, und treffen Sie diese zur Entscheidungsfindung.Hoffentlich haben Sie Ihr System so aufgebaut, dass es weniger kostspielig ist, dies zu ermitteln, als die vollständige Antwort zu erstellen.

Wenn ein INM vorhanden ist und der Wert dieses Headers mit dem Wert übereinstimmt, den Sie im ETag platzieren würden, antworten Sie mit 304.

Wenn ein IMS vorhanden ist und der Datumswert in diesem Header später ist als der, den Sie in „Zuletzt geändert“ platzieren würden, antworten Sie mit 304.

Andernfalls gehen Sie so vor, als ob die Anfrage diese Header nicht enthalten würde.

Um Teil 2 Ihrer Frage mit dem geringsten Aufwand zu lösen, finden Sie heraus, welche der Header (Expires, ETag und Last-Modified) Sie einfach und korrekt in Ihrer Webanwendung erzeugen können.

Für empfohlenes Lesematerial:

http://www.w3.org/Protocols/rfc2616/rfc2616.html

http://www.mnot.net/cache_docs/

Sie sollten eine 304 senden, wenn der Client ausdrücklich angegeben hat, dass er die Seite möglicherweise bereits in seinem Cache hat.Dies wird als bedingtes GET bezeichnet, das Folgendes enthalten sollte wenn-geändert-seit Header in der Anfrage.

Im Wesentlichen enthält dieser Anforderungsheader ein Datum, ab dem der Client behauptet, eine zwischengespeicherte Kopie zu haben.Sie sollten prüfen, ob sich der Inhalt nach diesem Datum geändert hat, und eine 304 senden, wenn dies nicht der Fall ist.

Sehen http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html#sec14.25 für den entsprechenden Abschnitt im RFC.

Wir verarbeiten auch zwischengespeicherte, aber gesicherte Ressourcen.Wenn Sie einen ETAg-Header senden/generieren (was gemäß RFC 2616 Abschnitt 13.3 empfohlen werden SOLLTE), MUSS der Client ihn in einer bedingten Anfrage verwenden (normalerweise in einem If-None-Match - HTTP_IF_NONE_MATCH - Header).Wenn Sie einen Last-Modified-Header senden (wiederum SOLLTEN Sie es tun), sollten Sie den If-Modified-Since - HTTP_IF_MODIFIED_SINCE - Header überprüfen.Wenn Sie beide senden, SOLLTE der Client beide senden, MUSS jedoch das ETag senden.Beachten Sie außerdem, dass Validtion lediglich als Überprüfung der bedingten Header auf strikte Gleichheit mit denen definiert ist, die Sie versenden würden.Außerdem wird für Bereichsanfragen (bei denen nur ein Teil einer Ressource angefordert wird) nur ein starker Validator (z. B. ein ETag) verwendet.

Da die von uns geschützten Ressourcen ziemlich statisch sind und eine Verzögerungszeit von einer Sekunde akzeptabel ist, gehen wir in der Praxis wie folgt vor:

  1. Überprüfen Sie, ob der Benutzer berechtigt ist, auf die angeforderte Ressource zuzugreifen

    Wenn dies nicht der Fall ist, leiten Sie sie um oder senden Sie gegebenenfalls eine 4xx-Antwort.Wir generieren 404-Antworten auf Anfragen, die wie Hackversuche oder eklatante Versuche, einen Sicherheitsangriff durchzuführen, aussehen.

  2. Vergleichen Sie den If-Modified-Since-Header mit dem Last-Modified-Header, den wir senden würden (siehe unten), um strikte Gleichheit zu gewährleisten

    Wenn sie übereinstimmen, senden Sie eine 304 Not Modified-Antwort und beenden Sie die Seitenverarbeitung

  3. Erstellen Sie einen Last-Modified-Header unter Verwendung der Änderungszeit der angeforderten Ressource

    Schlagen Sie das HTTP-Datumsformat in RFC 2616 nach

  4. Versenden Sie den Header- und Ressourceninhalt zusammen mit einem entsprechenden Inhaltstyp

Wir haben uns entschieden, auf den ETag-Header zu verzichten, da er für unsere Zwecke zu viel des Guten ist.Ich nehme an, wir könnten auch einfach den Datums- und Zeitstempel als ETag verwenden.Wenn wir zu einem echten ETag-System wechseln, würden wir wahrscheinlich berechnete Hashes für die Ressourcen speichern und diese als ETags verwenden.

Wenn Ihre Ressourcen dynamisch generiert werden, beispielsweise aus Datenbankinhalten, sind ETags möglicherweise besser für Ihre Anforderungen geeignet, da es sich lediglich um Text handelt, der nach Belieben ausgefüllt werden kann.

zur Cache-Kontrolle:

Sie sollten sich bei der Bereitstellung keine Gedanken über die Cache-Kontrolle machen müssen, außer sie auf einen angemessenen Wert festzulegen.Im Grunde wird dem Browser und anderen nachgeschalteten Entitäten (z. B. einem Proxy) mitgeteilt, wie viel Zeit maximal vergehen soll, bevor der Cache abläuft.

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top