Skip to content

Commit a55b77d

Browse files
committed
stream: finished on closed OutgoingMessage
finished should invoke callback on closed OutgoingMessage the same way as for regular streams. Fixes: #34301 PR-URL: #34313 Fixes: #34274 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Luigi Pinca <luigipinca@gmail.com>
1 parent d46fc91 commit a55b77d

File tree

6 files changed

+32
-14
lines changed

6 files changed

+32
-14
lines changed

lib/_http_client.js

+6-6
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,7 @@ const Agent = require('_http_agent');
4949
const { Buffer } = require('buffer');
5050
const { defaultTriggerAsyncIdScope } = require('internal/async_hooks');
5151
const { URL, urlToOptions, searchParamsSymbol } = require('internal/url');
52-
const { kOutHeaders, kNeedDrain, kClosed } = require('internal/http');
52+
const { kOutHeaders, kNeedDrain } = require('internal/http');
5353
const { connResetException, codes } = require('internal/errors');
5454
const {
5555
ERR_HTTP_HEADERS_SENT,
@@ -387,7 +387,7 @@ function _destroy(req, socket, err) {
387387
if (err) {
388388
req.emit('error', err);
389389
}
390-
req[kClosed] = true;
390+
req._closed = true;
391391
req.emit('close');
392392
}
393393
}
@@ -430,7 +430,7 @@ function socketCloseListener() {
430430
res.emit('error', connResetException('aborted'));
431431
}
432432
}
433-
req[kClosed] = true;
433+
req._closed = true;
434434
req.emit('close');
435435
if (!res.aborted && res.readable) {
436436
res.on('end', function() {
@@ -450,7 +450,7 @@ function socketCloseListener() {
450450
req.socket._hadError = true;
451451
req.emit('error', connResetException('socket hang up'));
452452
}
453-
req[kClosed] = true;
453+
req._closed = true;
454454
req.emit('close');
455455
}
456456

@@ -555,7 +555,7 @@ function socketOnData(d) {
555555

556556
req.emit(eventName, res, socket, bodyHead);
557557
req.destroyed = true;
558-
req[kClosed] = true;
558+
req._closed = true;
559559
req.emit('close');
560560
} else {
561561
// Requested Upgrade or used CONNECT method, but have no handler.
@@ -727,7 +727,7 @@ function requestOnPrefinish() {
727727
}
728728

729729
function emitFreeNT(req) {
730-
req[kClosed] = true;
730+
req._closed = true;
731731
req.emit('close');
732732
if (req.res) {
733733
req.res.emit('close');

lib/_http_outgoing.js

+3-3
Original file line numberDiff line numberDiff line change
@@ -36,7 +36,7 @@ const assert = require('internal/assert');
3636
const EE = require('events');
3737
const Stream = require('stream');
3838
const internalUtil = require('internal/util');
39-
const { kOutHeaders, utcDate, kNeedDrain, kClosed } = require('internal/http');
39+
const { kOutHeaders, utcDate, kNeedDrain } = require('internal/http');
4040
const { Buffer } = require('buffer');
4141
const common = require('_http_common');
4242
const checkIsHttpToken = common._checkIsHttpToken;
@@ -117,7 +117,7 @@ function OutgoingMessage() {
117117
this.finished = false;
118118
this._headerSent = false;
119119
this[kCorked] = 0;
120-
this[kClosed] = false;
120+
this._closed = false;
121121

122122
this.socket = null;
123123
this._header = null;
@@ -664,7 +664,7 @@ function onError(msg, err, callback) {
664664

665665
function emitErrorNt(msg, err, callback) {
666666
callback(err);
667-
if (typeof msg.emit === 'function' && !msg[kClosed]) {
667+
if (typeof msg.emit === 'function' && !msg._closed) {
668668
msg.emit('error', err);
669669
}
670670
}

lib/_http_server.js

+2-3
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,6 @@ const { OutgoingMessage } = require('_http_outgoing');
4949
const {
5050
kOutHeaders,
5151
kNeedDrain,
52-
kClosed,
5352
emitStatistics
5453
} = require('internal/http');
5554
const {
@@ -216,7 +215,7 @@ function onServerResponseClose() {
216215
// Fortunately, that requires only a single if check. :-)
217216
if (this._httpMessage) {
218217
this._httpMessage.destroyed = true;
219-
this._httpMessage[kClosed] = true;
218+
this._httpMessage._closed = true;
220219
this._httpMessage.emit('close');
221220
}
222221
}
@@ -733,7 +732,7 @@ function resOnFinish(req, res, socket, state, server) {
733732

734733
function emitCloseNT(self) {
735734
self.destroyed = true;
736-
self[kClosed] = true;
735+
self._closed = true;
737736
self.emit('close');
738737
}
739738

lib/internal/http.js

-1
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,6 @@ function emitStatistics(statistics) {
5151
module.exports = {
5252
kOutHeaders: Symbol('kOutHeaders'),
5353
kNeedDrain: Symbol('kNeedDrain'),
54-
kClosed: Symbol('kClosed'),
5554
nowDate,
5655
utcDate,
5756
emitStatistics

lib/internal/streams/end-of-stream.js

+2-1
Original file line numberDiff line numberDiff line change
@@ -147,7 +147,8 @@ function eos(stream, options, callback) {
147147
if (options.error !== false) stream.on('error', onerror);
148148
stream.on('close', onclose);
149149

150-
const closed = (
150+
// _closed is for OutgoingMessage which is not a proper Writable.
151+
const closed = (!wState && !rState && stream._closed === true) || (
151152
(wState && wState.closed) ||
152153
(rState && rState.closed) ||
153154
(wState && wState.errorEmitted) ||

test/parallel/test-stream-finished.js

+19
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ const assert = require('assert');
1313
const EE = require('events');
1414
const fs = require('fs');
1515
const { promisify } = require('util');
16+
const http = require('http');
1617

1718
{
1819
const rs = new Readable({
@@ -480,3 +481,21 @@ testClosed((opts) => new Writable({ write() {}, ...opts }));
480481
finished(p, common.mustNotCall());
481482
}));
482483
}
484+
485+
{
486+
const server = http.createServer((req, res) => {
487+
res.on('close', () => {
488+
finished(res, common.mustCall(() => {
489+
server.close();
490+
}));
491+
});
492+
res.end();
493+
})
494+
.listen(0, function() {
495+
http.request({
496+
method: 'GET',
497+
port: this.address().port
498+
}).end()
499+
.on('response', common.mustCall());
500+
});
501+
}

0 commit comments

Comments
 (0)