2010-01-04 8 views
10

Ich habe cachefähigen dynamischen Inhalt in PHP 5.1.0+ gemacht. Ich sende bereits die richtigen Header (einschließlich Last-Modified und ETag) an Clients.Beantworten von HTTP_IF_MODIFIED_SINCE und HTTP_IF_NONE_MATCH in PHP

Ich möchte jetzt mein Skript in der Lage sein, $_SERVER['HTTP_IF_MODIFIED_SINCE'] und $_SERVER['HTTP_IF_NONE_MATCH'] zu beantworten, wenn vorhanden. Wenn die Bedingungen übereinstimmen, möchte ich eine HTTP 304 "Not Modified" an Clients beantworten.

Wie lauten die korrekten Bedingungen? Wann genau gebe ich einen 304 statt des gesamten Inhalts aus?

Die akzeptierte Antwort in Frage How to know when to send a 304 Not Modified response scheint dies richtig zu erteilen, aber ich habe harte Zeiten zu portieren, der Code auf PHP 5.

Thank you!

Antwort

27

habe ich immer verwendet:

function caching_headers ($file, $timestamp) { 
    $gmt_mtime = gmdate('r', $timestamp); 
    header('ETag: "'.md5($timestamp.$file).'"'); 
    header('Last-Modified: '.$gmt_mtime); 
    header('Cache-Control: public'); 

    if(isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) || isset($_SERVER['HTTP_IF_NONE_MATCH'])) { 
     if ($_SERVER['HTTP_IF_MODIFIED_SINCE'] == $gmt_mtime || str_replace('"', '', stripslashes($_SERVER['HTTP_IF_NONE_MATCH'])) == md5($timestamp.$file)) { 
      header('HTTP/1.1 304 Not Modified'); 
      exit(); 
     } 
    } 
} 

mich nicht erinnern, ob ich es geschrieben habe oder es wurde irgendwo anders aus ...

ich es normalerweise an der Spitze einer Datei auf diese Weise mit:

caching_headers ($_SERVER['SCRIPT_FILENAME'], filemtime($_SERVER['SCRIPT_FILENAME'])); 
+1

Große Funktion! Ja wirklich! Es hat meinen Tag gerettet! – Industrial

+4

Schöne Funktion Reich! Etwas lesbarer: 'caching_headers (__FILE__, filemtime (__ FILE __));'. – Julian

+1

Wirklich hilfreich! Versucht dies, aber die Ausführung mehrerer Anfragen gibt alternativ eine 200 und 304 aus. Das Verschieben von "Last-Modified" und "Cache-Control" nach der "ETag" -Definition behebt es. –

0

Wenn der Client eine bedingte GET-Anforderung durchgeführt hat und den Zugriff erlaubt, aber das Dokument ist nicht geändert, der Server mit diesem Statuscode reagieren soll. Die 304 Antwort darf keine Nachricht-Körper enthalten und wird daher immer von der ersten leeren Zeile nach den Header-Feldern beendet.

Von - http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5

Also, wenn Sie den Körper eine 304 nicht senden.

+0

Ich weiß das und meine Frage ist nicht darüber ... Meine Frage ist über Wann sende ich eine 304 ... – AlexV

+0

Meinst du, zu welchem ​​Zeitpunkt in der PHP-Skript? – user151841

+0

Ah sorry, ich muss langsamer werden, =] –

3

Die Antwort, auf die Sie verweisen, scheint alles zu enthalten, was Sie benötigen. Fassen wir zusammen:

  • erzeugen Ihre eigene ETag und Last-Modified-Header, so als ob Sie den ganzen Körper
  • Blick auf die If-Modified-Since Senden würde Header der Client gesendet, wenn Sie Ihre eigenen letzt geändert ist älter oder das gleiche senden Sie die 304
  • Blick auf die If-None-Match-Header des Clients, wenn es mit Ihrem eigenen ETag die 304
  • übereinstimmen, wenn Sie diesen Ort erreichen, die Header nicht übereinstimmen, senden kompletter Körper und neue ETag/Last-Modified Header
1

Hier ist ein Ausschnitt meiner render_file() - Funktion.

$last_modified = filemtime($filename); 
if ($last_modified === false) { 
    throw new Exception('Modify date unknown'); 
} 
if (array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER)) { 
    $if_modified_since = strtotime(preg_replace('/;.*$/', '', $_SERVER['HTTP_IF_MODIFIED_SINCE'])); 
    if ($if_modified_since >= $last_modified) { // Is the Cached version the most recent? 
    header($_SERVER['SERVER_PROTOCOL'].' 304 Not Modified'); 
    exit(); 
    } 
} 
header('Last-Modified: '.date('r', $last_modified)); // tz should be GMT according to specs but also works with other tzs 

// other headers and contents go here 
+0

Und was ist mit HTTP_IF_NONE_MATCH? Wo sollte es in Ihrem Snippet sein? – AlexV

+1

Das Änderungsdatum war für mich genug Validierung, die Berechnung eines Etag (Prüfsumme für den Inhalt md5/sha1) erzeugt etwas Server-Overhead. Etags sind jedoch weniger fehlerbehaftet. Wenn die inhaltliche Richtigkeit wichtig ist, überprüfen Sie zuerst die IF_NONE_MATCH. Wenn IF_NONE_MATCH nicht gesetzt ist, aktivieren Sie IF_MODIFIED_SINCE. Überprüfen Sie nicht das IF_MODIFIED_SINCE, wenn das Etag nicht übereinstimmt. Weil Sie wissen, dass der Browser-Cache ungültig ist! Senden Sie einfach den Header 304 und beenden Sie() –

-3

Warum?

Nach einer Menge Forschung zu diesem Thema habe ich festgestellt, dass bedingte Anfragen tatsächlich eine Website verlangsamen. Es gibt bestimmte Szenarien, in denen dies nicht der Fall ist, aber die Zuordnung zu allgemeinen Nutzungsmustern ergibt insgesamt einen geringeren Durchsatz und weniger effektives Caching.

C.

+0

Warum würde es eine Website verlangsamen. Ich kann mir nicht einmal vorstellen, wie es das verlangsamen würde (es sendet richtige Cache-Header) ... – AlexV

+1

Die kurze Antwort auf diese Frage ist etwa 5 Seiten Text und Grafiken. Ich habe immer den Sinn, es irgendwo ins Internet zu stellen ... sieh dir diesen Raum an. – symcbean

+0

Wäre interessant zu sehen, dass :) – AlexV

0

This article beantworten alle Ihre Fragen über Caching

fand ich, dass das Hinzufügen

RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}] 
RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}] 

Bis zum Ende meiner Htaccess-Datei (unter allen rewriterule) gearbeitet.

Verwandte Themen