В чем может быть разница между if-modified-since и if-none-match? У меня такое чувство, что если-нить-совпадение используется для файлов, тогда как if-modified-since используется для страниц?
If-modified-поскольку vs if-none-match
Ответ 1
Относительно различий между Last-Modified/If-Modified-Since
и ETag/If-None-Match
:
Оба могут использоваться взаимозаменяемо. Однако в зависимости от типа ресурса и того, как он генерируется на сервере, один или другой вопрос ( "было ли это изменено с...?" / "Это все еще соответствует этому ETag?" ), Может быть проще ответить.
Примеры:
- Если вы подаете файлы, использование файла
mtime
в качестве датыLast-Modified
является самым простым решением. - Если вы используете динамическую веб-страницу, созданную из нескольких SQL-запросов, проверка того, что данные, возвращенные любым из этих запросов, изменились, может быть непрактичным (если только у всех из них нет своего рода "последний измененный" столбец), В этом случае, используя, например, хеш md5 содержимого страницы, так как
ETag
будет намного проще.
OTOH, это означает, что вам все равно придется генерировать всю страницу на сервере, даже для условного GET. Выяснив, что именно нужно входить в ETag (первичные ключи, номера версий,... и т.д.), Может сэкономить вам много времени.
Смотрите эти ссылки для получения более подробной информации по теме:
Ответ 2
If-Modified-Since
сравнивается с Last-Modified
тогда как If-None-Match
сравнивается с ETag
. Оба Modified-Since
и ETag
могут использоваться для идентификации конкретного варианта ресурса.
Но сравнение If-Modified-Since
с Last-Modified
дает вам информацию о том, является ли кешированный вариант старше или новее, тогда как сравнение If-None-Match
- ETag
просто дает вам информацию о том, идентичны ли они или нет. Кроме того, большинство генераторов ETag
включают информацию о системном конкретном inode, поэтому перемещение файла на другой диск может изменить значение ETag
.
Ответ 3
Значение временной отметки, используемое в Last-Modified/If-Modified-Since имеет ограниченную точность - одну секунду, и этого просто недостаточно для быстрого изменения контента, например, приложения для веб-чата, где может быть отправлено более одного сообщения любой второй. ETag/If-None-Match может помочь решить эту проблему.
Ответ 4
Как указано в лучших рекомендациях Google:
Важно указать один из Max-age Expires или Cache-Control и один из Last-Modified или ETag для всех кэшируемых ресурсов. Это избыточно, чтобы указать как Expires, так и Cache-Control: max-age, или указать как Last-Modified, так и ETag.
https://developers.google.com/speed/docs/best-practices/caching
Ответ 5
If-Modified-Since использует дату, а If-None -Match использует ETag. Они могут использоваться как для "страниц" (т.е. HTML), так и для других файлов.
Ответ 6
Если не указано как слабое сервером, ETag считается сильным валидатором и, таким образом, может использоваться для удовлетворения запроса с ограниченным диапазоном. Однако большинство автоматически генерируемых ETags обнаруживают трудности в ситуациях фермы серверов, поскольку они часто используют информацию inode и/или уникальный постоянный счетчик. На практике я нашел, что заголовок Last Modified достаточно для довольно статического содержимого, например. обслуживающий защищенный статический контент, поскольку время записи файла делает достаточно хороший валидатор.
ETag на сегодняшний день является наиболее гибким. Соответствующие клиенты обязаны отправлять ETag в условный запрос, тогда как они ДОЛЖНЫ отправлять оба, если они доступны.
Ответ 7
Так как боты Google и Bing используют If-Modified-Since
, а не If-None-Match
, его полезно поддерживать.
Существует способ поддерживать If-Modified-Since
даже на сложных страницах без отслеживания времени модификации. Мы используем этот метод в WikiMentions.com. Эти методы делают много предположений об установке. Это может не сработать для всех.
Ваш обработанный html должен быть чистой функцией данных, возвращаемых вызовами api. Рассмотрим пример страницы example.com/shows/cosmos
. Возможно, потребуется несколько вызовов api:
api.example.com/shows/cosmos
api.example.com/cast/cosmos
api.example.com/related/cosmos
api.example.com/featured
Если каждый вызов возвращает etag, вы можете создать etag для своей html-страницы, объединив эти etags и хешируя результат. Затем вы можете использовать это как etag для html-страницы. Затем вы можете сохранить этот файл в memcached вместе со временем его создания и сгенерированным html.
{
"Modified": timestamp,
"Content": rendered page,
"E-tag": hash of concatenated etags of api calls
}
Теперь, когда страница запрашивается в первый раз:
- Сделать api вызовы для страницы
- Создание конкатенированного etag
- Поиск etag в memcached (он не существует)
- Отобразить страницу
- Добавить в memcached
- Отправить его пользователю
Когда страница запрашивается еще одним новым посетителем:
- Сделать api вызовы для страницы
- Создание конкатенированного etag
- Lookup etag в memcached (он будет существовать)
- Отправить кешированную копию из предыдущего посещения
Когда страница запрашивается возвращающимся посетителем (с If-Modified-Since):
- Сделать api вызовы для страницы
- Создание конкатенированного etag
- Lookup etag в memcached (он будет существовать)
- Если время модификации в memcached позже If-Modified-Since
- Отправить кешированную копию
- Else
- Отправить 304 не измененных
Преимущества:
- Может поддерживать как
If-Modified-Since
, так иIf-None-Match
. - Нет страниц повторной рендеринга для новых посетителей, если они уже были отображены раньше.
- Никогда не используйте устаревший контент.
Предостережения:
- Нет необходимости получать обработанный html из memcached, если мы собираюсь отправить 304. Таким образом, вы можете хранить его отдельно в memcached с префиксом, прикрепленным к клавише etag.
- При изменении кода рендеринга данные api не изменяются, но ваш обработанный html делает. В результате вы не сможете увидеть свою изменения, так как вы увидите только кешированный html. Чтобы этого избежать генерировать небольшую случайную строку каждый раз, когда вы создаете и добавляете ее к etags перед хэшированием.
- Это не работает, если отображаемый html не является чистой функцией данных api (например: строки времени). Обходной путь, который мы используем для WikiMentions, - это визуализировать gmt timestamps и конвертировать их в timeago на стороне клиента после реактивных нагрузок.
Это может не работать для всех в зависимости от настройки. Это работает для нас. Мы используем торнадо для нашего api и React с Node.js для нашего front-end.
Ответ 8
Заголовок If-Modified-Since используется для указания времени, когда браузер последний раз получил запрошенный ресурс. Заголовок If-None-Match используется для указания тега объекта, который сервер выпустил с запрошенным ресурсом, когда он был получен в последний раз.
Двумя описанными способами эти заголовки используются для поддержки кэширования содержимого в браузере, и они позволяют серверу инструктировать браузер использовать кэшированную копию ресурса, а не отвечать полным содержимым ресурса, если это не обязательно.