Что имеет приоритет: HTTP-заголовок ETag или Last-Modified?

83

Для двух последующих запросов, какой из следующих двух заголовков будет иметь больший вес браузерами, если один из них изменится: ETag или Last-Modified?

user101442
источник

Ответы:

90

Согласно RFC 2616, раздел 13.3.4, клиент HTTP 1.1 ДОЛЖЕН использовать ETag в любых условных запросах кеширования, и если присутствуют и ETag, и Last Modified, он ДОЛЖЕН использовать оба. Заголовок ETag считается сильным валидатором (см. Раздел 13.3.3), если сервер явно не объявил его слабым, тогда как заголовок Last Modified считается слабым, если между ним и заголовком Date не существует хотя бы минутной разницы. Обратите внимание, однако, что сервер также не обязан отправлять (но он ДОЛЖЕН, если он может).

Обратите внимание, что Клиент не проверяет заголовки, чтобы увидеть, изменились ли они; он просто слепо использует их в следующем условном запросе; Сервер должен оценить, отправлять ли запрошенное содержимое или ответ 304 Not Modified. Если Сервер отправляет только один, то Клиент будет использовать только его (хотя для запроса диапазона полезны только сильные валидаторы). Конечно, это также на усмотрение промежуточных кешей (если они не были заблокированы от кеширования с помощью директив Cache Control) и Сервера в отношении того, как они будут действовать с заголовками; RFC заявляет, что они НЕ ДОЛЖНЫ возвращать 304 Not Modified, если валидаторы несовместимы, но, поскольку значения заголовков генерируются сервером, у него есть небольшая свобода действий.

На практике я заметил, что Chrome, FireFox и IE 7+ отправляют оба заголовка, если они доступны. Я также протестировал поведение при отправке измененных заголовков, о чем я уже подозревал, исходя из информации в RFC. Четыре клиента, которые я тестировал, отправляли условные запросы только в том случае, если страница (страницы) обновлялась или если это был первый раз, когда страница была запрошена текущим процессом.

Томас С. Триас
источник
1
Отличный ответ, Томас. Благодарим за предоставление официальной спецификации и обсуждение текущих реализаций браузеров.
dthrasher
1
Цитируя раздел 14.26, сервер НЕ ДОЛЖЕН выполнять запрошенный метод, если это не требуется, потому что дата модификации ресурса не соответствует дате, указанной в поле заголовка If-Modified-Since в запросе. Похоже, что If-Modified-Since имеет приоритет.
Vicary
20

Разве это не больше похоже на выражение «ИЛИ». В псевдокоде:

if ETagFromServer != ETagOnClient || LastModifiedFromServer != LastModifiedOnClient
   GetFromServer
else
   GetFromCache
Гидеон
источник
4
Я думаю, что последнюю измененную метку времени следует сравнивать по-другому, например: if ETagFromServer! = ETagOnClient || LastModifiedFromServer> LastModifiedOnClient
RoyM
Это оператор AND, потому что ETag может быть слабым, и в этом случае у вас может быть семантически эквивалентный объект, а затем вы вернетесь к последнему измененному заголовку. Рассмотрим ситуацию, когда изображение может быть перекодировано, и мы хотим сказать, что оригинал и перекодирование совпадают, несмотря на то, что они не идентичны по байтам. В этом случае мы хотим использовать последнее изменение в качестве запасного варианта, и именно поэтому они ОБЕИ должны быть последовательными
ParoX
8

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

Почему? Рассмотрим случай, когда оператор сервера отменяет плохую версию ресурса. Восстановленная версия СТАРШАЯ, но верная.

Клиент должен использовать версию, предлагаемую в настоящее время сервером; он может использовать кешированную версию, только если она такая же. Таким образом, сервер должен проверять равенство, а не «новее».

AccuracyInReponses
источник