当服务器由于超时而没有响应时,我偶尔遇到重试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分钟后使请求超时。
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
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
从开发控制台,使用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上发布请求
向/ 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 - 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中观察到了这种行为。
有人可以帮助我理解非幂等请求超时后的浏览器重试逻辑吗?
在关闭连接之前,浏览器会重试请求(包括POST),然后再收到服务器的响应。这在HTTP 1.1 Spec第8.2.4节中定义。