ChatGPT解决这个技术问题 Extra ChatGPT

“Vary: Accept” HTTP 标头的作用是什么?

我使用 PHP 来生成动态网页。如以下教程所述(参见下面的链接),当 $_SERVER['HTTP_ACCEPT'] 允许时,XHTML 文档的 MIME 类型应为“application/xhtml+xml”。由于您可以使用 2 个不同的 MIME(“application/xhtml+xml”和“text/html”)为同一页面提供服务,因此您应该将“Vary”HTTP 标头设置为“Accept”。这将有助于代理上的缓存。

链接:http://keystonewebsites.com/articles/mime_type.php

现在我不确定: header('Vary: Accept'); 的含义。我不太确定“Vary:Accept”究竟会做什么......

我找到的唯一解释是:

在 Content-Type 标头之后,一个 Vary 标头被发送到(如果我理解正确的话)告诉中间缓存,如代理服务器,文档的内容类型根据请求文档的客户端的功能而有所不同。 http://www.456bereastreet.com/archive/200408/content_negotiation/

任何人都可以给我这个标题的“真实”解释(带有那个值)。我想我了解以下内容: Vary: Accept-Encoding 其中代理上的缓存可能基于所服务页面的编码,但我不明白: Vary: Accept

坦率地说 - 不要打扰。撇开该站点上的实现缺陷不谈,您唯一能从使用 XML 内容类型服务中获益的时候是当您执行 text/html 中无法完成的事情时 - 如果您正在做的所有事情正在切换 Doctype 和 xmlns,那么您将不会做这些事情。坚持文本/html。就此而言,您不妨坚持使用 HTML 4.01。
是的,我理解这一点,我认为像这样的“问题”在 Web 开发中经常出现。感谢规范/RFC中的“应该”!
在考虑使用 VARY 之前,您可能应该阅读以下内容:blogs.msdn.com/ieinternals/archive/2009/06/17/…
This videoVary: 标头有很好的解释。

e
echox

缓存控制标头是 HTTP 服务器告诉缓存代理响应的“新鲜度”的主要机制。 (即,如何/如果多长时间将响应存储在缓存中)

在某些情况下,缓存控制指令是不够的。 HTTP 工作组的讨论在此处存档,描述了仅随语言变化的页面。这不是可变标头的正确用例,但上下文对我们的讨论很有价值。 (虽然我相信 Vary 标头会在这种情况下解决问题,但有更好的方法。)从该页面:

Vary 严格适用于代理无法复制服务器将执行的操作或过于复杂的情况。

RFC2616“Header-Field Definitions”从服务器的角度描述了头部的使用,从缓存代理的角度描述了 RFC2616“Caching Negotiated Responses”。它旨在指定一组确定请求唯一性的 HTTP 请求标头。

一个人为的例子:

您的 HTTP 服务器有一个很大的登录页面。您有两个具有相同 URL 的稍微不同的页面,具体取决于用户之前是否去过那里。您根据 Cookie 区分请求和用户的“访问次数”。但是——因为你的服务器的登陆页面太大了,如果可能的话,你希望中间代理缓存响应。

URL、Last-Modified 和 Cache-Control 标头不足以为缓存代理提供这种洞察力,但如果您添加 Vary: Cookie,缓存引擎会将 Cookie 标头添加到其缓存决策中。

最后,对于小流量、动态的网站——我一直认为简单的 Cache-Control: no-cache, no-storePragma: no-cache 就足够了。

编辑——更准确地回答您的问题:HTTP 请求标头“接受”定义了客户端可以处理的内容类型。如果您在同一个 URL 有两个相同内容的副本,仅在 Content-Type 上有所不同,则使用 Vary: Accept 可能是合适的。

12 年 9 月 11 日更新:

自最初发布此评论以来,我将包含几个出现在评论中的链接。它们都是 Vary 的真实示例(和问题)的极好资源:接受;如果您正在阅读此答案,则还需要阅读这些链接。

首先,来自杰出的 EricLaw,关于 Internet Explorer 使用 Vary 标头的行为以及它给开发人员带来的一些挑战:Vary Header Prevents Caching in IE。简而言之,IE(IE9 之前)不会缓存任何使用 Vary 标头的内容,因为请求缓存不包含 HTTP 请求标头。 EricLaw(现实世界中的 Eric Lawrence)是 IE 团队的项目经理。

第二个来自 Eran Medan,是关于 Chrome 中与 Vary 相关的意外行为的持续讨论:Backing doesn't handle Vary header correctly。这与 IE 的行为有关,除了 Chrome 开发人员采取了不同的方法——尽管这似乎不是一个深思熟虑的选择。


当心这与 Chrome 中的后退浏览器按钮一起使用时,对于这个错误有一种激烈的战争(现在由于某种原因不会修复)code.google.com/p/chromium/issues/detail?id=94369
@EranMedan Chrome 错误已被修复。
J
Jason Orendorff

Vary: Accept 只是表示响应是根据请求中的 Accept 标头生成的。具有不同 Accept 标头的请求可能会得到不同的响应。

(您可以看到链接的 PHP 代码查看 $HTTP_ACCEPT。这是 Accept 请求标头的值。)

对于 HTTP 缓存,这意味着必须格外小心地缓存响应。它只会对具有完全相同的 Accept 标头 的后续请求进行有效匹配。

现在,这仅在页面首先是可缓存的情况下才重要。默认情况下,PHP 页面不是。 PHP 页面可以通过发送某些标头(例如 Expires)将输出标记为可缓存。但是否以及如何做到这一点是一个不同的问题。


是“可能得到”还是“应该得到”?
@Pacerier“可能会”是正确的。 Vary: Accept 并不意味着每个可能的不同 Accept 标头值都会产生不同且唯一的响应。这仅意味着不同的 Accept 标头可能产生不同的响应。
K
Kannan Mohan

这个 google webmaster video 对 HTTP Vary 标头有很好的解释。


B
Brad Berger

实际上,即将推出大量新功能(并且已经在 Chrome 中)使 Vary 标头非常有用。例如,考虑 Client Hinting。例如,当与图像结合使用时,客户端提示允许服务器根据以下条件优化图像等资源:

图像宽度

视口宽度

浏览器支持的编码类型(想想 WebP)

下行链路(本质上是网络速度)

因此,支持这些功能的服务器将设置 Vary 标头来表明这一点。

Chrome 通过将“image/webp”设置为每个请求的 Vary 标头的一部分来宣传 WebP 支持。因此,如果浏览器支持,服务器可能会将图像重写为 WebP,因此代理需要检查标头以便不缓存 WebP 图像,然后将其提供给不支持 WebP 的浏览器。显然,如果您的服务器不这样做,那也没关系。因此,由于服务器的响应在 Accept 请求标头上有所不同,因此响应必须包含该标头,以免混淆代理:

Vary: Accept

另一个例子可能是图像宽度。在移动浏览器上,与从桌面浏览器查看时相比,对于响应式图像,Width 标头可能非常小。因此,在这种情况下,将 Width 添加到 Vary 标头对于代理不缓存小型移动版本并将其提供给桌面浏览器至关重要,反之亦然。在这种情况下,标头可能包括:

Vary: Accept, Width

或者在服务器支持所有客户端提示规范的情况下,标头将类似于:

Vary: Accept, DPR, Width, Save-Data, Downlink