“ Vary:接受” HTTP标头的功能是什么?


93

我使用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


1
坦白说-不要打扰。撇开该站点上实现上的缺陷,通过使用XML内容类型来获得收益的唯一机会是,当您做无法在text / html中完成的事情时-如果您正在做所有事情正在关闭Doctype和xmlns,那么您将不会做这些事情。坚持使用text / html。因此,您最好还是坚持使用HTML 4.01。
昆汀,

是的,我理解这一点,并且我认为类似的“问题”在Web开发中经常出现。感谢规范/ RFC中的“应该”!
AlexV

2
在考虑使用VARY之前,您可能应该阅读以下内容:blogs.msdn.com/ieinternals/archive/2009/06/17/…
EricLaw 2010年

1
该视频很好地说明了Vary:标题。
Kannan Mohan 2015年

Answers:


94
  • cache-control消息头是HTTP服务器来告诉缓存代理的一个响应的“新鲜”的主要机制。(即,将响应存储在缓存中的时间/时间长短)

  • 在某些情况下,cache-control指令不足。HTTP工作组的讨论记录在这里,描述了仅随语言而变化的页面。这不是 variable标头的正确用例,但是上下文对于我们的讨论很有价值。(尽管我相信Vary标头可以解决这种情况下的问题,但是有一种更好的方法。)从该页面:

Vary 仅适用于代理复制服务器将无法完成或绝望的情况。

一个人为的例子:

您的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日更新:

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

首先,来自杰出的EricLaw,有关Internet Explorer使用Vary标头的行为以及它对开发人员提出的一些挑战: Vary Header防止IE中的缓存。简而言之,IE(pre IE9)不会缓存使用Vary头的任何内容,因为请求缓存不包括HTTP请求头。EricLaw(现实世界中的Eric Lawrence)是IE团队的程序经理。

第二篇来自Eran Medan,是有关Chrome中与Vary相关的意外行为的持续讨论:后备不能正确处理Vary标头。它与IE的行为有关,但Chrome开发人员采用了不同的方法-尽管这似乎不是故意的选择。


3
请注意,结合Chrome中的后退浏览器按钮,此错误会引起一场火焰大战(由于某种原因现在无法修复)code.google.com/p/chromium/issues/detail?id=94369
Eran棉兰2012年

6
@EranMedan Chrome错误已得到修复。

59

Vary: Accept简单地说,响应是基于Accept请求中的标头生成的。具有不同Accept标头的请求可能会得到不同的响应。

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

对于HTTP缓存,这意味着必须格外小心地缓存响应。只有标题完全相同的情况下,Accept它才是有效的匹配。

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


是“可能得到”还是“应该得到”?
Pacerier 2011年

6
@Pacerier“可能得到”是正确的。Vary: Accept并不意味着每个可能的不同Accept标头值都会产生不同且唯一的响应。这仅意味着不同的Accept标头可能会产生不同的响应。
杰森·奥伦多夫


2

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

  • 影像宽度
  • 视口宽度
  • 浏览器支持的编码类型(想想WebP)
  • 下行链路(实质上是网络速度)

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

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

Vary: Accept

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

Vary: Accept, Width

或者,如果服务器支持所有客户端提示规范,则标头将类似于:

Vary: Accept, DPR, Width, Save-Data, Downlink
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.