Skip to content

Commit 7c7230a

Browse files
devm33ruyadorno
authored andcommitted
http2: send RST code 8 on AbortController signal
Fixes: #47321 Refs: https://www.rfc-editor.org/rfc/rfc7540#section-7 PR-URL: #48573 Reviewed-By: Rafael Gonzaga <rafael.nunu@hotmail.com> Reviewed-By: Yagiz Nizipli <yagiz@nizipli.com> Reviewed-By: Minwoo Jung <nodecorelab@gmail.com>
1 parent a68a67f commit 7c7230a

File tree

2 files changed

+40
-4
lines changed

2 files changed

+40
-4
lines changed

lib/internal/http2/core.js

+11-4
Original file line numberDiff line numberDiff line change
@@ -2318,10 +2318,17 @@ class Http2Stream extends Duplex {
23182318
// this stream's close and destroy operations.
23192319
// Previously, this always overrode a successful close operation code
23202320
// NGHTTP2_NO_ERROR (0) with sessionCode because the use of the || operator.
2321-
const code = (err != null ?
2322-
(sessionCode || NGHTTP2_INTERNAL_ERROR) :
2323-
(this.closed ? this.rstCode : sessionCode)
2324-
);
2321+
let code = this.closed ? this.rstCode : sessionCode;
2322+
if (err != null) {
2323+
if (sessionCode) {
2324+
code = sessionCode;
2325+
} else if (err instanceof AbortError) {
2326+
// Enables using AbortController to cancel requests with RST code 8.
2327+
code = NGHTTP2_CANCEL;
2328+
} else {
2329+
code = NGHTTP2_INTERNAL_ERROR;
2330+
}
2331+
}
23252332
const hasHandle = handle !== undefined;
23262333

23272334
if (!this.closed)

test/parallel/test-http2-client-destroy.js

+29
Original file line numberDiff line numberDiff line change
@@ -285,3 +285,32 @@ const { getEventListeners } = require('events');
285285
testH2ConnectAbort(false);
286286
testH2ConnectAbort(true);
287287
}
288+
289+
// Destroy ClientHttp2Stream with AbortSignal
290+
{
291+
const server = h2.createServer();
292+
const controller = new AbortController();
293+
294+
server.on('stream', common.mustCall((stream) => {
295+
stream.on('error', common.mustNotCall());
296+
stream.on('close', common.mustCall(() => {
297+
assert.strictEqual(stream.rstCode, h2.constants.NGHTTP2_CANCEL);
298+
server.close();
299+
}));
300+
controller.abort();
301+
}));
302+
server.listen(0, common.mustCall(() => {
303+
const client = h2.connect(`http://localhost:${server.address().port}`);
304+
client.on('close', common.mustCall());
305+
306+
const { signal } = controller;
307+
const req = client.request({}, { signal });
308+
assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
309+
req.on('error', common.mustCall((err) => {
310+
assert.strictEqual(err.code, 'ABORT_ERR');
311+
assert.strictEqual(err.name, 'AbortError');
312+
client.close();
313+
}));
314+
req.on('close', common.mustCall());
315+
}));
316+
}

0 commit comments

Comments
 (0)