Skip to content

Commit 1f26576

Browse files
authored
http2: submit RST_STREAM before emitting 'aborted'
Signed-off-by: lazerg <lazerg2@gmail.com> PR-URL: #66314 Fixes: #66306 Reviewed-By: Matteo Collina <matteo.collina@gmail.com> Reviewed-By: Tim Perry <pimterry@gmail.com>
1 parent 691cf62 commit 1f26576

2 files changed

Lines changed: 40 additions & 7 deletions

File tree

‎lib/internal/http2/core.js‎

Lines changed: 8 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -2153,14 +2153,7 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
21532153
stream.setTimeout(0);
21542154
stream.removeAllListeners('timeout');
21552155

2156-
// Emit 'aborted' if the user hadn't ended the writable yet. This is
2157-
// unusual and doesn't match 'error' but is deprecated & preserved for
2158-
// backward compat (DEP0207).
21592156
const { ending } = stream._writableState;
2160-
if (!ending && !stream.aborted) {
2161-
state.flags |= STREAM_FLAGS_ABORTED;
2162-
stream.emit('aborted');
2163-
}
21642157

21652158
if (rstStreamStatus !== kNoRstStream) {
21662159
// If the user already called .end() and writes are still draining,
@@ -2174,6 +2167,14 @@ function closeStream(stream, code, rstStreamStatus = kSubmitRstStream) {
21742167
}
21752168
}
21762169

2170+
// Emit 'aborted' if the user hadn't ended the writable yet. This is
2171+
// unusual and doesn't match 'error' but is deprecated & preserved for
2172+
// backward compat (DEP0207).
2173+
if (!ending && !stream.aborted) {
2174+
state.flags |= STREAM_FLAGS_ABORTED;
2175+
stream.emit('aborted');
2176+
}
2177+
21772178
if (type === NGHTTP2_SESSION_CLIENT) {
21782179
if (onClientStreamCloseChannel.hasSubscribers) {
21792180
onClientStreamCloseChannel.publish({ stream });
Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
'use strict';
2+
3+
const common = require('../common');
4+
if (!common.hasCrypto)
5+
common.skip('missing crypto');
6+
const assert = require('assert');
7+
const http2 = require('http2');
8+
const { NGHTTP2_CANCEL } = http2.constants;
9+
10+
const server = http2.createServer();
11+
12+
server.on('stream', common.mustCall((stream) => {
13+
stream.respond();
14+
stream.on('error', common.expectsError({
15+
code: 'ERR_HTTP2_STREAM_ABORTED',
16+
}));
17+
stream.on('close', common.mustCall(() => {
18+
assert.strictEqual(stream.rstCode, NGHTTP2_CANCEL);
19+
server.close();
20+
}));
21+
}));
22+
23+
server.listen(0, common.mustCall(() => {
24+
const client = http2.connect(`http://localhost:${server.address().port}`);
25+
const req = client.request({ ':method': 'POST' });
26+
27+
req.on('aborted', common.mustCall(() => req.destroy()));
28+
req.on('close', common.mustCall(() => client.close()));
29+
req.on('response', common.mustCall(() => {
30+
req.close(NGHTTP2_CANCEL);
31+
}));
32+
}));

0 commit comments

Comments
 (0)