psyb0rg
psyb0rg

Reputation: 85

Nodejs HTTPS client timeout not closing TCP connection

I need to close http connection if they take longer than 3s, so this is my code:

var options = {
  host: 'google.com',
  port: '81',
  path: ''
};

callback = function(response) {
  var str = '';

  response.on('data', function (chunk) {
    str += chunk;
  });

  response.on('end', function () {
    console.log(str);
  });

  response.on('error', function () {
    console.log('ERROR!');
  });
}

var req = https.request(options, callback);

req.on('socket', function(socket) {
  socket.setTimeout(3000);
  socket.on('timeout', function() {
    console.log('Call timed out!');
    req.abort();
    //req.end();
    //req.destroy();
  });
});

req.on('error', function(err) {
  console.log('REQUEST ERROR');
  console.dir(err);
    req.abort();
    //req.end();
});

req.end();

This is what I get after 3s:

Call timed out!
REQUEST ERROR
{ [Error: socket hang up] code: 'ECONNRESET' }

Using a watch on lsof | grep TCP | wc -l I can see that the TCP connection remains open, even after receiving the 'timeout' event. After an eternity, I get this and the connection is closed:

REQUEST ERROR
{ [Error: connect ETIMEDOUT] code: 'ETIMEDOUT', errno: 'ETIMEDOUT', syscall: 'connect' }

Does anyone know why this is happening? Why does calling req.abort() or req.end() or req.destory() not close the connection? Is it because I'm setting the timeout on the socket instead of the actual HTTP call? If yes, how do I close the connection?

Upvotes: 3

Views: 2321

Answers (1)

javierfdezg
javierfdezg

Reputation: 2107

you need to set the timeout on the connection:

req.connection.setTimeout(3000);

This timeout will change the socket status from ESTABLISHED to FIN_WAIT1 and FIN_WAIT2.

In Ubuntu there is a default timeout of 60 seconds for FIN_WAIT socket status, so the total time for the socket to close is 63 seconds if it doesn't receive any traffic. If the sockets receive traffic, the timeouts will start over.

If you need to close the socket within 3 seconds, I guess you have to set the connection timeout to 3000ms and lower the kernel tcp fin wait timeout.

Upvotes: 1

Related Questions