diff --git a/lib/agent.js b/lib/agent.js index 8bd354e..7438d30 100644 --- a/lib/agent.js +++ b/lib/agent.js @@ -90,7 +90,13 @@ class Agent extends OriginalAgent { this.timeoutSocketCount = 0; this.timeoutSocketCountLastCheck = 0; - this.on('free', socket => { + this.on('free', (socket, options) => { + // Node's listener may assign the socket to a queued request before this + // listener runs. Only apply the free socket timeout if it was pooled. + const name = this.getName(options); + if (!this.freeSockets[name] || this.freeSockets[name].indexOf(socket) === -1) { + return; + } // https://github.com/nodejs/node/pull/32000 // Node.js native agent will check socket timeout eqs agent.options.timeout. // Use the ttl or freeSocketTimeout to overwrite. diff --git a/test/http_agent.test.js b/test/http_agent.test.js index 4e1228b..b224e89 100644 --- a/test/http_agent.test.js +++ b/test/http_agent.test.js @@ -762,6 +762,42 @@ describe('test/agent.test.js', () => { assert(agent.requests[name].length === 1); }); + it('should use active timeout when socket is assigned to a queued request', done => { + const name = 'localhost:' + port + ':'; + const agent = new HttpAgent({ + maxSockets: 1, + freeSocketTimeout: 50, + timeout: 1000, + }); + let finished = false; + const finish = err => { + if (finished) return; + finished = true; + agent.destroy(); + done(err); + }; + + http.get({ + agent, + port, + path: '/?timeout=10', + }, res => { + res.resume(); + }).on('error', finish); + + http.get({ + agent, + port, + path: '/?timeout=200', + }, res => { + assert(res.statusCode === 200); + res.resume(); + res.on('end', finish); + }).on('error', finish); + + assert(agent.requests[name].length === 1); + }); + it('should keep 1 free socket', done => { const name = 'localhost:' + port + ':'; const agent = new HttpAgent({