重试 – HTTP响应头后 – 它影响什么?

如果我想礼貌地拒绝网站上的服务,由于临时过载,HTTP响应503服务不可用似乎是合适的。 该规范提到用503发送一个Retry-after头。

有什么意思吗? Retry-After会影响到什么吗? 浏览器是否注意到它?

据我所知,没有浏览器注意到Retry-after标题。 代理和caching可能,但是

显然,一些浏览器现在包含对Retry-After某种级别的支持(虽然支持仍然是最好的)。 我并不完全相信在浏览器中这样做的好处, 一般来说,caching失败是一个坏主意。 但如果你知道什么时候你会再次接受请求,告诉客户不能伤害。 (如果你早于预期地回来,那么任何真正尊重标题的程序都应该假设 – 并且报告 – 该网站仍然在运行。)

最明显的好处是,似乎Googlebot(也可能是其他的蜘蛛)会关注标题,如果它在那里,可以防止一段时间的页面不索引。

尽pipe如此,如果增加一些微不足道的东西,你可以拿出一个合理准确的估计服务何时可用的方法。 尽pipe如此,我不build议你不要这样做。 无论如何,这只是一个build议,把错误的时间放在那里可能会导致更多的问题,而不是不包括标题。

Retry-After标题的当前状态

自从最初发布这个问题以来,客户端和服务器中Retry-After头的实现在最近几年中有所变化。 所以我想我会提供一个更新的答案。

首先,RFC 2616, 第14.37节Retry-After声明:

Retry-After response-header字段可与503(服务不可用)响应一起使用,以指示服务对于请求客户端来说预计不可用的时间。

两个使用的例子是

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

在后面的例子中,延迟是2分钟。

支持客户端和服务器软件

以下是各种软件中的Retry-After标题的代码库提交消息,通告和文档。

镀铬/铬

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

火狐浏览器

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

一个错误最初是在2004年1月6日提交的,标题为Retry-HTTP3发送响应后被忽略 。

Googlebot的

Google网站pipe理员中央博客有关处理网站停机的文章提到, Retry-After标题可用于确定何时重新抓取url 。

Bingbot / MSNBot会

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

Nginx的

add_header指令指出:

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

因此,要使用以下版本为503响应添加Retry-After标题:

  • 1.7.4及更早版本,使用第三方模块,比如Headers More 。

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

阿帕奇

与Nginx不同的是,Apache 头文件并没有表明它不能在503响应中发送Retry-After头。 关于非2xx回应,文件陈述:

向本地生成的非成功(非2xx)响应(例如redirect)添加头,在这种情况下,只有总是对应的表被用于最终响应。

正如文件build议的,这是一个SO答案 ,它为503个答复设置了一个Retry-After头。

AskApache文章提供了其他configuration示例, 指导如何指示search引擎使用带有Retry-After标头的503响应返回 。

客户端testing

我写了一个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的OpenBSD 5.8,
  • 使用Chrome 47和Safari 6.1的Mac OSX 10.7.5,
  • Windows 10使用Chrome 48,Firefox 41和Edge 25。

我期待这些浏览器在10秒后自动刷新URL并显示一个新的随机数。 但是,即使几分钟后,所有的浏览器都不会重试。 我尝试了更短,更长的Retry-After时期以及相同的结果。 服务器访问日志确认没有从这些浏览器的任何重试。

此外,在“重试后”时间段之前的“软”刷新会立即重新捕获URL。 因此,Retry-After标题不能用于节制“更新快乐”的用户。 我提到这一点是因为我在一些论坛上看到,这个头文件可以用来扼杀不耐烦的用户打击你的网站。

作为一个方面说明,对于“软”刷新在超时期限之前没有动作似乎是合乎逻辑的,但是“硬”或者高速caching绕过刷新将忽略任何超时并立即重新获取URL。

结论

在客户端和服务器上对Retry-After头的支持仍然看起来有点粗略。 尽pipe如此,如果configuration不难,为503个响应设置重试超时值是个好主意。

即使Googlebot是支持标题的唯一客户端,并且在超时期限后实际重试,它也可能会使您的页面不被删除索引 – 而不是404,500,502或504响应。

我认为这是一个鸡与鸡蛋的问题:没有浏览器目前实施重试 – 之后,因为没有网站打扰。 在我看来,继续作为服务发送给用户。 如果他们select的浏览器没有实现它,那么他们的浏览器就是不给他们有用的信息。 你做到了!

当要实现具有多个竞争实现的标准时,我总是试图遵守这些标准,而不是注意不同的实现(除非我特别试图模仿一个实现,比如cURLing,但是伪装我的头文件看起来像网页浏览器)。 否则,我们最终会达到事实上的标准,如果你还记得你不想要的IE浏览器霸主日!

如果你想在X时间后自动刷新,你可以发送一个

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

在PHP中:

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

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

我在不同版本的Opera,Firefox和Internet Explorer中testing了这个头文件。

这个头甚至用于刷新二进制内容像图像(但只有当直接加载或在框架中 – 一个IMG标签不能重新加载)。