Description
Description
Hi Luigi, i am a bit lost if this a valid edge case to report. but i do find it "odd" that reading the payload from the response (while doing such successfully) can result in the underlying socket being left open).
Calling the request.socket.destroy();
after response end event fires bypasses the problem.
Is this behavior expected from your point of view?
Reproducible in:
- version: 7.4.4
- Node.js version(s): v14.16.1
- OS version(s): Fedora 33, 5.11.12-200.fc33.x86_64
Steps to reproduce:
Demo server (returning invalid data on purpose):
let http = require('http');
let server = http.createServer(function (req, res) {
res.writeHead(502, {'Content-Type': 'text/html'});
res.write('uhoh\r\n');
res.end();
});
server.keepAliveTimeout = 0;
server.listen(4987);
Client demonstrating the issue:
const WebSocket = require('ws');
for (let id = 0; id < 100; id++) {
let ws = new WebSocket('ws:127.0.0.1:4987');
ws.on('open', () => {});
ws.on('close', (code, reason) => {
console.log('close', id, code, reason);
});
ws.on('error', (error) => {
console.log('error', id, error.toString());
});
ws.on('unexpected-response', (request, response) => {
let chunks = [];
let payload = null;
response.on('data', (chunk) => chunks.push(chunk));
response.on('end', () => {
payload = Buffer.concat(chunks).toString();
// uncommenting this when ready
// request.socket.destroy();
ws.terminate();
});
});
}
Expected result:
With the demo client code above, the bottom line is that the node process shuts down on its own.
Actual result:
The demo client code did not shut down because the underlying TCP sockets are left in ESTABLISHED
state.
Regardless of calling ws.close() or ws.terminate().
The "trigger" for the above scenario appears to be binding the additional event handlers used to read the response payload (which does succeeds).
You can confirm that the connections are left open by doing netstat -an | grep ':4987' | grep ESTABLISHED | wc -l