Skip to content

Commit 4c6bfbd

Browse files
ronagaddaleax
authored andcommitted
http: fix client response close & aborted
Fixes: #20102Fixes: #20101Fixes: #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: #20075Fixes: #17352 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: James M Snell <jasnell@gmail.com> Reviewed-By: Trivikram Kamat <trivikr.dev@gmail.com>
1 parent 30aceed commit 4c6bfbd

2 files changed

Lines changed: 69 additions & 41 deletions

File tree

‎lib/_http_client.js‎

Lines changed: 23 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -328,26 +328,33 @@ function socketCloseListener() {
328328

329329
// NOTE: It's important to get parser here, because it could be freed by
330330
// the `socketOnData`.
331-
varparser=socket.parser;
332-
if(req.res&&req.res.readable){
331+
constparser=socket.parser;
332+
constres=req.res;
333+
if(res){
333334
// Socket closed before we emitted 'end' below.
334-
if(!req.res.complete){
335-
req.res.aborted=true;
336-
req.res.emit('aborted');
335+
if(!res.complete){
336+
res.aborted=true;
337+
res.emit('aborted');
337338
}
338-
varres=req.res;
339-
res.on('end',function(){
339+
req.emit('close');
340+
if(res.readable){
341+
res.on('end',function(){
342+
this.emit('close');
343+
});
344+
res.push(null);
345+
}else{
340346
res.emit('close');
341-
});
342-
res.push(null);
343-
}elseif(!req.res&&!req.socket._hadError){
344-
// This socket error fired before we started to
345-
// receive a response. The error needs to
346-
// fire on the request.
347-
req.socket._hadError=true;
348-
req.emit('error',createHangUpError());
347+
}
348+
}else{
349+
if(!req.socket._hadError){
350+
// This socket error fired before we started to
351+
// receive a response. The error needs to
352+
// fire on the request.
353+
req.socket._hadError=true;
354+
req.emit('error',createHangUpError());
355+
}
356+
req.emit('close');
349357
}
350-
req.emit('close');
351358

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

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

Lines changed: 46 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,29 +23,50 @@
2323
constcommon=require('../common');
2424
consthttp=require('http');
2525

26-
constserver=http.createServer(common.mustCall(function(req,res){
27-
res.writeHead(200);
28-
res.write('a');
26+
{
27+
constserver=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+
constserver=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)