Skip to content

Commit 66fe2d9

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 Backport-PR-URL: #32212 PR-URL: #32197 Reviewed-By: Anna Henningsen <[email protected]> Reviewed-By: Matteo Collina <[email protected]>
1 parent 77e5b50 commit 66fe2d9

File tree

2 files changed

+45
-4
lines changed

2 files changed

+45
-4
lines changed

lib/internal/streams/pipeline.js

+24-4
Original file line numberDiff line numberDiff line change
@@ -25,8 +25,20 @@ let EE;
2525
let PassThrough;
2626
let createReadableStreamAsyncIterator;
2727

28-
function isRequest(stream) {
29-
return stream && stream.setHeader && typeof stream.abort === 'function';
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+
);
3042
}
3143

3244
function destroyer(stream, reading, writing, final, callback) {
@@ -37,10 +49,18 @@ function destroyer(stream, reading, writing, final, callback) {
3749
eos(stream, { readable: reading, writable: writing }, (err) => {
3850
if (destroyed) return;
3951
destroyed = true;
40-
const readable = stream.readable || isRequest(stream);
41-
if (err || !final || !readable) {
52+
53+
if (!err && (isIncoming(stream) || isOutgoing(stream))) {
54+
// http/1 request objects have a coupling to their response and should
55+
// not be prematurely destroyed. Assume they will handle their own
56+
// lifecycle.
57+
return callback();
58+
}
59+
60+
if (err || !final || !stream.readable) {
4261
destroyImpl.destroyer(stream, err);
4362
}
63+
4464
callback(err);
4565
});
4666

test/parallel/test-stream-pipeline.js

+21
Original file line numberDiff line numberDiff line change
@@ -995,3 +995,24 @@ const { promisify } = require('util');
995995
assert.strictEqual(res, '');
996996
}));
997997
}
998+
999+
{
1000+
const server = http.createServer((req, res) => {
1001+
req.socket.on('error', common.mustNotCall());
1002+
pipeline(req, new PassThrough(), (err) => {
1003+
assert.ifError(err);
1004+
res.end();
1005+
server.close();
1006+
});
1007+
});
1008+
1009+
server.listen(0, () => {
1010+
const req = http.request({
1011+
method: 'PUT',
1012+
port: server.address().port
1013+
});
1014+
req.end('asd123');
1015+
req.on('response', common.mustCall());
1016+
req.on('error', common.mustNotCall());
1017+
});
1018+
}

0 commit comments

Comments
 (0)