Заметим, что кнопка «Обновить» (включая клавишу F5) не запускает данный механизм, потому что «Обновить» всегда отправляет на сервер запрос If-Modified-Since. Однако с помощью описанной выше логики будут открываться все ссылки.
В следующем примере сервер уведомляет Internet Explorer, что содержание документа не будет меняться в течение 1 часа (pre-check=3600) и что его можно загружать прямо из локального кэша. В случае же изменения страницы, если пользователь запросит ее по истечении 15 минут, Internet Explorer должен отобразить локальный кэш, но при этом в фоновом режиме проверить, является ли сохраненная копия страницы актуальной, и по необходимости загрузить ее с сервера.
Cache-Controclass="underline" post-check=900,pre-check=3600
Использование описанных параметров для тонкой настройки общения сервера с IE может оказаться весьма полезным для высоконагруженных проектов, ориентированных на пользователей Internet Explorer. Это позволит как существенно уменьшить число запросов к серверу и сэкономить его ресурсы, так и поддерживать актуальность кэшируемых документов.
3.3. Last-Modified и ETag
Давайте рассмотрим, какие существуют альтернативы прямому ограничению повторных загрузок ресурсов со стороны сервера и сохранению их в пользовательском кэше.
Дополнительно к заголовку Cache-Control, который предупреждает браузер, что последний может не запрашивать исходный документ с сервера некоторое время, будет полезно проверять версию ресурса каждый раз при запросе. Например, нам нужно, чтобы браузер пользователя проверял файлы стилей не реже, чем раз в день, но при этом сами файлы могут меняться достаточно редко (например, несколько раз в месяц). Для решения такой задачи и была придумана пара заголовков Last-Modified и If-Modified-Since.
Как это работает? Дополнительно к периоду кэширования сервер может также отправить заголовок Last-Modified, который будет обозначать время последнего изменения файла на сервере. Если у браузера есть уже такой файл в локальном кэше, то он может отправить на сервер If-Modified-Since с соответствующим временем. В случае, если файл не менялся со времени последнего посещения, сервер ответит статус-кодом 304 и не будет пересылать содержимое файла.
Данная схема позволяет экономить время, затрачиваемое на передачу данных, однако при ее использовании браузер все равно будет устанавливать соединение с сервером, чтобы узнать, имеется ли более новая версия.
ETag (англ. Entity Tags — тэги сущностей) — механизм, который используют браузеры и веб-серверы, чтобы определить, является ли объект, находящийся в кэше браузера, таким же, как соответствующий объект на сервере. Теги сущностей являются почти полной аналогией Last-Modified заголовка за исключением того, что в качестве тега может быть передана произвольная строка. Сервер указывает ETag для компонента, используя HTTP-заголовок ETag:
HTTP/1.1 200 OK
Last-Modified: Tue, 12 Dec 2008 03:03:59 GMT
ETag: "10c24bc-4ab-457e1c1f"
Content-Length: 19145
Позднее, если браузер хочет определить актуальность компонента, он передает заголовок If-None-Match для передачи ETag обратно на сервер. Если ETag совпадают, ответ от сервера приходит со статус-кодом 304, уменьшая, таким образом, объем передачи на 19145 байтов:
GET /b.png HTTP/1.1
Host: i.webo.in
If-Modified-Since: Tue, 12 Dec 2008 03:03:59 GMT
If-None-Match: "10c24bc-4ab-457e1c1f"
HTTP/1.1 304 Not Modified
Включить ETag для Apache можно, например, следующей директивой в конфигурации:
FileETag MTime Size
При этом ETag будет сформирован из даты изменения файла и его размера.
Синхронизация ETag и Last-Modified
Проблема ETag состоит в том, что обычно они используют атрибуты, специфичные в пределах одного сервера. ETag не совпадут, если браузер загрузит компонент страницы с одного сервера и попробует проверить его с другим сервером (у которого время изменения файла и(ли) номер блока на жестком диске для данного файла отличаются от первого) — ситуация очень распространенная, если вы используете кластер для обработки запросов. По умолчанию и Apache, и IIS включают в ETag такие данные, которые вряд ли дадут положительный результат при проверке на актуальность компонента на разных серверах.
Apache 1.3 и 2 генерирует ETag в формате inode-size-timestamp. Даже если один и тот же файл на разных серверах лежит в одной и той же папке, имеет те же права, размер и время, номер его иногда будет отличаться от сервера к серверу.