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

HTTP: объединение кеширования истечения срока действия и валидации

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

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

Конечное поведение, которое я выполняю, следующее:

  • Клиент запрашивает ресурс, который ранее не видел.
  • Сервер отвечает ресурсом вместе с ETag и max-age (24 часа).
  • До тех пор, пока не пройдет 24 часа, клиент будет использовать кешированный ресурс.
  • После истечения срока действия клиент выполнит запрос проверки (If-None-Match: [etag])
  • Если ресурс не изменился:
    • сервер отвечает 304 Not Modified
    • клиент как-то сообщил, что существующий ресурс имеет новую дату истечения срока действия через 24 часа
    • вернуться к шагу 3

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

4b9b3361

Ответ 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.

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