Skip to content

Instantly share code, notes, and snippets.

@Jimbly
Created April 9, 2012 21:54
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Jimbly/2346805 to your computer and use it in GitHub Desktop.
Save Jimbly/2346805 to your computer and use it in GitHub Desktop.
Adding keep alive for https connections
function addKeepAliveTimeout(agent) {
function fail(msg) {
console.warn(msg + ', node version: ' + process.version);
return agent;
}
// Check it's what we expect
var old_listeners = agent.listeners('free');
if (!old_listeners || old_listeners.length !== 1) {
return fail('Unexpected lacking "free" listener');
}
var expected_listener =
'function (socket, host, port) {\n'
+ ' var name = host + \':\' + port;\n'
+ ' if (self.requests[name] && self.requests[name].length) {\n'
+ ' self.requests[name].shift().onSocket(socket);\n'
+ ' if (self.requests[name].length === 0) {\n'
+ ' // don\'t leak\n'
+ ' delete self.requests[name];\n'
+ ' }\n'
+ ' } else {\n'
+ ' // If there are no pending requests just destroy the\n'
+ ' // socket and it will get removed from the pool. This\n'
+ ' // gets us out of timeout issues and allows us to\n'
+ ' // default to Connection:keep-alive.\n'
+ ' socket.destroy();\n'
+ ' }\n'
+ ' }';
var expected_addRequest =
'function (req, host, port) {\n'
+ ' var name = host + \':\' + port;\n'
+ ' if (!this.sockets[name]) {\n'
+ ' this.sockets[name] = [];\n'
+ ' }\n'
+ ' if (this.sockets[name].length < this.maxSockets) {\n'
+ ' // If we are under maxSockets create a new one.\n'
+ ' req.onSocket(this.createSocket(name, host, port));\n'
+ ' } else {\n'
+ ' // We are over limit so we\'ll add it to the queue.\n'
+ ' if (!this.requests[name]) {\n'
+ ' this.requests[name] = [];\n'
+ ' }\n'
+ ' this.requests[name].push(req);\n'
+ ' }\n'
+ '}';
if (old_listeners[0].toString() !== expected_listener) {
console.log(require('util').inspect(old_listeners[0].toString()));
return fail('Listener not defined as expected');
}
if (agent.addRequest.toString() !== expected_addRequest) {
console.log(require('util').inspect(agent.addRequest.toString()));
return fail('addRequest not defined as expected');
}
console.log('Using wrapped listener agent');
assert.ok(!agent.free_sockets); // We're adding this field
// Remove old listener
agent.removeAllListeners('free');
agent.free_sockets = {};
agent.on('free', function(socket, host, port) {
var name = host + ':' + port;
if (agent.requests[name] && agent.requests[name].length) {
agent.requests[name].shift().onSocket(socket);
if (agent.requests[name].length === 0) {
// don't leak
delete agent.requests[name];
}
} else {
// save the socket for at least a little while
var obj = {
socket: socket
};
obj.timeout_id = setTimeout(function() {
var idx = agent.free_sockets[name].indexOf(obj);
Assert.ok(idx !== -1);
agent.free_sockets[name].splice(idx, 1);
if (!agent.free_sockets[name].length) {
delete agent.free_sockets[name];
}
socket.destroy();
}, 10000);
if (!agent.free_sockets[name]) {
agent.free_sockets[name] = [];
}
agent.free_sockets[name].push(obj);
}
});
agent.addRequest = function(req, host, port) {
var name = host + ':' + port;
if (this.free_sockets[name] && this.free_sockets[name].length) {
// Has a free socket, use it
var obj = this.free_sockets[name].shift();
clearTimeout(obj.timeout_id);
req.onSocket(obj.socket);
} else {
if (!this.sockets[name]) {
this.sockets[name] = [];
}
if (this.sockets[name].length < this.maxSockets) {
// If we are under maxSockets create a new one.
req.onSocket(this.createSocket(name, host, port));
} else {
// We are over limit so we'll add it to the queue.
if (!this.requests[name]) {
this.requests[name] = [];
}
this.requests[name].push(req);
}
}
};
return agent;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment