Что такое Cache-Control: приватный?

Когда я посещаю http://chesseng.herokuapp.com/, я получаю заголовок ответа, который выглядит как

Cache-Control:private
Connection:keep-alive
Content-Encoding:gzip
Content-Type:text/css
Date:Tue, 16 Oct 2012 06:37:53 GMT
Last-Modified:Tue, 16 Oct 2012 03:13:38 GMT
Status:200 OK
transfer-encoding:chunked
Vary:Accept-Encoding
X-Rack-Cache:miss

а потом я обновляю страницу и получаю

Cache-Control:private
Connection:keep-alive
Date:Tue, 16 Oct 2012 06:20:49 GMT
Status:304 Not Modified
X-Rack-Cache:miss

кажется, что кеширование работает. Если это работает для кеширования, то в чем смысл Expires и Cache-Control: max-age. Чтобы добавить путаницу, когда я тестирую страницу на https://developers.google.com/speed/pagespeed/insights он говорит мне: "Использовать кэширование в браузере".

4 ответа

Решение
Cache-Control: private

Указывает, что все или часть ответного сообщения предназначены для одного пользователя и НЕ ДОЛЖНЫ кешироваться общим кешем, таким как прокси-сервер.

Из RFC2616 раздел 14.9.1

Чтобы ответить на ваш вопрос о том, почему кэширование работает, хотя веб-сервер не включает заголовки:

  • Истекает: [a date]
  • Cache-Control: max-age = [seconds]

Сервер любезно попросил любые промежуточные прокси-серверы не кэшировать содержимое (т.е. элемент должен кэшироваться только в частном кэше, т.е. только на вашем локальном компьютере):

  • Cache-Control: приватный

Но сервер забыл включить любые подсказки кэширования:

  • они забыли включить Expires, поэтому браузер знает, что использовать кэшированную копию до этой даты
  • они забыли включить Max-Age, поэтому браузер знает, как долго кэшируемый элемент хорош
  • забыли включить E-Tag, чтобы браузер мог сделать условный запрос

Но они включили дату последнего изменения в ответ:

Last-Modified: Tue, 16 Oct 2012 03:13:38 GMT

Поскольку браузер знает дату, когда файл был изменен, он может выполнить условный запрос. Он запросит файл у сервера, но прикажет серверу отправлять файл, только если он был изменен с 2012/10/16 3:13:38:

GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT

Сервер получает запрос, понимает, что у клиента уже самая последняя версия. Вместо отправки клиента 200 OK, сопровождаемое содержимым страницы, вместо этого оно говорит вам, что ваша кэшированная версия хороша:

304 Not Modified

Ваш браузер должен был перенести задержку отправки запроса на сервер и дождаться ответа, но он избавил от необходимости повторно загружать статический контент.

Почему Макс-Эйдж? Почему истекает?

Потому что Last-Modified отстой.

Не все на сервере имеют дату, связанную с ним. Если я создаю страницу на лету, с ней не связано никакой даты - это сейчас. Но я совершенно готов позволить пользователю кэшировать домашнюю страницу на 15 секунд:

200 OK
Cache-Control: max-age=15

Если пользователь забьет F5, он получит кэшированную версию в течение 15 секунд. Если это корпоративный прокси-сервер, то все 67198 пользователей, попадающих на одну и ту же страницу в одном и том же 15-секундном окне, получат одинаковое содержимое - все из закрытого кэша. Спектакль победит всех.

Добродетель добавления Cache-Control: max-age в том, что браузер даже не должен выполнять условный запрос.

  • если вы указали только Last-Modified браузер должен выполнить запрос If-Modified-Since и смотреть за 304 Not Modified ответ
  • если вы указали max-age браузеру даже не придется страдать в сети; контент выйдет прямо из кеша

Разница между "Cache-Control: max-age" и "Expires"

Expires является наследственным эквивалентом современного (c. 1998) Cache-Control: max-age заголовок:

  • Expires: вы указываете дату (гадость)
  • max-age: вы указываете секунды (доброта)
  • И если указаны оба, то браузер использует max-age:

    200 OK
    Cache-Control: max-age=60
    Expires: 20180403T192837 
    

Любой веб-сайт, написанный после 1998 года, не должен использовать Expires больше, а вместо этого использовать max-age,

Что такое ETag?

ETag похож на Last-Modified, за исключением того, что он не должен быть датой - он просто должен быть чем-то.

Если я вытаскиваю список продуктов из базы данных, сервер может отправить последний rowversion как ETag, а не как дата:

200 OK
ETag: "247986"

Мой ETag может быть хешем SHA1 статического ресурса (например, изображения, js, css, шрифта) или кэшированной визуализированной страницы (то есть, именно это и делает вики Mozilla MDN; они хэшируют окончательную разметку):

200 OK
ETag: "33a64df551425fcc55e4d42a148795d9f25f89d4"

И так же, как в случае условного запроса на основе Last-Modified:

GET / HTTP/1.1
If-Modified-Since: Tue, 16 Oct 2012 03:13:38 GMT

304 Not Modified

Я могу выполнить условный запрос на основе ETag:

GET / HTTP/1.1
If-None-Match: "33a64df551425fcc55e4d42a148795d9f25f89d4"

304 Not Modified

ETag превосходит Last-Modified потому что это работает для вещей, кроме файлов, или вещей, которые имеют понятие даты. Это просто

RFC 2616, раздел 14.9.1:

Указывает, что все или часть ответного сообщения предназначены для одного пользователя и НЕ ДОЛЖНЫ кешироваться общим кешем... Частный (не общий) кеш МОЖЕТ кешировать ответ.


Браузеры могут использовать эту информацию. Конечно, текущий "пользователь" может означать много вещей: пользователь ОС, пользователь браузера (например, профили Chrome) и т. Д. Он не указан.

Для меня более конкретный пример Cache-Control: private в том, что прокси-серверы (которые обычно имеют много пользователей) не будут кешировать его. Он предназначен для конечного пользователя, и никто другой.


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

Такое использование слова private только контролирует, где может кэшироваться ответ, и не может обеспечить конфиденциальность содержимого сообщения.

В поле заголовка объекта Expires указывается дата / время, после которого ответ считается устаревшим. Поле Cache-control: maxage дает значение возраста (в секундах), которое больше, чем ответ считается устаревшим.

Хотя вышеупомянутое поле заголовка предоставляет клиенту механизм, чтобы решить, отправлять ли запрос на сервер. В некоторых условиях клиент отправляет запрос на разрыв, и возрастное значение ответа больше, чем максимальное значение, то есть доза означает, что серверу нужно отправить ресурс клиенту? Возможно, ресурс никогда не менялся.

Для решения этой проблемы HTTP1.1 дает заголовок с последним изменением. Сервер предоставляет дату последнего изменения ответа клиенту. Когда клиенту нужен этот ресурс, он отправит поле заголовка If-Modified-Since на сервер. Если эта дата предшествует дате изменения ресурса, сервер отправит ресурс клиенту и даст 200 кодов. В противном случае он вернет клиенту код 304, и это означает, что клиент может использовать кэшированный ресурс.

Другие вопросы по тегам