Skip to content

Commit 554afa8

Browse files
committed
quic: update the docs
1 parent 4ec288a commit 554afa8

1 file changed

Lines changed: 84 additions & 6 deletions

File tree

doc/api/quic.md

Lines changed: 84 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1138,7 +1138,7 @@ const { QuicError } = require('node:quic');
11381138
```
11391139

11401140
When a `QuicError` is supplied to APIs that emit a wire frame
1141-
(currently [`writer.fail()`][]), the QUIC stack uses
1141+
([`writer.fail()`][], [`stream.destroy()`][]), the QUIC stack uses
11421142
[`error.errorCode`][] as the wire code for the resulting frame.
11431143
When any other value is supplied (for example a plain `Error`), the
11441144
implementation falls back to the negotiated application protocol's
@@ -1231,17 +1231,54 @@ an `ERR_QUIC_APPLICATION_ERROR` or `ERR_QUIC_TRANSPORT_ERROR` when the
12311231
stream is closed due to a QUIC error (e.g., stream reset by the peer,
12321232
CONNECTION\_CLOSE with a non-zero error code).
12331233

1234-
### `stream.destroy([error])`
1234+
### `stream.destroy([error[, options]])`
12351235

12361236
<!-- YAML
12371237
added: v23.8.0
1238+
changes:
1239+
- version: REPLACEME
1240+
pr-url: https://github.com/nodejs/node/pull/62876
1241+
description: Added the `options` parameter accepting `code` and `reason`.
12381242
-->
12391243

12401244
* `error` {any}
1245+
* `options` {Object}
1246+
* `code` {bigint|number} The application error code to include in the
1247+
`RESET_STREAM` and `STOP_SENDING` frames sent to the peer. Numbers are
1248+
coerced to `BigInt`. When omitted, the wire code is derived from `error`
1249+
(see below).
1250+
* `reason` {string} An optional human-readable reason string. Accepted for
1251+
symmetry with [`session.close()`][] and [`session.destroy()`][], but
1252+
**not transmitted on the wire** — neither `RESET_STREAM` nor
1253+
`STOP_SENDING` carry a reason field. Provided for application logging
1254+
and for use by the [`stream.onerror`][] callback.
12411255

12421256
Immediately and abruptly destroys the stream. If `error` is provided and
12431257
[`stream.onerror`][] is set, the `onerror` callback is invoked before
1244-
destruction. The `stream.closed` promise will reject with the error.
1258+
destruction. The `stream.closed` promise rejects with the error.
1259+
1260+
When the stream is destroyed with an `error` (or with an explicit
1261+
`options.code`), the QUIC stack signals the abort to the peer:
1262+
1263+
* If the writable side is still open, a `RESET_STREAM` frame is sent.
1264+
* If the readable side is still open (a bidirectional stream, or a
1265+
remote-initiated unidirectional stream), a `STOP_SENDING` frame is sent.
1266+
1267+
Both frames carry the same wire code, resolved with the following
1268+
precedence:
1269+
1270+
1. `options.code`, when explicitly provided.
1271+
2. [`error.errorCode`][], when `error` is a [`QuicError`][].
1272+
3. The negotiated application protocol's "internal error" code
1273+
(`H3_INTERNAL_ERROR` (`0x102`) for HTTP/3, or the QUIC transport-layer
1274+
`INTERNAL_ERROR` (`0x1`) for raw QUIC).
1275+
1276+
A clean destroy — no `error` and no `options.code` — does not emit
1277+
`RESET_STREAM` or `STOP_SENDING`; the stream's existing close machinery
1278+
handles teardown.
1279+
1280+
See [Aborting a stream][] for an overview of the available stream-abort
1281+
APIs.
12451282

12461283
### `stream.destroyed`
12471284

@@ -1253,6 +1290,28 @@ added: v23.8.0
12531290

12541291
True if `stream.destroy()` has been called.
12551292

1293+
### Aborting a stream
1294+
1295+
A QuicStream can be aborted in three ways, each producing different
1296+
wire-frame side effects:
1297+
1298+
* [`writer.fail(reason)`][] — Aborts only the writable side. Sends
1299+
`RESET_STREAM` to the peer. The readable side is unaffected; any data
1300+
already buffered for read remains available.
1301+
* [`stream.destroy()`][] with an `error` argument — Tears the stream
1302+
down completely. Sends `RESET_STREAM` on any still-open writable side
1303+
**and** `STOP_SENDING` on any still-open readable side. The wire code
1304+
is derived from `error` (see [`stream.destroy()`][] for the precedence
1305+
rules).
1306+
* [`stream.destroy()`][] with an explicit `options.code` — Same as the
1307+
previous form but with a caller-supplied wire code, which takes
1308+
precedence over any code carried by `error`.
1309+
1310+
When `error` is a [`QuicError`][], its [`error.errorCode`][] is used as
1311+
the wire code for both `writer.fail()` and `stream.destroy()`. Otherwise
1312+
the implementation falls back to the negotiated application protocol's
1313+
"internal error" code (see [`QuicError`][]).
1314+
12561315
### `stream.early`
12571316

12581317
* Type: {boolean}
@@ -1332,7 +1391,19 @@ added: v23.8.0
13321391

13331392
* Type: {quic.OnStreamErrorCallback}
13341393

1335-
The callback to invoke when the stream is reset. Read/write.
1394+
The callback to invoke when the peer aborts a direction of the stream by
1395+
sending a `RESET_STREAM` frame (the peer abandons their writable side, so
1396+
no further data will arrive on our readable side) or a `STOP_SENDING`
1397+
frame (the peer asks us to stop writing on our writable side).
1398+
1399+
The callback receives a Node.js error whose `errorCode` (`bigint`)
1400+
property carries the application error code from the wire frame.
1401+
1402+
The stream is **not** automatically destroyed when this callback fires —
1403+
the application chooses how to react. Common patterns are: ignore (and
1404+
continue using the still-active direction on a bidirectional stream),
1405+
abort the other direction with [`writer.fail()`][], or tear down the
1406+
whole stream with [`stream.destroy()`][]. Read/write.
13361407

13371408
### `stream.headers`
13381409

@@ -1563,12 +1634,14 @@ The Writer has the following methods:
15631634
* `writev(chunks[, options])` — Async vectored write.
15641635
* `endSync()` — Synchronous close. Returns total bytes or `-1`.
15651636
* `end([options])` — Async close.
1566-
* `fail(reason)` — Errors the stream (sends RESET\_STREAM to peer).
1637+
* `fail(reason)` — Errors the stream (sends `RESET_STREAM` to peer).
15671638
When `reason` is a [`QuicError`][], its [`error.errorCode`][] is used
1568-
as the wire code on the resulting RESET\_STREAM frame; otherwise
1639+
as the wire code on the resulting `RESET_STREAM` frame; otherwise
15691640
the wire code falls back to the negotiated application protocol's
15701641
"internal error" code (`H3_INTERNAL_ERROR` (`0x102`) for HTTP/3, or
15711642
the QUIC transport-layer `INTERNAL_ERROR` (`0x1`) for raw QUIC).
1643+
See [`stream.destroy()`][] for a full-stream abort that also resets
1644+
the readable side via `STOP_SENDING`.
15721645
* `desiredSize` — Available capacity in bytes, or `null` if closed/errored.
15731646

15741647
### `stream.setBody(body)`
@@ -3251,6 +3324,7 @@ Published when a stream is flow-control blocked and cannot send data
32513324
until the peer increases the flow control window. Useful for diagnosing
32523325
throughput issues caused by flow control.
32533326
3327+
[Aborting a stream]: #aborting-a-stream
32543328
[Callback error handling]: #callback-error-handling
32553329
[JSON-SEQ]: https://www.rfc-editor.org/rfc/rfc7464
32563330
[NSS Key Log Format]: https://udn.realityripple.com/docs/Mozilla/Projects/NSS/Key_Log_Format
@@ -3263,6 +3337,8 @@ throughput issues caused by flow control.
32633337
[`fs.promises.open(path, 'r')`]: fs.md#fspromisesopenpath-flags-mode
32643338
[`quic.connect()`]: #quicconnectaddress-options
32653339
[`quic.listen()`]: #quiclistencallback-options
3340+
[`session.close()`]: #sessioncloseoptions
3341+
[`session.destroy()`]: #sessiondestroyerror-options
32663342
[`session.maxPendingDatagrams`]: #sessionmaxpendingdatagrams
32673343
[`session.onerror`]: #sessiononerror
32683344
[`session.onkeylog`]: #sessiononkeylog
@@ -3272,6 +3348,7 @@ throughput issues caused by flow control.
32723348
[`sessionOptions.keylog`]: #sessionoptionskeylog
32733349
[`sessionOptions.qlog`]: #sessionoptionsqlog
32743350
[`sessionOptions.sni`]: #sessionoptionssni-server-only
3351+
[`stream.destroy()`]: #streamdestroyerror-options
32753352
[`stream.onerror`]: #streamonerror
32763353
[`stream.onwanttrailers`]: #streamonwanttrailers
32773354
[`stream.pendingTrailers`]: #streampendingtrailers
@@ -3280,5 +3357,6 @@ throughput issues caused by flow control.
32803357
[`stream.setPriority()`]: #streamsetpriorityoptions
32813358
[`stream.writer`]: #streamwriter
32823359
[`writer.fail()`]: #streamwriter
3360+
[`writer.fail(reason)`]: #streamwriter
32833361
[qlog]: https://datatracker.ietf.org/doc/draft-ietf-quic-qlog-main-schema/
32843362
[qvis]: https://qvis.quictools.info/

0 commit comments

Comments
 (0)