У меня есть кешируемое динамическое содержимое, сделанное в PHP 5.1.0+. Я уже отправляю правильные заголовки (включая Last-Modified и ETag) клиентам.
Теперь я хочу, чтобы мой скрипт мог отвечать на $_SERVER['HTTP_IF_MODIFIED_SINCE']
и $_SERVER['HTTP_IF_NONE_MATCH']
при наличии. Когда условия совпадают, я хочу ответить на HTTP 304 "Not Modified"
для клиентов.
Каковы правильные условия? Когда именно я выдаю 304 вместо всего контента?
Принятый ответ на вопрос Как узнать, когда отправлять 304 Not Modified ответ, кажется, это правильно, но мне трудно переносить этот код на PHP 5.
Спасибо!
Я всегда использовал:
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(); } } }
Не помню, писал ли я его или получил его откуда-то еще …
Обычно я использую его в верхней части файла таким образом:
caching_headers ($_SERVER['SCRIPT_FILENAME'], filemtime($_SERVER['SCRIPT_FILENAME']));
Ответ, на который вы ссылаетесь, кажется, содержит все, что вам нужно. Обобщить:
Вот фрагмент моей функции render_file ().
$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
Если клиент выполнил условный запрос GET и разрешен доступ, но документ не был изменен, сервер ДОЛЖЕН ответить этим кодом состояния. Ответ 304 НЕ ДОЛЖЕН содержать тело сообщения и, таким образом, всегда заканчивается первой пустой строкой после полей заголовка.
От: http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html#sec10.3.5
Итак, если вы отправляете 304, не отправляйте тело.
Эта статья ответит на все ваши вопросы по кешированию
Я обнаружил, что добавление
RewriteRule .* - [E=HTTP_IF_MODIFIED_SINCE:%{HTTP:If-Modified-Since}] RewriteRule .* - [E=HTTP_IF_NONE_MATCH:%{HTTP:If-None-Match}]
В нижней части моего файла htaccess (ниже всех переписывающих) работал.
Зачем?
Проведя много исследований по этому вопросу, я обнаружил, что условные запросы фактически замедляют работу сайта. Существуют определенные сценарии, в которых это не так, но в общем случае использование общих шаблонов использования приводит к снижению пропускной способности и менее эффективному кэшированию.
C.