agent-base
Advanced tools
Comparing version 4.1.2 to 4.2.0
4.2.0 / 2018-01-15 | ||
================== | ||
* Add support for returning an `http.Agent` instance | ||
* Optimize promisifying logic | ||
* Set `timeout` to null for proper cleanup | ||
* Remove Node.js <= 0.11.3 special-casing from test case | ||
4.1.2 / 2017-11-20 | ||
@@ -3,0 +11,0 @@ ================== |
58
index.js
'use strict'; | ||
/** | ||
* Module dependencies. | ||
*/ | ||
require('./patch-core'); | ||
@@ -12,8 +7,8 @@ const inherits = require('util').inherits; | ||
/** | ||
* Module exports. | ||
*/ | ||
module.exports = Agent; | ||
function isAgent(v) { | ||
return v && typeof v.addRequest === 'function'; | ||
} | ||
/** | ||
@@ -26,3 +21,2 @@ * Base `http.Agent` implementation. | ||
*/ | ||
function Agent(callback, _opts) { | ||
@@ -35,2 +29,6 @@ if (!(this instanceof Agent)) { | ||
// The callback gets promisified if it has 3 parameters | ||
// (i.e. it has a callback function) lazily | ||
this._promisifiedCallback = false; | ||
let opts = _opts; | ||
@@ -65,10 +63,6 @@ if ('function' === typeof callback) { | ||
*/ | ||
Agent.prototype.addRequest = function addRequest( | ||
req, | ||
_opts | ||
) { | ||
Agent.prototype.addRequest = function addRequest(req, _opts) { | ||
const ownOpts = Object.assign({}, _opts); | ||
// set default `host` for HTTP to localhost | ||
// Set default `host` for HTTP to localhost | ||
if (null == ownOpts.host) { | ||
@@ -78,3 +72,3 @@ ownOpts.host = 'localhost'; | ||
// set default `port` for HTTP if none was explicitly specified | ||
// Set default `port` for HTTP if none was explicitly specified | ||
if (null == ownOpts.port) { | ||
@@ -87,3 +81,3 @@ ownOpts.port = ownOpts.secureEndpoint ? 443 : 80; | ||
if (opts.host && opts.path) { | ||
// if both a `host` and `path` are specified then it's most likely the | ||
// If both a `host` and `path` are specified then it's most likely the | ||
// result of a `url.parse()` call... we need to remove the `path` portion so | ||
@@ -100,3 +94,3 @@ // that `net.connect()` doesn't attempt to open that as a unix socket file. | ||
// hint to use "Connection: close" | ||
// Hint to use "Connection: close" | ||
// XXX: non-documented `http` module API :( | ||
@@ -106,3 +100,3 @@ req._last = true; | ||
// create the `stream.Duplex` instance | ||
// Create the `stream.Duplex` instance | ||
let timeout; | ||
@@ -121,2 +115,3 @@ let timedOut = false; | ||
function ontimeout() { | ||
timeout = null; | ||
timedOut = true; | ||
@@ -134,2 +129,3 @@ const err = new Error( | ||
clearTimeout(timeout); | ||
timeout = null; | ||
} | ||
@@ -143,7 +139,14 @@ onerror(err); | ||
clearTimeout(timeout); | ||
timeout = null; | ||
} | ||
if (socket) { | ||
if (isAgent(socket)) { | ||
// `socket` is actually an http.Agent instance, so relinquish | ||
// responsibility for this `req` to the Agent from here on | ||
socket.addRequest(req, opts); | ||
} else if (socket) { | ||
req.onSocket(socket); | ||
} else { | ||
const err = new Error(`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\``); | ||
const err = new Error( | ||
`no Duplex stream was returned to agent-base for \`${req.method} ${req.path}\`` | ||
); | ||
onerror(err); | ||
@@ -153,5 +156,6 @@ } | ||
if (this.callback.length >= 3) { | ||
// legacy callback function, convert to Promise | ||
if (!this._promisifiedCallback && this.callback.length >= 3) { | ||
// Legacy callback function - convert to a Promise | ||
this.callback = promisify(this.callback, this); | ||
this._promisifiedCallback = true; | ||
} | ||
@@ -164,8 +168,6 @@ | ||
try { | ||
Promise.resolve(this.callback(req, opts)) | ||
.then(onsocket, callbackError); | ||
Promise.resolve(this.callback(req, opts)).then(onsocket, callbackError); | ||
} catch (err) { | ||
Promise.reject(err) | ||
.catch(callbackError); | ||
Promise.reject(err).catch(callbackError); | ||
} | ||
}; |
{ | ||
"name": "agent-base", | ||
"version": "4.1.2", | ||
"version": "4.2.0", | ||
"description": "Turn a function into an `http.Agent` instance", | ||
@@ -5,0 +5,0 @@ "main": "./index.js", |
'use strict'; | ||
const url = require('url'); | ||
@@ -4,0 +3,0 @@ const https = require('https'); |
@@ -66,3 +66,3 @@ agent-base | ||
You can also return a Promise or use an `async` function: | ||
Returning a Promise or using an `async` function is also supported: | ||
@@ -76,3 +76,12 @@ ```js | ||
Return another `http.Agent` instance to "pass through" the responsibility | ||
for that HTTP request to that agent: | ||
```js | ||
agent(function (req, opts) { | ||
return opts.secureEndpoint ? https.globalAgent : http.globalAgent; | ||
}); | ||
``` | ||
API | ||
@@ -79,0 +88,0 @@ --- |
@@ -17,2 +17,6 @@ /** | ||
var PassthroughAgent = Agent(function(req, opts) { | ||
return opts.secureEndpoint ? https.globalAgent : http.globalAgent; | ||
}); | ||
describe('Agent', function() { | ||
@@ -74,6 +78,6 @@ describe('subclass', function() { | ||
var agent = new Agent(); | ||
agent.callback = function () { | ||
agent.callback = function() { | ||
called = true; | ||
assert.equal(this, agent); | ||
} | ||
}; | ||
var info = url.parse('http://127.0.0.1/foo'); | ||
@@ -86,11 +90,11 @@ info.agent = agent; | ||
}); | ||
}) | ||
}); | ||
it('should be the Agent instance with callback signature', function(done) { | ||
var called = false; | ||
var agent = new Agent(); | ||
agent.callback = function (req, opts, fn) { | ||
agent.callback = function(req, opts, fn) { | ||
called = true; | ||
assert.equal(this, agent); | ||
fn(); | ||
} | ||
}; | ||
var info = url.parse('http://127.0.0.1/foo'); | ||
@@ -103,4 +107,4 @@ info.agent = agent; | ||
}); | ||
}) | ||
}) | ||
}); | ||
}); | ||
describe('"error" event', function() { | ||
@@ -208,9 +212,3 @@ it('should be invoked on `http.ClientRequest` instance if `callback()` has not been defined', function( | ||
); | ||
if ('function' == typeof stream.ondata) { | ||
// node <= v0.11.3 | ||
stream.ondata(buf, 0, buf.length); | ||
} else { | ||
// node > v0.11.3 | ||
stream.emit('data', buf); | ||
} | ||
stream.emit('data', buf); | ||
}); | ||
@@ -407,2 +405,24 @@ | ||
}); | ||
describe('PassthroughAgent', function() { | ||
it('should pass through to `http.globalAgent`', function(done) { | ||
// add HTTP server "request" listener | ||
var gotReq = false; | ||
server.once('request', function(req, res) { | ||
gotReq = true; | ||
res.setHeader('X-Foo', 'bar'); | ||
res.setHeader('X-Url', req.url); | ||
res.end(); | ||
}); | ||
var info = url.parse('http://127.0.0.1:' + port + '/foo'); | ||
info.agent = PassthroughAgent; | ||
http.get(info, function(res) { | ||
assert.equal('bar', res.headers['x-foo']); | ||
assert.equal('/foo', res.headers['x-url']); | ||
assert(gotReq); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -435,3 +455,2 @@ | ||
it('should not modify the passed in Options object', function(done) { | ||
@@ -525,2 +544,25 @@ var called = false; | ||
}); | ||
describe('PassthroughAgent', function() { | ||
it('should pass through to `https.globalAgent`', function(done) { | ||
// add HTTP server "request" listener | ||
var gotReq = false; | ||
server.once('request', function(req, res) { | ||
gotReq = true; | ||
res.setHeader('X-Foo', 'bar'); | ||
res.setHeader('X-Url', req.url); | ||
res.end(); | ||
}); | ||
var info = url.parse('https://127.0.0.1:' + port + '/foo'); | ||
info.agent = PassthroughAgent; | ||
info.rejectUnauthorized = false; | ||
https.get(info, function(res) { | ||
assert.equal('bar', res.headers['x-foo']); | ||
assert.equal('/foo', res.headers['x-url']); | ||
assert(gotReq); | ||
done(); | ||
}); | ||
}); | ||
}); | ||
}); | ||
@@ -527,0 +569,0 @@ |
34154
776
146