什么优先:ETag 或 Last-Modified HTTP 标头?

Posted

技术标签:

【中文标题】什么优先:ETag 或 Last-Modified HTTP 标头?【英文标题】:What takes precedence: the ETag or Last-Modified HTTP header? 【发布时间】:2010-10-23 20:59:43 【问题描述】:

对于两个后续请求,如果其中一个发生更改,以下两个标头中哪一个会被浏览器赋予更大的权重:ETag 或 Last-Modified?

【问题讨论】:

【参考方案1】:

根据RFC 2616 第 13.3.4 节,HTTP 1.1 客户端必须在任何缓存条件请求中使用 ETag,如果 ETag 和 Last Modified 都存在,则它应该同时使用两者。 ETag 标头被认为是一个强验证器(参见第 13.3.3 节),除非服务器明确声明为弱,而 Last Modified 标头被认为是弱的,除非它与 Date 标头之间存在至少一分钟的差异。但是请注意,服务器不需要发送任何一个(但它应该,如果可以的话)。

请注意,客户端不会检查标头是否已更改;它只是在下一个条件请求中盲目地使用它们;由服务器评估是否发送请求的内容或 304 Not Modified 响应。如果服务器只发送一个,那么客户端将单独使用那个(尽管只有强验证器对 Range 请求有用)。当然,中间缓存(除非它们已通过缓存控制指令阻止缓存)和服务器也可以自行决定它们将如何作用于标头; RFC 规定,如果验证器不一致,它们不得返回 304 Not Modified,但由于标头值是由服务器生成的,因此它有很大的余地。

在实践中,我注意到 Chrome、FireFox 和 IE 7+ 都会发送两个标头(如果可用)。我还测试了发送修改后的标头时的行为,我已经从 RFC 中的信息中怀疑了这一点。我测试的四个客户端仅在页面被刷新或当前进程第一次请求页面时才发送条件请求。

【讨论】:

很好的答案,托马斯。感谢您提供官方规范并讨论当前的浏览器实现。 引用第 14.26 节的内容,服务器不得执行请求的方法,除非需要这样做,因为资源的修改日期无法与中的 If-Modified-Since 标头字段中提供的日期匹配请求。 看起来 If-Modified-Since 优先。【参考方案2】:

这不是更像一个“OR”表达式吗?在伪代码中:

if ETagFromServer != ETagOnClient || LastModifiedFromServer != LastModifiedOnClient
   GetFromServer
else
   GetFromCache

【讨论】:

我认为最后修改的时间戳应该进行不同的比较,如:if ETagFromServer != ETagOnClient || LastModifiedFromServer > LastModifiedOnClient 这是一个 AND 语句,因为 ETag 可能很弱,在这种情况下,您可以拥有一个语义等价的实体,然后您会退回到最后修改的标头。考虑一个图片可以重新编码的情况,我们想说原始和重新编码是相同的,尽管它们不是字节相同的。在这种情况下,我们希望使用 last-modified 作为后备,这就是为什么它们都必须一致【参考方案3】:

=!是正确的比较运算符。客户端需要保留从服务器接收到的文字字符串,因为转换可能会产生微小的差异。您不能假设“更新更好”。

为什么?考虑服务器操作员恢复资源的错误版本的情况。还原的版本较旧 - 但正确。

客户端必须使用服务器当前提供的版本;只有在相同的情况下,它才能使用缓存版本。因此,服务器必须检查相等性,而不是“更新”。

【讨论】:

以上是关于什么优先:ETag 或 Last-Modified HTTP 标头?的主要内容,如果未能解决你的问题,请参考以下文章

[转]技术心得Last-Modified,Etag,Expire区别

HTTP 缓存相关的响应头信息

缓存验证Last-Modified和Etag的使用

http-headers头

浏览器缓存之Expires Etag Last-Modified max-age详解

Last-Modified If-Modified-Since ETag If-None-Match