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
все еще не отображается в супер массиве $_SERVER
.
Ответы
Ответ 1
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 M Y H: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
Ответ 2
Эта статья ответит на все ваши вопросы по кешированию
Я обнаружил, что добавление
RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}]
RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
В нижней части моего файла htaccess (ниже всех переписывающих) работает.
Ответ 3
$_SERVER['HTTP_IF_MODIFIED_SINCE']
обычно пуст, когда register_globals
выключен.
Проверьте, является ли этот случай, и если да, попробуйте getenv('HTTP_IF_MODIFIED_SINCE')
Ответ 4
Есть также некоторые другие параметры для проверки.. в моем случае у меня не было обоих этих заголовков:
$_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 M Y H: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);
}
Ответ 5
У меня была эта проблема, и оказалось, что я открыл Firebug. У этого есть опция под вкладкой Net "Отключить кеш браузера", которая по умолчанию отмечена галочкой. Аналогичная опция доступна в инструментах разработчика Chrome, одной из галочек на панели в строке меню.
Устранение этих параметров привело к тому, что браузер правильно отправил HTTP_IF_MODIFIED_SINCE
, и все работает нормально (даже если Firebug или Chrome Dev Tools открыты).