重试-在 HTTP 响应头之后-它会影响什么吗?

如果我想礼貌地拒绝网站上的服务,由于临时过载,HTTP 响应 503服务暂停似乎是合适的。该规范提到发送带有503的 之后再试头。

有什么意义吗? Retry-after 会影响什么吗? 浏览器会关注它吗?

53005 次浏览

据我所知,没有浏览器会关注 Retry-after头文件。代理和缓存可能会,但是

显然,一些浏览器现在包含了对 Retry-After的某种程度的支持(尽管最好的情况下支持仍然有问题)。我不完全相信在浏览器中这样做的好处; 通常,缓存失败被认为是一个坏主意。但是如果你知道你什么时候会再次接受请求,告诉客户也无妨。(但是,如果您比预期更早地恢复,那么任何真正尊重标题的程序都应该假设——并报告——站点仍然处于关闭状态。)

最明显的好处是,似乎 Googlebot (可能还有其他蜘蛛)会注意页眉,如果页眉在那里的话,这可以让它在一段时间内不索引页面。

尽管如此... ... 如果添加起来很简单,而且您可以对服务何时可用做出合理的准确估计,那么就去做吧。不过我不建议你特意这么做。无论如何,这只是一个建议,如果把错误的时间放在那里会导致更多的问题,而不是完全不包括头球。

我认为这是一个先有鸡还是先有蛋的问题: 目前没有浏览器实现 Retry-after,因为没有网站愿意这样做。在我看来,继续把它作为一种服务发送给用户。如果他们选择的网络浏览器没有实现它,那么这就是他们的浏览器没有给他们提供有用的信息。你做到了!

当我想要实现那些具有多个相互竞争的实现的标准时,我总是试图坚持这些标准,而不去关注不同的实现(除非我特别想要模拟一个实现,比如 cURLing,但是把我的头伪装成 Web 浏览器的样子)。否则,我们最终得到的就是事实上的标准,如果你还记得 IE 占主导地位的日子,你就不会想要这样的标准了!

重试后报头的当前状态

自从最初提出这个问题以来,重试后头在客户机和服务器中的实现发生了一些变化。所以我想提供一个最新的答案。

首先,RFC2616,第14.37节后重试声明:

Retry-After response-header 字段可以用于503(服务不可用)响应,以指示请求客户端预期服务不可用的时间。

...

使用它的两个例子是

  Retry-After: Fri, 31 Dec 1999 23:59:59 GMT
Retry-After: 120

在后一个示例中,延迟为2分钟。

支持客户端和服务器软件

下面是代码存储库提交消息、公告和有关各种软件中的 重试后头的文档。

铬/铬

2012年11月22日,一段代码提交了日志消息: 添加了检测超时和 Retry-After HTTP header 的使用。

Mozilla/Firefox

代码在2012年3月27日提交,日志消息是: 实现对5xxs、 X-Weave-Backoff、 Retry-After 的处理。此外,在他们的 Mercurial 存储库中还有 另外三次提到 Retry-After 标题

Bug 最初是在2004年1月6日提交的,标题为 重试-忽略使用 HTTP503响应发送之后的操作

谷歌机器人

谷歌网站管理员中心博客的一篇关于处理网站停机的文章提到了 Retry-After 头可用于确定何时重新抓取 URL

Bingbot/Msnbot

找不到任何正式的 Retry-After 支持文档。然而,在随机的论坛中有一些提到在503响应中使用这个标题来限制微软的机器人。

Nginx

Add _ header 指令指出:

如果响应代码等于200、201、204、206、301、302、303、304或307,则将指定字段添加到响应标头。

因此,要使用 version 为503响应添加 Retry-After 头:

  • 1.7.4及更早版本,使用第三方模块,如 更多标题

  • 1.7.5及更高版本中,将 always参数附加到 add_header指令。

阿帕奇人

与 Nginx 不同,Apache头文件没有表明它不能在503响应上发送 Retry-After 头。然而,关于非2xx 的回复,文件指出:

向本地生成的非成功(非2xx)响应(如重定向)添加头,在这种情况下,最终响应中始终只使用与之对应的表。

下面是一个 回答我,它为503个响应设置了一个 Retry-After 头,其中包含 一直都是条件,正如文档所建议的那样。

AskApache 的一篇文章提供了如何使用带有 Retry-After 头的503响应进行 命令搜索引擎返回的其他配置示例。

客户测试

我编写了一个 Ruby 服务器,它只返回一个503响应,Retry-After 头部设置为10秒,主体包含一个随机数。

require 'sinatra'


get '/' do
headers 'Content-Type' => 'text/plain', 'Retry-After' => '10'
status 503
body rand(1000).to_s
end

我是通过:

  • 使用 Chromium 44、 Firefox-ESR 38和 Seamonkey 2.33,
  • 使用 Chrome 47和 Safari 6.1的 Mac OSX 10.7.5,
  • 使用 Chrome 48、 Firefox 41和 Edge 25的 Windows 10。

我期望这些浏览器在10秒后自动刷新 URL 并显示一个新的随机数。然而,所有的浏览器都没有重试,甚至在几分钟之后。我尝试了越来越短的重试-后期以及与相同的结果。服务器访问日志证实这些浏览器都没有重试过。

另外,在 Retry-After 周期之前的“软”刷新会立即重新获取 URL。因此 Retry-After 标头不能用于限制“刷新快乐”用户。我之所以提到这一点,是因为我在一些论坛上看到,这个标题可以用来限制不耐烦的用户敲打您的网站。

顺便说一句,“软”刷新在超时期限之前不执行任何操作似乎是合乎逻辑的,但是“硬”或缓存绕过刷新将忽略任何超时并立即重新获取 URL。

结论

重试后头部的支持在客户端和服务器上似乎仍然有些粗略。尽管如此,如果不难配置的话,为503响应设置重试超时是一个好主意。

即使 Googlebot 是唯一支持页眉的客户端,并且在超时后重试,它也可以防止你的页面被去索引——而不是404,500,502或504的响应。

如果希望在 X 时间后发送自动刷新,可以发送

Refresh: 120; url=http://your_url.com

在 PHP 中:

header("Refresh: "    .$retry_time."; url=". $url);

要刷新当前页面,可以使用 $_SERVER["REQUEST_URI"]作为 $url。

我在 Opera、 Firefox 和 Internet Explorer 的不同版本中成功测试了这个头文件。

这个头部甚至可以刷新二进制内容,比如图像(但是只有当直接加载的地方或者在一个帧中-IMG-Tag 不会重新加载时)。