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

148

Когда я посещаю 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/, он говорит мне: «Использовать кэширование в браузере».

user782220
источник
проверьте эту схему stackoverflow.com/a/49925190/3748498
правдомил

Ответы:

74

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

  • Истекает: [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

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

Ян Бойд
источник
1
Потрясающие! Я положил награду за этот ответ. Что происходит, если cache-controlне существует? И у вас есть только Etag? Разве ему не нужно делать «условный запрос» к серверу? Поведение, которое я наблюдаю в автономном режиме, заключается в том, что он просто возвращается из кэша. Но когда он не в сети, он не может сделать этот условный запрос. Так значит ли это, что он будет кешироваться бесконечно, если вы останетесь в автономном режиме? Я уже задавал этот вопрос подробно здесь . Вы можете посмотреть?
Мед
168
Cache-Control: private

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

Из RFC2616 раздел 14.9.1

Дэн Д.
источник
14
Потому что он был кеширован вашим браузером. Вы единственный пользователь, для которого предназначен ответ.
Дэн Д.
13
Нет, это не потому, что Cache-Control:privateтолько состояния, в которых используются общие кэши (например, прокси-кэши), не должны кэшировать ответ.
Дэн Д.
5
@Trejkaz Нет, это действительно означает, что один пользователь. Пользователь - это учетная запись, которая имеет собственный домашний каталог, в котором находится кэш. Те профили, которые принадлежат одному и тому же пользователю, могут совместно использовать свой кеш. Как вы нашли. Но два профиля на одном компьютере, если они принадлежат разным пользователям, не должны совместно использовать свой кеш, если только этот кеш не рассматривается как общий кеш.
Дэн Д.
2
Ах, так это для каждого пользователя на уровне ОС. Да, причина, по которой я задаюсь вопросом, заключается в явной утечке информации между инкогнито-окнами Chrome и неинкогнито-окнами, которые для этого используют кеш.
Trejkaz
2
@didibus proxy-revalidateтребует, чтобы прокси-серверы всегда проходили повторную проверку при каждом доступе. Где как privateмешает прокси от кеширования.
Дэн Д.
21

RFC 2616, раздел 14.9.1 :

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


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

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


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

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

Пол Дрэйпер
источник
5
Частный (не общий) кеш МОЖЕТ кешировать ответ. Эта часть является ключевой. Спасибо.
Оливер
0

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

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

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

Lin.Yang
источник