Является ли моя реализация HTTP Conditional Ответы на PHP в порядке?

После многого поиска, прочитав все обучающие материалы, которые я нашел, и задал несколько вопросов здесь, мне наконец-то удалось ответить (по крайней мере, я думаю) на аргументы if-none-match и if-modified-since HTTP.

Чтобы сделать краткое описание, это то, что я делаю на всех страницах, кэш:

session_cache_limiter('public'); //Cache on clients and proxies session_cache_expire(180); //3 hours header('Content-Type: ' . $documentMimeType . '; charset=' . $charset); header('ETag: "' . $eTag . '"'); //$eTag is a MD5 of $currentLanguage + $lastModified if ($isXML) header('Vary: Accept'); //$documentMimeType can be either application/xhtml+xml or text/html for XHTML (based on $_SERVER['HTTP_ACCEPT']) header('Last-Modified: ' . $lastModified); header('Content-Language: ' . $currentLanguage); 

Кроме того, каждая страница имеет собственный URL (для каждого языка). Например, «index.php» будет отображаться по адресу «/ ru / home» на английском языке и «/ fr / accueil» на французском языке.

Моя большая проблема заключалась в том, чтобы ответить на «304 Not Modified» на if-none-match и if-modified-так как HTTP-запросы только тогда, когда это необходимо .

Лучший doc, который я нашел, это: http://rithiur.anthd.com/tutorials/conditionalget.php

И это реализация, которую я сделал с ней (этот фрагмент кода называется ASAP на страницах, которые можно кэшировать):

 $ifNoneMatch = array_key_exists('HTTP_IF_NONE_MATCH', $_SERVER) ? $_SERVER['HTTP_IF_NONE_MATCH'] : false; $ifModifiedSince = array_key_exists('HTTP_IF_MODIFIED_SINCE', $_SERVER) ? $_SERVER['HTTP_IF_MODIFIED_SINCE'] : false; if ($ifNoneMatch !== false && $ifModifiedSince !== false) { //Both if-none-match and if-modified-since were received. //They must match the document values in order to send a HTTP 304 answer. if ($ifNoneMatch == $eTag && $ifModifiedSince == $lastModified) { header('Not Modified', true, 304); exit(); } } else { //Only one header received, it it match the document value, send a HTTP 304 answer. if (($ifNoneMatch !== false && $ifNoneMatch == $eTag) || ($ifModifiedSince !== false && $ifModifiedSince == $lastModified)) { header('Not Modified', true, 304); exit(); } } 

Мой вопрос в два раза:

  • Правильно ли это? Я имею в виду, когда отправляются сообщения if-none-match и if-modified-since, оба должны совпадать, чтобы ответить на 304, и если отправлено только одно из двух, только для этого будет нормально отправлять 304?
  • При использовании в контексте, описанном здесь, эти два фрагмента являются общедоступными с точки зрения кэширования кеша (я имею в виду кеш-интерфейс для прокси-серверов и веб-браузеров)?

BTW, я использую только PHP 5.1.0+ (я не поддерживаю версии ниже этого).

Изменить: Добавлена ​​баунти … Я ожидаю качественного ответа. Не отвечайте / голосуйте, если вы что-то угадываете!

  • Это не совсем правильно. Пожалуйста, взгляните на алгоритм: alt text http://img532.imageshack.us/img532/1017/cache.png
  • Решение является прокси-дружественным, вы можете использовать Cache-control: proxy-revalidate, чтобы заставить кеши подчиняться любой информации о свежести, которую вы даете им о ресурсе (применяется только к общим кэшам прокси-сервера)

Вот функция, которая может помочь:

 function isModified($mtime, $etag) { return !( ( isset($_SERVER['HTTP_IF_MODIFIED_SINCE']) && strtotime($_SERVER['HTTP_IF_MODIFIED_SINCE']) >= $mtime ) || ( isset($_SERVER['HTTP_IF_NONE_MATCH']) && $_SERVER['HTTP_IF_NONE_MATCH'] == $etag ) ) ; } 

Я предлагаю вам взглянуть на следующую статью: http://www.peej.co.uk/articles/http-caching.html

Обновить:

[AlexV] Возможно ли получить if-none-match AND if-modified-так как в то же время?

У вас наверняка есть оба набора. Однако:

Если ни один из тегов сущностей не совпадает, тогда сервер МОЖЕТ выполнить запрошенный метод, как если бы поле заголовка If-None-Match не существовало, но ДОЛЖНО также игнорировать любые поля (-ы) заголовка If-Modified-Since в запросе. То есть, если теги сущностей не совпадают, тогда сервер НЕ ДОЛЖЕН возвращать ответ 304 (не модифицированный).

RFC2616 # 14.26

Примеры значений (W означает «слабый», более подробно читайте в RFC2616 # 13.3.3 ):

 If-None-Match: "xyzzy", "r2d2xxxx", "c3piozzzz" If-None-Match: W/"xyzzy", W/"r2d2xxxx", W/"c3piozzzz" If-Modified-Since: Sat, 29 Oct 1994 19:43:31 GMT If-None-Match: * 

В качестве специального случая значение «*» соответствует любому текущему объекту ресурса.