10

I'm using node.js 0.6.18, and the following code makes node.js close the TCP connection between every two requests (verified with strace on Linux). How do I make node.js reuse the same TCP connection for multiple HTTP requests (i.e. keep-alive)? Please note that the webserver is capable of keep-alive, it works with other clients. The webserver returns a chunked HTTP response.

var http = require('http');
var cookie = 'FOO=bar';
function work() {
  var options = {
      host: '127.0.0.1',
      port: 3333,
      path: '/',
      method: 'GET',
      headers: {Cookie: cookie},
  };
  process.stderr.write('.')
  var req = http.request(options, function(res) {
    if (res.statusCode != 200) {
      console.log('STATUS: ' + res.statusCode);
      console.log('HEADERS: ' + JSON.stringify(res.headers));
      process.exit(1)
    }
    res.setEncoding('utf8');
    res.on('data', function (chunk) {});
    res.on('end', function () { work(); });
  });
  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
    process.exit(1);
  });
  req.end();
}
work()
pts
  • 80,836
  • 20
  • 110
  • 183
  • were you able to ever figure this out? – Jim Rubenstein Aug 29 '12 at 00:34
  • 7
    you may want to be aware that calling work() will create a stack memory leak. This is because every end event will add a new call to work(), never releasing the stack unless every call's end event is complete. To work around this, you may want to push work() out of scope by calling "process.nextTick(work);". This will allow scope of the end handler to terminate. – thesmart Dec 10 '12 at 22:42

2 Answers2

12

I was able to get this to work (verified with strace) by creating an http.Agent and setting its maxSockets property to 1. I don't know if this is the ideal way to do it; however, it does meet the requirements. One thing that I did notice is that what the docs claimed about http.Agent behavior did not accurately describe how it worked in practice. Code below:

var http = require('http');
var cookie = 'FOO=bar';
var agent = new http.Agent;
agent.maxSockets = 1;

function work() {
  var options = {
      host: '127.0.0.1',
      port: 3000,
      path: '/',
      method: 'GET',
      headers: {Cookie: cookie},
      agent: agent
  };
  process.stderr.write('.')
  var req = http.request(options, function(res) {
    if (res.statusCode != 200) {
      console.log('STATUS: ' + res.statusCode);
      console.log('HEADERS: ' + JSON.stringify(res.headers));
      process.exit(1)
    }
    res.setEncoding('utf8');
    res.on('data', function (chunk) {});
    res.on('end', function () { work(); });
  });
  req.on('error', function(e) {
    console.log('problem with request: ' + e.message);
    process.exit(1);
  });
  req.end();
}
work()

EDIT: I should add that I did my testing with node.js v0.8.7

Charles Hooper
  • 2,739
  • 1
  • 19
  • 16
  • Maybe it doesn't concern exactly about the top question but your code solved my problem. I was trying set a cookie and a refer 'directly' inside options, but now I'm setting it on the headers:{} and know my htttp/get/cookies request are working fine. Thanks! – user1321759 Apr 02 '14 at 02:40
7

you can just set:

http.globalAgent.keepAlive = true
Krishna Srinivas
  • 1,620
  • 1
  • 13
  • 19