Подтвердить что ты не робот

Непоследовательное поведение при попытке повторить попытку браузера при запросах POST

Я периодически провожу запросы на POST-запрос, когда от сервера не возникает ответа из-за таймаута. У всех современных браузеров есть логика повтора для идемпотентных запросов (GET, HEAD и т.д.), Но я не могу объяснить, почему это происходит для запроса POST.

Я тестирую этот случай, используя простой сервер node.js с тремя маршрутами и браузером Chrome.

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

Из консоли Dev, запустите ajax POST-запрос/hi с помощью jquery

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

Пт Mar 01 2013 12:22:05 GMT + 0530 (IST) Запрос POST on/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 (или любой другой 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)

Вопрос

Хотя нам нужно разработать наше веб-приложение, чтобы терпеть эти дополнительные запросы (либо браузерами, либо любыми другими посредниками), эти непоследовательные попытки браузера выглядят странно. Я наблюдал это поведение в chrome (v16 и v24) и firefox.

Может ли кто-нибудь помочь мне понять логику повторной попытки браузера за вычетом не-идемпотентных запросов?

Другие относящиеся к этому вопросы, касающиеся stackoverflow

Что произойдет, если ответ не получен для запроса? Я вижу повторы

4b9b3361

Ответ 1

Браузеры повторно запрашивают запросы (включая POST), когда соединение закрывается, прежде чем получать ответ от сервера. Это определено в HTTP 1.1 Spec Section 8.2.4.