Chrome / Firefox sends two POSTs under the hood exactly 5 seconds apart, only one call to receive Nodejs 8.0.0 server

NOTE. These are not optional options, and this is not an icon or anything else like that. These are actually 2 POSTS. To show this, screenshot below.

My specifications / versions:

  • macOS Sierra Version 10.12.3
  • Chrome version 61.0.3128.0 (Official Build) dev (64-bit)
  • Node v8.0.0

I have a server that uses setTimeout to wait 10 seconds before responding. I have an interface that does one POST on the server. Using wirehark, I can see that the browser actually does 2 POSTs, the second at t + 5. The server sees both of these POSTs and responds to both. The interface receives the result of only the second POST.

In the example below, you will see that the selection actually takes 15 seconds, not the 10 seconds you expect from a server timeout.

The call is CORS, and this only happens when the server takes more than 5 seconds to answer.

What is going on here and how can I stop it?

Here is the minimum playback:

server.js (run this with node)

var http = require("http");
// A counter for the requests
var counter = 0;

var server = http.createServer(function(request, response) {
  // Closure to prevent the request number from changing with the counter.
  (function(requestNumber) {
    console.log('Incoming:', request.method, "assigning number", requestNumber);

    // CORS headers
    response.writeHead(200, {
      "Content-Type": "application/json",
      "Access-Control-Allow-Methods": "GET,HEAD,PUT,POST,DELETE",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Headers": "authorization,content-type,expect",
    });

    // Respond to options immediately.
    if (request.method === "OPTIONS") {
      response.end()
    } else {
      // Otherwise simulate a long running process (db write whatever)
      setTimeout(function() {
        console.log('Timeout done, responding to request number', requestNumber);
        response.write(JSON.stringify({ number: requestNumber }));
        response.end();
      }, 10000);
    }
  }(counter++));
});

server.listen(8080);
console.log("Server is listening");
Run codeHide result

Call a call in the interface:

var start = new Date();
console.log('making call. Wait ~15 seconds for the result to come back');
fetch('http://localhost:8080', {
  headers: {
    Accept: 'application/json',
    'Content-Type': 'application/json',
  },
  method: 'post',
  mode: 'cors',
  body: JSON.stringify({ some: 'content' }),
}).then(result => result.json()).then(json => {
  console.log('result', json);
  console.log('call took:', (new Date() - start), 'seconds');
}).catch(err => {
  console.log('err', err);
});
Run codeHide result

Here is a screenshot of the server, front-end console, and wirehark traffic: enter image description here

And here is the network tab. You can see that the request β€œstopped” for 5 seconds. enter image description here

Some additional testing notes I made:

chrome firefox, . ( mac, chrome Version 60.0.3112.20 (Official Build) dev (64-)) , CORS, . jQuery ajax, , , . ( jQuery, , xhr , , .)

+4

Source: https://habr.com/ru/post/1679298/


All Articles