HTTP: сочетание срока действия и кеширования проверки

У меня проблемы с формулировкой заголовков HTTP-кеша для следующей ситуации.

На нашем сервере хранятся большие данные, которые меняются, возможно, пару раз в неделю. Я хочу, чтобы браузеры кэшировали эти данные. Кроме того, я хочу минимизировать задержку при условном получении, поскольку сеть ненадежна.

Конечное поведение, которое мне нужно, таково:

  1. Клиент запрашивает ресурс, которого раньше не видел.
  2. Сервер отвечает ресурсом вместе с ETag и max-age (24 часа).
  3. Пока не пройдет 24 часа, клиент будет использовать кешированный ресурс.
  4. По истечении срока действия клиент выполнит запрос на подтверждение (If-None-Match: [etag])
  5. If resource has not changed:
    • server responds with 304 Not Modified
    • клиент каким-то образом проинформирован о том, что у существующего ресурса новый срок действия через 24 часа
    • вернуться к шагу 3

Сводка к сути ... может ли ответ 304 содержать новый max-age? Или исходный max-age учитывается для последующих запросов?


person roufamatic    schedule 14.06.2011    source источник


Ответы (1)


Да, ответ 304 может содержать новый max-age (или ETag, или другие заголовки ответа, если на то пошло).

Я провел эксперимент с использованием Firefox 4, чтобы проверить, соблюдается ли исходный максимальный возраст или новый, и получил ответ, что новый max-age соблюдается, поэтому вы сможете реализовать то, что хотите.

Важно помнить, что max-age относится к заголовку ответа Date, а не Last-Modified, поэтому всякий раз, когда ваш сервер устанавливает директиву max-age на 24 часа, он говорит: «Через 24 часа». Итак, если это то, что вы хотите, вам вообще не придется менять свой max-age, просто всегда возвращайте 86400.

Во всяком случае, вот обзор и дамп моего эксперимента. Обычно я попадаю на тестовый URL, который устанавливает ETag и устанавливает max-age равным 120 секундам. Соответственно, сервер вернул страницу с такими заголовками ответа:

HTTP/1.1 200 OK
Date: Tue, 14 Jun 2011 23:48:51 GMT
Cache-Control: max-age=120
Etag: "901ea3d0ac9303ae4855a09676f96701"
Last-Modified: Mon, 13 Jun 2011 22:20:03 GMT

Затем я повторил нажатие «Enter» в адресной строке, чтобы загрузить страницу (но без принудительной перезагрузки). Сетевого трафика не было, поскольку Firefox неоднократно перезагружал страницу из кеша. Затем, по прошествии 120 секунд, в следующий раз, когда я нажму Enter, Firefox вместо этого отправил на сервер условный GET, как и следовало ожидать. Запрос и ответ от сервера были:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:50:54 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

Обратите внимание, что в ответе 304 сервер изменил max-age с 120 секунд до 240.

Итак, большой вопрос: что произойдет через 120 секунд? Будет ли Firefox уважать новый max-age и продолжать загружать страницу из кеша, или он попадет на сервер? Ответ заключается в том, что он продолжал загружать страницу из кеша и не запрашивал повторно до тех пор, пока не было достигнуто 240 секунд:

GET /example HTTP/1.1
If-Modified-Since: Mon, 13 Jun 2011 22:20:03 GMT
If-None-Match: "901ea3d0ac9303ae4855a09676f96701"

HTTP/1.1 304 Not Modified
Date: Tue, 14 Jun 2011 23:54:56 GMT
Etag: "901ea3d0ac9303ae4855a09676f96701"
Cache-Control: max-age=240

Я повторил еще один 240-секундный цикл, и все заработало, как и следовало ожидать. Надеюсь, это ответ на ваш вопрос.

В RFC объясняется, как должны выполняться вычисления возраста и как остальные параметры Cache-Control работают. Нет никакой гарантии, что каждый браузер и прокси будут следовать правилам, но на данный момент HTTP 1.1 довольно старый, и можно ожидать, что большинство из них будут работать так же, как Firefox.

(Примечание: для краткости в этих примерах дампа я удалил нерелевантные заголовки, такие как host, connection / keep-alive, кодировка / длина / тип контента, пользовательский агент и т. д.)

person joelhardi    schedule 15.06.2011
comment
Затем я повторил нажатие Enter в адресной строке, чтобы загрузить страницу (но без принудительной перезагрузки). - Это была ключевая информация, которая мне понадобилась для проведения эксперимента самому! Спасибо за продуманный ответ! - person roufamatic; 15.06.2011
comment
Я воспроизвел то, что вы описали, с помощью FireFox. В Chrome нажатие клавиши ввода в адресной строке по-прежнему вызывает 304. Я обнаружил, что переход на другую страницу (например, google.com), а затем нажатие кнопки «Назад» покажет желаемое поведение кеша. (Интересно, что если я перешел на свою страницу с помощью кнопки «Вперед», она ВСЕГДА отображала кешированный файл.) - person roufamatic; 15.06.2011
comment
Спасибо, это хорошая информация о Chrome. Я предполагаю, что главное, что нужно сделать, если вы тестируете, - это попытаться смоделировать все, что делают ваши пользователи, какую бы комбинацию щелчков ссылок, щелчков по закладкам (прямой трафик), что вы могли оценить по данным реферера (я бы предположил, что эти оба будут загружены из действительного кеша). И разбить по браузеру. Или просто доверяйте Firefox / Chrome и будьте счастливы, что вы правильно реализуете HTTP так, как хотите. - person joelhardi; 16.06.2011
comment
Итак, при тестировании того, как работает кеширование браузера (по крайней мере, в Chrome), откройте нужный URL-адрес в новой вкладке, затем вы можете перейти к новому URL-адресу и затем вернуться. Использование ENTER в адресной строке и, конечно же, F5 приводит к жесткой перезагрузке для меня. - person Vitaly Sazanovich; 15.10.2014
comment
Кто-то получил на это ответ? - stackoverflow.com/questions/26964948/ - person Codebeat; 17.11.2014