37

是否有 HTTP 状态代码来指示客户端再次执行相同的请求?

我面临的情况是服务器在处理请求时必须“等待”锁消失。但是当锁消失时,请求可能会接近它的超时限制。因此,相反,一旦锁定清除,我想指示客户端再次执行相同的请求。

我想出的最好的方法是将 HTTP 307 发送到同一位置,但我担心某些浏览器可能不会接受这一点(重定向循环检测)。

4

2 回答 2

40

当服务器无法处理请求时,正确的响应是503 Service Unavailable。如果条件是临时的,就像您的情况一样,您可以设置Retry-After标头以让客户端知道在重试之前应该等待多长时间。

但是,这不会强制浏览器再次执行请求 - 这是您需要在 javascript 中自己处理的事情。例如,以下是在 jquery 中执行重试 ajax POST 请求的方式:

function postData() {
  $.ajax({
    type: 'POST',
    url:  '503.php',
    success: function() {
      /*
         Do whatever you need to do here when successful.
      */
    },
    statusCode: {
      503: function(jqXHR) {
        var retryAfter = jqXHR.getResponseHeader('Retry-After');
        retryAfter = parseInt(retryAfter, 10);
        if (!retryAfter) retryAfter = 5;
        setTimeout(postData, retryAfter * 1000);
      }
    }
  });
}

请注意,上述代码仅支持Retry-After以秒为单位指定重试延迟的标头。如果您想支持需要更多工作的日期。在生产代码中,我还建议使用某种计数器,以确保您不会永远重试。

至于使用 307 状态码自动重复请求,我认为这不是一个好主意。即使您添加了一个重试参数来绕过浏览器循环检测(感觉就像一个可怕的黑客攻击),它仍然无法处理 POST 请求。来自RFC2616

如果收到 307 状态代码以响应 GET 或 HEAD 以外的请求,则用户代理不得自动重定向请求,除非用户可以确认。

虽然已知某些浏览器会忽略此要求,但这绝对是不正确的,也不是您想要依赖的东西。

如果你没有使用 POST 请求,你几乎肯定应该使用。请记住,GET 请求不应有任何副作用,并且默认情况下响应将被缓存。从您的问题的描述来看,听起来您的请求很可能正在做一些有副作用的事情。

于 2013-07-29T22:30:57.167 回答
2

使用 307 重定向,但添加重试计数器:

http://path/to/server?retry=3

这将使每次重试时的 URL 都不同,从而防止循环检测。服务器可以检查重试是否达到限制,并在发生错误时中止,因此用户不会永远等待。

于 2013-07-25T15:22:37.543 回答