超时POST请求的浏览器重试行为不一致

时间:2013-03-01 10:02:25

标签: node.js http google-chrome

当由于超时而没有来自服务器的响应时,我偶尔会遇到POST请求的重试。所有现代浏览器都具有幂等请求的重试逻辑(GET,HEAD等),但我无法推断为什么它会发生在POST请求中。

我正在使用一个带有3个路由和chrome浏览器的简单node.js服务器来测试这种情况。

/       : gives a html page with jquery and code snippets to fire ajax requests
/hi     : gives a text response 'hello'
/sleep  : request will timeout without any response 

默认情况下,node.js http服务器会在2分钟后超时请求。

retry.js

var http = require('http');
var server = http.createServer();

server.on('request', function(req, res) {
    console.log(new Date() + ' ' + req.method + ' request on ' + req.url);

    if (req.url === '/sleep') {
        console.log('!!! sleeping');
    } else if (req.url === '/') {
        html = "$.post('/hi', {'for':'server'}, function() { console.log(arguments) } ).error(function() { console.log(arguments) })";
        html += "<br><br>";
        html += "$.post('/sleep', {'for':'infinite'}, function() { console.log(arguments) } ).error(function() { console.log(arguments) })";
        html += '<script src="http://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>';

        res.writeHead(200, {'Content-Type': 'text/html'});
        res.end(html);
    } else {
        res.writeHead(200, {'Content-Type': 'text/plain'});
        res.end('hello');
    }
});

server.listen(2020);
console.log('server listening on port 2020');

运行它

$ node retry.js 
server listening on port 2020

1

Load this page in browser http://localhost:2020

Fri Mar 01 2013 12:21:59 GMT+0530 (IST) GET request on /
Fri Mar 01 2013 12:21:59 GMT+0530 (IST) GET request on /favicon.ico

2

从开发控制台,使用jquery

向/ hi发出ajax POST请求
$.post('/hi', {'for':'server'}, function() { console.log(arguments) } ).error(function() { console.log(arguments) })
  

Fri Mar 01 2013 12:22:05 GMT + 0530(IST)POST请求/ hi

3

将一个POST请求发送到/ sleep,导致2分钟后重试,4分钟后出错。

$.post('/sleep', {'for':'infinite'}, function() { console.log(arguments) } ).error(function() { console.log(arguments) })

服务器日志显示2个请求

Fri Mar 01 2013 12:22:21 GMT+0530 (IST) POST request on /sleep
!!! sleeping
Fri Mar 01 2013 12:24:21 GMT+0530 (IST) POST request on /sleep
!!! sleeping

再次射击,在2分钟内出错而不进行任何重试。

Fri Mar 01 2013 12:30:01 GMT+0530 (IST) POST request on /sleep
!!! sleeping ?

在我们向/ hi(或任何其他网址)发出导致响应的请求之前,不会重试。并且只有一个后续请求/ sleep才会重试。

在浏览器中,网络选项卡显示类似

的模式
/hi - success 
/sleep - cancelled - 4 mins (retry happens)
/sleep - cancelled - 2 mins (no retry)
/sleep - cancelled - 2 mins (no retry)
/hi - success 
/sleep - cancelled - 4 mins (retry happens)
/sleep - cancelled - 2 mins (no retry)
/sleep - cancelled - 2 mins (no retry)

问题

虽然我们需要设计我们的Web应用程序以容忍这些额外请求(通过浏览器或任何其他中介),但这种不一致的浏览器重试看起来很奇怪。我在chrome(v16&amp; v24)&amp; Firefox浏览器。

有人可以帮我理解超时非幂等请求背后的浏览器重试逻辑吗?

其他相关的stackoverflow问题

What happens when no response is received for a request? I'm seeing retries

1 个答案:

答案 0 :(得分:19)

浏览器在从服务器接收响应之前关闭连接时重试请求(包括POST)。这在HTTP 1.1 Spec Section 8.2.4中定义。