Что такое 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
Указывает, что все или часть ответного сообщения предназначены для одного пользователя и НЕ ДОЛЖНЫ кешироваться общим кешем, таким как прокси-сервер.
Чтобы ответить на ваш вопрос о том, почему кэширование работает, хотя веб-сервер не включает заголовки:
- Истекает:
[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, и это означает, что клиент может использовать кэшированный ресурс.