From 47e84e4e75f2d4a92abc97a64c1d3d001188a3ff Mon Sep 17 00:00:00 2001 From: Naman Trivedi Date: Sat, 12 Sep 2026 13:47:33 +0000 Subject: [PATCH] quic: add stream.cancel() sending H3_REQUEST_CANCELLED When an endpoint deliberately abandons a request or response, RFC 9114 section 4.1.1 says the stream should be aborted with the error code H3_REQUEST_CANCELLED. There is currently no way to express this: the reset primitives default to the no-error code and destroy(error) uses the internal error code. Add stream.cancel([reason]), which abruptly terminates both directions of the stream using the cancellation code defined by the negotiated application protocol (H3_REQUEST_CANCELLED for HTTP/3; the no-error code for other applications). The code value is plumbed from the application layer through the session state, following the same pattern as the request-rejected code. Refs: https://github.com/nodejs/node/issues/65509 Signed-off-by: Naman Trivedi --- doc/api/quic.md | 19 ++++ lib/internal/quic/quic.js | 17 ++++ lib/internal/quic/state.js | 9 ++ src/quic/application.cc | 5 ++ src/quic/application.h | 7 ++ src/quic/http3.cc | 4 + src/quic/session.cc | 2 + test/parallel/test-quic-stream-cancel.mjs | 102 ++++++++++++++++++++++ 8 files changed, 165 insertions(+) create mode 100644 test/parallel/test-quic-stream-cancel.mjs diff --git a/doc/api/quic.md b/doc/api/quic.md index 19995000b20e..577d1e8348b6 100644 --- a/doc/api/quic.md +++ b/doc/api/quic.md @@ -1948,6 +1948,24 @@ an `ERR_QUIC_APPLICATION_ERROR` or `ERR_QUIC_TRANSPORT_ERROR` when the stream is closed due to a QUIC error (e.g., stream reset by the peer, CONNECTION\_CLOSE with a non-zero error code). +### `stream.cancel([reason])` + + + +* `reason` {string} Optional human-readable reason. + +Cancels the stream: abruptly terminates both directions, signaling to the +peer that the request or response was deliberately abandoned. `STOP_SENDING` +is sent for a still-open readable side and `RESET_STREAM` for a still-open +writable side. When the negotiated application protocol defines a +cancellation code ([RFC 9114 section 4.1.1][] defines `H3_REQUEST_CANCELLED` +for HTTP/3) the frames carry it; other application protocols use their +"no error" code. + +The call does nothing if the stream is already destroyed. + ### `stream.destroy([error[, options]])`