Я использую 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
.
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).