HTTP: объединение срока действия и проверки кэширования - PullRequest
19 голосов
/ 15 июня 2011

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

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

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

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

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

1 Ответ

29 голосов
/ 15 июня 2011

Да, ответ 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.

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

...