当由于超时而没有来自服务器的响应时,我偶尔会重试 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 分钟后超时请求。
重试.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) })
2013 年 3 月 1 日星期五 12:22:05 GMT+0530 (IST) 在 /hi 上的 POST 请求
3
向 /sleep 发出 POST 请求,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 (或任何其他 url)发出请求并导致响应之前,它不会重试。并且重试仅针对一个随后的 /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 & v24) 和 firefox 中观察到了这种行为。
有人可以帮我理解超时非幂等请求背后的浏览器重试逻辑吗?