-
Notifications
You must be signed in to change notification settings - Fork 9
docs(http): correct serializeStream return type - follow-up to #641 #655
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change | ||||||||
|---|---|---|---|---|---|---|---|---|---|---|
|
|
@@ -434,12 +434,23 @@ contentTypes.set('text/xml', { | |||||||||
|
|
||||||||||
| ### Handler Interface | ||||||||||
|
|
||||||||||
| | Property | Type | Description | | ||||||||||
| | ----------------------- | ----------------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||||||||||
| | `serialize(data)` | `(any) => Buffer \| Uint8Array \| string` | Serialize data for a response | | ||||||||||
| | `serializeStream(data)` | `(any) => Readable` | Serialize a streaming response body. Called once per response with the whole iterable (not once per chunk), and only when the response body is an iterable or async iterable. Returns a Node.js [`Readable`](https://nodejs.org/api/stream.html#class-streamreadable). | | ||||||||||
| | `deserialize(buffer)` | `(Buffer \| string) => any` | Deserialize an incoming request body. String for `text/*` types, Buffer for binary types. | | ||||||||||
| | `q` | number (0–1) | Quality indicator for content negotiation. Defaults to `1`. | | ||||||||||
| | Property | Type | Description | | ||||||||||
| | ----------------------- | ----------------------------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | ||||||||||
| | `serialize(data)` | `(any) => Buffer \| Uint8Array \| string \| Readable` | Serialize a complete response body. Used when the response body is not iterable, or when the handler defines no `serializeStream`. Most handlers return a string or a `Buffer`; the built-in `text/csv` handler returns a [`Readable`](https://nodejs.org/api/stream.html#class-streamreadable), which Harper streams to the response. | | ||||||||||
| | `serializeStream(data)` | `(any) => Readable \| Buffer \| string` | Serialize a streaming response body. Called once per response with the whole iterable (not once per chunk), and only when the response body is an object that is iterable or async iterable. A Node.js [`Readable`](https://nodejs.org/api/stream.html#class-streamreadable) is the usual return, but it is not the only one — see [Non-streaming returns from `serializeStream`](#non-streaming-returns-from-serializestream). | | ||||||||||
| | `deserialize(buffer)` | `(Buffer) => any` | Deserialize an incoming request body. Harper always passes a `Buffer`, including for `text/*` types — a text handler calls `buffer.toString()` itself. | | ||||||||||
| | `q` | number (0–1) | Quality indicator for content negotiation. Defaults to `1`. | | ||||||||||
|
|
||||||||||
| #### Non-streaming returns from `serializeStream` | ||||||||||
|
|
||||||||||
| `serializeStream` may return a `Readable`, a `Buffer`, a string, or any iterable or async iterable. Harper writes all of these to the response: a `Readable` is piped, an iterable is wrapped with `Readable.from()`, and a `Buffer` or string is sent as the whole body. | ||||||||||
|
|
||||||||||
| The union is not theoretical. Harper picks `serializeStream` over `serialize` whenever the response body is iterable, and a plain array is iterable — so a resource that returns an array reaches `serializeStream`. A handler that has nothing to stream in that case can serialize the value in one shot instead: | ||||||||||
|
|
||||||||||
| - The built-in `application/x-msgpack` handler streams only non-array iterables. For a plain array it returns a packed `Buffer`. | ||||||||||
| - The built-in NDJSON handler returns a string when it is handed a value that is not iterable. | ||||||||||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This is not a reachable |
||||||||||
|
|
||||||||||
| One caveat if you return something other than a stream: when Brotli compression applies to the response (the client sent `Accept-Encoding: br` and `http.compressionThreshold` is non-zero), Harper pipes the value returned by `serializeStream` into the compressor. A `Buffer` or string has no `pipe`, so a handler that must work with compression enabled should return a stream — wrap a buffered result with `Readable.from([buffer])` if there is nothing to stream incrementally. | ||||||||||
|
Contributor
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Since this Brotli compression caveat describes a scenario that leads to a runtime crash (
Suggested change
References
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This documents a framework bug as a handler requirement. |
||||||||||
|
|
||||||||||
| --- | ||||||||||
|
|
||||||||||
|
|
||||||||||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The return type is incomplete relative to the subsection immediately below it:
serializeStreamis said to accept any iterable or async iterable and wrap it withReadable.from(), but neither is represented here. A typed custom handler returning a generator would therefore be rejected despite the documented runtime behavior. Add the iterable forms to the public type (and its core declaration), or narrow the prose to the supported contract.