针对超时POST请求的浏览器重试行为不一致 [英] Inconsistent browser retry behaviour for timed out POST requests

查看:1045
本文介绍了针对超时POST请求的浏览器重试行为不一致的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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



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

  /:给出一个包含jquery和代码片段的html页面发送ajax请求
/ hi:给出文本响应'hello'
/ sleep:请求将超时而没有任何响应

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



retry.js



  var http = require('http'); 
var server = http.createServer();
$ b 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 + ='<脚本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('监听端口2020的服务器');



运行它



  $ node retry.js 
监听端口2020的服务器



1



 在浏览器中加载此页面http:// localhost:2020 

Fri Mar 01 2013 12:21 :59 GMT + 0530(IST)GET请求/
Fri Mar 01 2013 12:21:59 GMT + 0530(IST)/favicon.ico获取请求



2



在开发控制台中,使用jquery将ajax POST请求发送到/ hi


$ b $

  $。post('/ hi',{'for':'server'},function(){console.log(arguments) }).error(function(){console.log(arguments)})




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




3



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

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

服务器日志显示2个请求

 星期五Mar 01 2013 12:22:21 GMT + 0530(IST) POST请求/睡眠
!!!睡觉
Fri Mar 01 2013 12:24:21 GMT + 0530(IST)POST请求/睡觉
!!!睡觉

再次点火,2分钟内无任何重试错误。

 星期五Mar 01 2013 12:30:01 GMT + 0530(IST)POST请求/睡眠
!!!睡觉?



直到我们向/ hi(或任何其他网址)发出请求才会重试一个回应。



在浏览器中,网络选项卡显示的模式如



  / hi  - 成功
/睡眠 - 取消 - 4分钟(重试发生)
/睡眠 - 取消 - 2分钟(不重试)
/睡眠 - 取消 - 2分钟(不重试)
/ hi - 成功
/睡眠 - 取消 - 4分钟(重试发生)
/睡眠 - 取消 - 2分钟(不重试)
/睡眠 - 取消 - 2分钟(不重试)






虽然我们需要设计我们的web应用程序来容忍这些额外的请求(无论是浏览器还是其他中介),但这种不一致的浏览器重试看起来很奇怪。我曾在铬(v16& v24)& Firefox浏览器。

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

其他相关的stackoverflow问题



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

I am experiencing occasional retries for a POST request, when there is no response from server due to timeout. All modern browsers have retry logic for idempotent requests (GET, HEAD, etc) but I am unable to reason out why it happens for a POST request.

I am testing this case using a simple node.js server with 3 routes and chrome browser .

/       : 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 

By default, node.js http server times out a request after 2 minutes.

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');

run it

$ 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

From Dev console, fire an ajax POST request to /hi using jquery

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

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

3

Fire a POST request to /sleep, results in a retry after 2 mins and errors out after 4 mins.

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

server logs shows 2 requests

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

Firing it again, errors out in 2 mins without any retry.

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

It's not getting retried until we fire a request to /hi (or any other url) that results in a response. And retry happens for just one subsequent request to /sleep.

In browser, the network tab shows the pattern like

/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)


Question

Though we need to design our web app to tolerate these extra requests (either by browsers or any other intermediaries), this inconsistent browser retries looks weird. I had observed this behaviour in chrome (v16 & v24) & firefox.

Can someone help me to understand the browser retry logic behind timed out non-idempotent requests ?

Other relevant stackoverflow questions

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

解决方案

Browsers retry requests (including POSTs) when the connection is closed before receiving a response from the server. This is defined in the HTTP 1.1 Spec Section 8.2.4.

这篇关于针对超时POST请求的浏览器重试行为不一致的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆