Skip to content

Commit c03cddb

Browse files
mitsos1osBethGriggs
authored andcommitted
test: http complete response after socket double end
PR-URL: #36633 Backport-PR-URL: #36940Fixes: #36620 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Benjamin Gruenbaum <benjamingr@gmail.com> Reviewed-By: Danielle Adams <adamzdanielle@gmail.com>
1 parent 2a1e4e9 commit c03cddb

2 files changed

Lines changed: 98 additions & 0 deletions

File tree

Lines changed: 95 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,95 @@
1+
'use strict';
2+
constcommon=require('../common');
3+
constassert=require('assert');
4+
consthttp=require('http');
5+
6+
constREQ_TIMEOUT=500;// Set max ms of request time before abort
7+
8+
// Set total allowed test timeout to avoid infinite loop
9+
// that will hang test suite
10+
constTOTAL_TEST_TIMEOUT=1000;
11+
12+
// Placeholder for sockets handled, to make sure that we
13+
// will reach a socket re-use case.
14+
consthandledSockets=newSet();
15+
16+
letmetReusedSocket=false;// Flag for request loop termination.
17+
18+
constdoubleEndResponse=(res)=>{
19+
// First end the request while sending some normal data
20+
res.end('regular end of request','utf8',common.mustCall());
21+
// Make sure the response socket is uncorked after first call of end
22+
assert.strictEqual(res.writableCorked,0);
23+
res.end();// Double end the response to prep for next socket re-use.
24+
};
25+
26+
constsendDrainNeedingData=(res)=>{
27+
// Send data to socket more than the high watermark so that
28+
// it definitely needs drain
29+
consthighWaterMark=res.socket.writableHighWaterMark;
30+
constbufferToSend=Buffer.alloc(highWaterMark+100);
31+
constret=res.write(bufferToSend);// Write the request data.
32+
// Make sure that we had back pressure on response stream.
33+
assert.strictEqual(ret,false);
34+
res.once('drain',()=>res.end());// End on drain.
35+
};
36+
37+
constserver=http.createServer((req,res)=>{
38+
const{socket: responseSocket}=res;
39+
if(handledSockets.has(responseSocket)){// re-used socket, send big data!
40+
metReusedSocket=true;// stop request loop
41+
console.debug('FOUND REUSED SOCKET!');
42+
sendDrainNeedingData(res);
43+
}else{// not used again
44+
// add to make sure we recognise it when we meet socket again
45+
handledSockets.add(responseSocket);
46+
doubleEndResponse(res);
47+
}
48+
});
49+
50+
server.listen(0);// Start the server on a random port.
51+
52+
constsendRequest=(agent)=>newPromise((resolve,reject)=>{
53+
consttimeout=setTimeout(common.mustNotCall(()=>{
54+
reject(newError('Request timed out'));
55+
}),REQ_TIMEOUT);
56+
http.get({
57+
port: server.address().port,
58+
path: '/',
59+
agent
60+
},common.mustCall((res)=>{
61+
constresData=[];
62+
res.on('data',(data)=>resData.push(data));
63+
res.on('end',common.mustCall(()=>{
64+
consttotalData=resData.reduce((total,elem)=>total+elem.length,0);
65+
clearTimeout(timeout);// Cancel rejection timeout.
66+
resolve(totalData);// fulfill promise
67+
}));
68+
}));
69+
});
70+
71+
server.once('listening',async()=>{
72+
consttestTimeout=setTimeout(common.mustNotCall(()=>{
73+
console.error('Test running for a while but could not met re-used socket');
74+
process.exit(1);
75+
}),TOTAL_TEST_TIMEOUT);
76+
// Explicitly start agent to force socket reuse.
77+
constagent=newhttp.Agent({keepAlive: true});
78+
// Start the request loop
79+
letreqNo=0;
80+
while(!metReusedSocket){
81+
try{
82+
console.log(`Sending req no ${++reqNo}`);
83+
consttotalData=awaitsendRequest(agent);
84+
console.log(`${totalData} bytes were received for request ${reqNo}`);
85+
}catch(err){
86+
console.error(err);
87+
process.exit(1);
88+
}
89+
}
90+
// Successfully tested conditions and ended loop
91+
clearTimeout(testTimeout);
92+
console.log('Closing server');
93+
agent.destroy();
94+
server.close();
95+
});

‎test/parallel/test-http-outgoing-end-multiple.js‎

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,12 +5,15 @@ const http = require('http');
55

66
constserver=http.createServer(common.mustCall(function(req,res){
77
res.end('testing ended state',common.mustCall());
8+
assert.strictEqual(res.writableCorked,0);
89
res.end(common.mustCall());
10+
assert.strictEqual(res.writableCorked,0);
911
res.on('finish',common.mustCall(()=>{
1012
res.end(common.mustCall((err)=>{
1113
assert.strictEqual(err.code,'ERR_STREAM_ALREADY_FINISHED');
1214
server.close();
1315
}));
16+
assert.strictEqual(res.writableCorked,0);
1417
}));
1518
}));
1619

0 commit comments

Comments
 (0)