Skip to content

Commit 77f0359

Browse files
lpincacjihrig
authored andcommitted
http: use 'connect' event only if socket is connecting
Fixes a bug that prevented `ClientRequest.prototype.setTimeout()` from working properly when the socket was reused for multiple requests. Fixes: #16716 Refs: #8895 PR-URL: #16725 Reviewed-By: Rich Trott <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Colin Ihrig <[email protected]> Reviewed-By: Benjamin Gruenbaum <[email protected]>
1 parent e4b3c00 commit 77f0359

File tree

2 files changed

+48
-2
lines changed

2 files changed

+48
-2
lines changed

lib/_http_client.js

+6-2
Original file line numberDiff line numberDiff line change
@@ -728,9 +728,13 @@ ClientRequest.prototype.setTimeout = function setTimeout(msecs, callback) {
728728
}
729729

730730
this.once('socket', function(sock) {
731-
sock.once('connect', function() {
731+
if (sock.connecting) {
732+
sock.once('connect', function() {
733+
sock.setTimeout(msecs, emitTimeout);
734+
});
735+
} else {
732736
sock.setTimeout(msecs, emitTimeout);
733-
});
737+
}
734738
});
735739

736740
return this;
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
'use strict';
2+
const common = require('../common');
3+
4+
// This test ensures that `ClientRequest.prototype.setTimeout()` does
5+
// not add a listener for the `'connect'` event to the socket if the
6+
// socket is already connected.
7+
8+
const assert = require('assert');
9+
const http = require('http');
10+
11+
// Maximum allowed value for timeouts.
12+
const timeout = 2 ** 31 - 1;
13+
14+
const server = http.createServer((req, res) => {
15+
res.end();
16+
});
17+
18+
server.listen(0, common.mustCall(() => {
19+
const agent = new http.Agent({ keepAlive: true, maxSockets: 1 });
20+
const options = { port: server.address().port, agent: agent };
21+
22+
doRequest(options, common.mustCall(() => {
23+
const req = doRequest(options, common.mustCall(() => {
24+
agent.destroy();
25+
server.close();
26+
}));
27+
28+
req.on('socket', common.mustCall((socket) => {
29+
assert.strictEqual(socket.listenerCount('connect'), 0);
30+
}));
31+
}));
32+
}));
33+
34+
function doRequest(options, callback) {
35+
const req = http.get(options, (res) => {
36+
res.on('end', callback);
37+
res.resume();
38+
});
39+
40+
req.setTimeout(timeout);
41+
return req;
42+
}

0 commit comments

Comments
 (0)