Что такое Cache-Control: частный?

Когда я нахожусь 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

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

Ответ 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 заголовок 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 потому что он работает для вещей помимо файлов или вещей, которые имеют представление о дате. Это просто

Ответ 2

Cache-Control: private

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

От RFC2616 раздел 14.9.1

Ответ 3

RFC 2616, раздел 14.9.1:

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


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

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


FYI, RFC поясняет, что это не обеспечивает безопасность. Речь идет о показе правильного контента, а не обеспечении содержимого.

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

Ответ 4

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

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

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