Skip to content

Commit

Permalink
http2: send RST code 8 on AbortController signal
Browse files Browse the repository at this point in the history
Fixes: #47321
Refs: https://www.rfc-editor.org/rfc/rfc7540#section-7
PR-URL: #48573
Reviewed-By: Rafael Gonzaga <[email protected]>
Reviewed-By: Yagiz Nizipli <[email protected]>
Reviewed-By: Minwoo Jung <[email protected]>
  • Loading branch information
devm33 authored and juanarbol committed Jul 13, 2023
1 parent a316808 commit 4a0b66e
Show file tree
Hide file tree
Showing 2 changed files with 40 additions and 4 deletions.
15 changes: 11 additions & 4 deletions lib/internal/http2/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -2319,10 +2319,17 @@ class Http2Stream extends Duplex {
// this stream's close and destroy operations.
// Previously, this always overrode a successful close operation code
// NGHTTP2_NO_ERROR (0) with sessionCode because the use of the || operator.
const code = (err != null ?
(sessionCode || NGHTTP2_INTERNAL_ERROR) :
(this.closed ? this.rstCode : sessionCode)
);
let code = this.closed ? this.rstCode : sessionCode;
if (err != null) {
if (sessionCode) {
code = sessionCode;
} else if (err instanceof AbortError) {
// Enables using AbortController to cancel requests with RST code 8.
code = NGHTTP2_CANCEL;
} else {
code = NGHTTP2_INTERNAL_ERROR;
}
}
const hasHandle = handle !== undefined;

if (!this.closed)
Expand Down
29 changes: 29 additions & 0 deletions test/parallel/test-http2-client-destroy.js
Original file line number Diff line number Diff line change
Expand Up @@ -285,3 +285,32 @@ const { getEventListeners } = require('events');
testH2ConnectAbort(false);
testH2ConnectAbort(true);
}

// Destroy ClientHttp2Stream with AbortSignal
{
const server = h2.createServer();
const controller = new AbortController();

server.on('stream', common.mustCall((stream) => {
stream.on('error', common.mustNotCall());
stream.on('close', common.mustCall(() => {
assert.strictEqual(stream.rstCode, h2.constants.NGHTTP2_CANCEL);
server.close();
}));
controller.abort();
}));
server.listen(0, common.mustCall(() => {
const client = h2.connect(`http://localhost:${server.address().port}`);
client.on('close', common.mustCall());

const { signal } = controller;
const req = client.request({}, { signal });
assert.strictEqual(getEventListeners(signal, 'abort').length, 1);
req.on('error', common.mustCall((err) => {
assert.strictEqual(err.code, 'ABORT_ERR');
assert.strictEqual(err.name, 'AbortError');
client.close();
}));
req.on('close', common.mustCall());
}));
}

0 comments on commit 4a0b66e

Please sign in to comment.