304: Не модифицировано и кэширование переднего конца

Я использую PHP-скрипт для работы с файлами. Я хотел бы иметь возможность отправить обратно 304 не измененный заголовок в моем ответе HTTP, если файл не изменился с момента последнего его загрузки клиентом. Это похоже на функцию в Apache (и большинстве других веб-серверов), но я не знаю, как это можно реализовать через PHP.

Я слышал об использовании $_SERVER['HTTP_IF_MODIFIED_SINCE'] , но эта переменная, похоже, не появляется в моем супер массиве $_SERVER .

Мой вопрос заключается не в том, как вернуть заголовок 304 , а как узнать, что его нужно вернуть.


Изменить: проблема в том, что мой $_SERVER['HTTP_IF_MODIFIED_SINCE'] не установлен. Это содержимое моего файла .htaccess :

 ExpiresActive On ExpiresByType image/jpeg "modification plus 1 month" ExpiresByType image/png "modification plus 1 month" ExpiresByType image/gif "modification plus 1 month" Header append Cache-Control: "must-revalidate" <IfModule mod_rewrite.c> RewriteEngine On RewriteCond $1 !^(controller\.php) RewriteRule (.*\.jpg|.*\.png|.*\.gif) controller.php/$1 </IfModule> 

HTTP_IF_MODIFIED_SINCE прежнему не отображается в HTTP_IF_MODIFIED_SINCE $_SERVER .

Related of "304: Не модифицировано и кэширование переднего конца"

HTTP_IF_MODIFIED_SINCE – это правильный способ сделать это. Если вы не получаете его, проверьте, что Apache имеет mod_expires и mod_headers включены и работают правильно. Заимствован из комментария на PHP.net :

 $last_modified_time = filemtime($file); $etag = md5_file($file); // always send headers header("Last-Modified: ".gmdate("D, d MYH:i:s", $last_modified_time)." GMT"); header("Etag: $etag"); // exit if not modified if (@strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) == $last_modified_time || @trim($_SERVER['HTTP_IF_NONE_MATCH']) == $etag) { header("HTTP/1.1 304 Not Modified"); exit; } // output data 

Эта статья ответит на все ваши вопросы по кешированию

Я обнаружил, что добавление

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

В нижней части моего файла htaccess (ниже всех переписывающих) работал.

$_SERVER['HTTP_IF_MODIFIED_SINCE'] обычно пуст, когда register_globals выключен.

Проверьте, так ли это, и если да, попробуйте getenv('HTTP_IF_MODIFIED_SINCE')

Есть также некоторые другие параметры для проверки .. в моем случае у меня не было обоих этих заголовков:

 $_SERVER['HTTP_IF_NONE_MATCH'] && $_SERVER['HTTP_IF_MODIFIED_SINCE'] 

которые необходимы для возврата правильного заголовка 304, поскольку мои системные часы были немного запоздалыми, они будут интерпретировать эти страницы как истекающие в будущем, а затем не отправлять эти значения вообще

Также проверьте заголовок, который возвращается apache, или, по крайней мере, переопределите его на большее значение

 Cache-Control: max-age=3600 

Поскольку он не отправляет предыдущие заголовки, если

 Last-Modified previous sent header < ( NOW - 3600 ) 

Поэтому в моем случае я установил эту довольно function lastModified($file){ $x=filemtime($file); while($x>time())$x-=86000;}#reduce by one day if touched in future date $date=gmdate('D, j MYH:i:s',$x).' GMT'; header('Cache-Control: max-age=86000',1); if($_SERVER['HTTP_IF_NONE_MATCH'] == $x || $_SERVER['HTTP_IF_MODIFIED_SINCE']==$date){ header('HTTP/1.1 304 Not Modified',1,304);die;} header('Etag: '.$x,1);header('Last-Modified: '.$date,1); } функциональную function lastModified($file){ $x=filemtime($file); while($x>time())$x-=86000;}#reduce by one day if touched in future date $date=gmdate('D, j MYH:i:s',$x).' GMT'; header('Cache-Control: max-age=86000',1); if($_SERVER['HTTP_IF_NONE_MATCH'] == $x || $_SERVER['HTTP_IF_MODIFIED_SINCE']==$date){ header('HTTP/1.1 304 Not Modified',1,304);die;} header('Etag: '.$x,1);header('Last-Modified: '.$date,1); } function lastModified($file){ $x=filemtime($file); while($x>time())$x-=86000;}#reduce by one day if touched in future date $date=gmdate('D, j MYH:i:s',$x).' GMT'; header('Cache-Control: max-age=86000',1); if($_SERVER['HTTP_IF_NONE_MATCH'] == $x || $_SERVER['HTTP_IF_MODIFIED_SINCE']==$date){ header('HTTP/1.1 304 Not Modified',1,304);die;} header('Etag: '.$x,1);header('Last-Modified: '.$date,1); }

У меня была эта проблема, и оказалось, что я открыл Firebug. У этого есть опция под вкладкой Net «Отключить кеш браузера», которая по умолчанию отмечена галочкой. Аналогичная опция в инструментах разработчика Chrome – одна из галочек на панели под панелью меню.

Устранение этих параметров привело к тому, что браузер правильно отправил HTTP_IF_MODIFIED_SINCE и все работает нормально (даже с Firebug или Chrome Dev Tools open).