Skip to content

Commit ffb503b

Browse files
ronagtrivikr
authored andcommitted
http: fix client response close & aborted
Fixes: nodejs#20102 Fixes: nodejs#20101 Fixes: nodejs#1735 - Response should always emit close. - Response should always emit aborted if aborted. - Response should always emit close after request has emitted close. PR-URL: nodejs#20075 Fixes: nodejs#17352 Reviewed-By: Matteo Collina <[email protected]> Reviewed-By: James M Snell <[email protected]> Reviewed-By: Trivikram Kamat <[email protected]>
1 parent fcf2e42 commit ffb503b

File tree

2 files changed

+69
-41
lines changed

2 files changed

+69
-41
lines changed

lib/_http_client.js

+23-16
Original file line numberDiff line numberDiff line change
@@ -340,26 +340,33 @@ function socketCloseListener() {
340340

341341
// NOTE: It's important to get parser here, because it could be freed by
342342
// the `socketOnData`.
343-
var parser = socket.parser;
344-
if (req.res && req.res.readable) {
343+
const parser = socket.parser;
344+
const res = req.res;
345+
if (res) {
345346
// Socket closed before we emitted 'end' below.
346-
if (!req.res.complete) {
347-
req.res.aborted = true;
348-
req.res.emit('aborted');
347+
if (!res.complete) {
348+
res.aborted = true;
349+
res.emit('aborted');
349350
}
350-
var res = req.res;
351-
res.on('end', function() {
351+
req.emit('close');
352+
if (res.readable) {
353+
res.on('end', function() {
354+
this.emit('close');
355+
});
356+
res.push(null);
357+
} else {
352358
res.emit('close');
353-
});
354-
res.push(null);
355-
} else if (!req.res && !req.socket._hadError) {
356-
// This socket error fired before we started to
357-
// receive a response. The error needs to
358-
// fire on the request.
359-
req.socket._hadError = true;
360-
req.emit('error', createHangUpError());
359+
}
360+
} else {
361+
if (!req.socket._hadError) {
362+
// This socket error fired before we started to
363+
// receive a response. The error needs to
364+
// fire on the request.
365+
req.socket._hadError = true;
366+
req.emit('error', createHangUpError());
367+
}
368+
req.emit('close');
361369
}
362-
req.emit('close');
363370

364371
// Too bad. That output wasn't getting written.
365372
// This is pretty terrible that it doesn't raise an error.

test/parallel/test-http-response-close.js

+46-25
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,50 @@
2323
const common = require('../common');
2424
const http = require('http');
2525

26-
const server = http.createServer(common.mustCall(function(req, res) {
27-
res.writeHead(200);
28-
res.write('a');
26+
{
27+
const server = http.createServer(
28+
common.mustCall((req, res) => {
29+
res.writeHead(200);
30+
res.write('a');
31+
})
32+
);
33+
server.listen(
34+
0,
35+
common.mustCall(() => {
36+
http.get(
37+
{ port: server.address().port },
38+
common.mustCall((res) => {
39+
res.on('data', common.mustCall(() => {
40+
res.destroy();
41+
}));
42+
res.on('close', common.mustCall(() => {
43+
server.close();
44+
}));
45+
})
46+
);
47+
})
48+
);
49+
}
2950

30-
req.on('close', common.mustCall(function() {
31-
console.error('request aborted');
32-
}));
33-
res.on('close', common.mustCall(function() {
34-
console.error('response aborted');
35-
}));
36-
}));
37-
server.listen(0);
38-
39-
server.on('listening', function() {
40-
console.error('make req');
41-
http.get({
42-
port: this.address().port
43-
}, function(res) {
44-
console.error('got res');
45-
res.on('data', function(data) {
46-
console.error('destroy res');
47-
res.destroy();
48-
server.close();
49-
});
50-
});
51-
});
51+
{
52+
const server = http.createServer(
53+
common.mustCall((req, res) => {
54+
res.writeHead(200);
55+
res.end('a');
56+
})
57+
);
58+
server.listen(
59+
0,
60+
common.mustCall(() => {
61+
http.get(
62+
{ port: server.address().port },
63+
common.mustCall((res) => {
64+
res.on('close', common.mustCall(() => {
65+
server.close();
66+
}));
67+
res.resume();
68+
})
69+
);
70+
})
71+
);
72+
}

0 commit comments

Comments
 (0)