stream: finished waits for 'close' on OutgoingMessage

Don't invoke finished callback until OutgoingMessagehas
emitted 'close'.

PR-URL: https://github.com/nodejs/node/pull/36648
Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
Reviewed-By: James M Snell <jasnell@gmail.com>
This commit is contained in:
Robert Nagy
2020-12-27 21:30:59 +01:00
committed by James M Snell
parent f4ef517deb
commit 52546c091d
2 changed files with 43 additions and 1 deletions

View File

@@ -21,6 +21,16 @@ function isRequest(stream) {
return stream.setHeader && typeof stream.abort === 'function';
}
function isServerResponse(stream) {
return (
typeof stream._sent100 === 'boolean' &&
typeof stream._removedConnection === 'boolean' &&
typeof stream._removedContLen === 'boolean' &&
typeof stream._removedTE === 'boolean' &&
typeof stream._closed === 'boolean'
);
}
function isReadable(stream) {
return typeof stream.readable === 'boolean' ||
typeof stream.readableEnded === 'boolean' ||
@@ -80,7 +90,7 @@ function eos(stream, options, callback) {
// TODO (ronag): Improve soft detection to include core modules and
// common ecosystem modules that do properly emit 'close' but fail
// this generic check.
let willEmitClose = (
let willEmitClose = isServerResponse(stream) || (
state &&
state.autoDestroy &&
(state.emitClose || isSocket(stream)) &&

View File

@@ -0,0 +1,32 @@
'use strict';
const common = require('../common');
const { finished } = require('stream');
const http = require('http');
const assert = require('assert');
const server = http.createServer(function(req, res) {
let closed = false;
res
.on('close', common.mustCall(() => {
closed = true;
finished(res, common.mustCall(() => {
server.close();
}));
}))
.end();
finished(res, common.mustCall(() => {
assert.strictEqual(closed, true);
}));
}).listen(0, function() {
http
.request({
port: this.address().port,
method: 'GET'
})
.on('response', function(res) {
res.resume();
})
.end();
});