Skip to content

Commit f8f2089

Browse files
ronagMylesBorins
authored andcommitted
stream: avoid destroying http1 objects
http1 objects are coupled with their corresponding res/req and cannot be treated independently as normal streams. Add a special exception for this in the pipeline cleanup. Fixes: #32184 PR-URL: #32197 Reviewed-By: Anna Henningsen <anna@addaleax.net> Reviewed-By: Matteo Collina <matteo.collina@gmail.com>
1 parent 51e8f28 commit f8f2089

File tree

2 files changed

+45
-6
lines changed

2 files changed

+45
-6
lines changed

lib/internal/streams/pipeline.js

Lines changed: 24 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -25,10 +25,32 @@ let EE;
2525
let PassThrough;
2626
let createReadableStreamAsyncIterator;
2727

28+
function isIncoming(stream) {
29+
return (
30+
stream.socket &&
31+
typeof stream.complete === 'boolean' &&
32+
ArrayIsArray(stream.rawTrailers) &&
33+
ArrayIsArray(stream.rawHeaders)
34+
);
35+
}
36+
37+
function isOutgoing(stream) {
38+
return (
39+
stream.socket &&
40+
typeof stream.setHeader === 'function'
41+
);
42+
}
43+
2844
function destroyer(stream, reading, writing, final, callback) {
2945
const _destroy = once((err) => {
30-
const readable = stream.readable || isRequest(stream);
31-
if (err || !final || !readable) {
46+
if (!err && (isIncoming(stream) || isOutgoing(stream))) {
47+
// http/1 request objects have a coupling to their response and should
48+
// not be prematurely destroyed. Assume they will handle their own
49+
// lifecycle.
50+
return callback();
51+
}
52+
53+
if (err || !final || !stream.readable) {
3254
destroyImpl.destroyer(stream, err);
3355
}
3456
callback(err);
@@ -71,10 +93,6 @@ function popCallback(streams) {
7193
return streams.pop();
7294
}
7395

74-
function isRequest(stream) {
75-
return stream.setHeader && typeof stream.abort === 'function';
76-
}
77-
7896
function isPromise(obj) {
7997
return !!(obj && typeof obj.then === 'function');
8098
}

test/parallel/test-stream-pipeline.js

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1011,3 +1011,24 @@ const { promisify } = require('util');
10111011
assert.strictEqual(res, '');
10121012
}));
10131013
}
1014+
1015+
{
1016+
const server = http.createServer((req, res) => {
1017+
req.socket.on('error', common.mustNotCall());
1018+
pipeline(req, new PassThrough(), (err) => {
1019+
assert.ifError(err);
1020+
res.end();
1021+
server.close();
1022+
});
1023+
});
1024+
1025+
server.listen(0, () => {
1026+
const req = http.request({
1027+
method: 'PUT',
1028+
port: server.address().port
1029+
});
1030+
req.end('asd123');
1031+
req.on('response', common.mustCall());
1032+
req.on('error', common.mustNotCall());
1033+
});
1034+
}

0 commit comments

Comments
 (0)