Подтвердить что ты не робот

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.

4b9b3361

Ответ 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 открыты).