Skip to content

Commit

Permalink
feat: support Keep-Alive Header
Browse files Browse the repository at this point in the history
  • Loading branch information
fengmk2 committed Feb 27, 2018
1 parent 6237d09 commit 0af7cdf
Show file tree
Hide file tree
Showing 4 changed files with 77 additions and 0 deletions.
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ node_js:
- '4'
- '6'
- '8'
- '9'
script:
- npm run ci
after_script:
Expand Down
1 change: 1 addition & 0 deletions appveyor.yml
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ environment:
- nodejs_version: '4'
- nodejs_version: '6'
- nodejs_version: '8'
- nodejs_version: '9'

install:
- ps: Install-Product node $env:nodejs_version
Expand Down
20 changes: 20 additions & 0 deletions lib/urllib.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,6 +56,9 @@ var TEXT_DATA_TYPES = [

var PROTO_RE = /^https?:\/\//i;

// Keep-Alive: timeout=5, max=100
var KEEP_ALIVE_RE = /^timeout=(\d+)/i;

/**
* Handle all http request, both http and https support well.
*
Expand Down Expand Up @@ -455,6 +458,23 @@ exports.requestWithCallback = function requestWithCallback(url, args, callback)
err.res = response;
}

// only support agentkeepalive module for now
if (agent && agent.keepAlive && agent.freeSocketKeepAliveTimeout > 0 &&
res.headers.connection === 'keep-alive' && res.headers['keep-alive']) {
// adjust freeSocketKeepAliveTimeout on the socket
var m = KEEP_ALIVE_RE.exec(res.headers['keep-alive']);
if (m) {
var seconds = parseInt(m[1]);
if (seconds > 0) {
// network delay 500ms
var serverKeepAliveTimeout = seconds * 1000 - 500;
if (serverKeepAliveTimeout < agent.freeSocketKeepAliveTimeout) {
res.socket.freeSocketKeepAliveTimeout = serverKeepAliveTimeout;
}
}
}
}

cb(err, data, args.streaming ? res : response);

if (args.emitter) {
Expand Down
55 changes: 55 additions & 0 deletions test/keep-alive-header.test.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
'use strict';

var assert = require('assert');
var http = require('http');
var Agent = require('agentkeepalive');
var urllib = require('..');

describe('test/keep-alive-header.test.js', function() {
let port;
let server;
before(function(done) {
server = http.createServer(function(req, res) {
if (server.keepAliveTimeout) {
res.setHeader('Keep-Alive', `timeout=${parseInt(server.keepAliveTimeout / 1000)}`);
}
res.end('Hello World, ' + req.connection.remotePort);
});
server.on('clientError', function(err, socket) {
socket.end('HTTP/1.1 400 Bad Request\r\n\r\n');
});
server.keepAliveTimeout = 1000;
server.listen(0, function(err) {
port = server.address().port;
done(err);
});
});

it('should handle Keep-Alive header and not throw reset error', function(done) {
const keepaliveAgent = new Agent({
keepAlive: true,
});

let count = 0;
function request() {
count++;
urllib.request('http://127.0.0.1:' + port + '/foo', {
method: 'GET',
agent: keepaliveAgent,
dataType: 'text',
}, function(err, text, res) {
assert(!err);
assert(res.status === 200);
console.log('[%s] status: %s, text: %s, headers: %j', count, text, res.status, res.headers);
assert(res.headers.connection === 'keep-alive');
assert(res.headers['keep-alive'] === 'timeout=1');
if (count > 5) {
done();
}
});
}

setInterval(request, server.keepAliveTimeout);
request();
});
});

0 comments on commit 0af7cdf

Please sign in to comment.