Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion reference/configuration/options.md
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ http:
```

- `sessionAffinity` — Route requests from same client to same worker thread (`ip` or header name)
- `compressionThreshold` — Response size threshold for Brotli compression; _Default_: `1200` (bytes)
- `compressionThreshold` — Response size threshold (bytes) for Brotli compression; `0` disables compression; _Default_: `0`
- `cors` — Enable CORS; _Default_: `true`
- `corsAccessList` — Allowed domains for CORS requests
- `corsAccessControlAllowHeaders` — `Access-Control-Allow-Headers` value for OPTIONS preflight
Expand Down
4 changes: 1 addition & 3 deletions reference/http/api.md
Original file line number Diff line number Diff line change
Expand Up @@ -449,9 +449,7 @@ A `Readable` is the usual return, but the non-stream forms are not theoretical.

Harper's own `ContentTypeHandler` TypeScript interface is currently narrower than this runtime contract, so a typed handler returning a `Readable` or an iterable may need a cast.

:::caution
Prefer returning a stream when your handler may run with response compression enabled — `Readable.from([value])` wraps an already-serialized value. Harper pipes the `serializeStream` result into the Brotli compressor, so a `Buffer` or string return throws `TypeError: stream.pipe is not a function` for a client that sends `Accept-Encoding: br`. Compression applies only when `http.compressionThreshold` is set to a non-zero value, and normalizing the non-stream forms belongs in Harper's compression path rather than in every handler — treat this as a current limitation, not as part of the return contract.
:::
<VersionBadge type="changed" version="v5.3.0" /> Every return form above is also compressed when response compression is enabled (`http.compressionThreshold` set to a non-zero value) and the client sends `Accept-Encoding: br`: a returned `Buffer` or string is compressed as a whole body when its `length` exceeds the threshold (a string's `length` counts UTF-16 code units, not UTF-8 bytes, so a non-ASCII string can be over the threshold in bytes and still be sent uncompressed), and a returned `Readable` or iterable is compressed as a stream. Before v5.3.0, a `Buffer`, string, or generator return failed with `TypeError: stream.pipe is not a function` under compression, so a handler targeting older releases should return a `Readable` — `Readable.from([value])` wraps an already-serialized value.

---

Expand Down
4 changes: 2 additions & 2 deletions reference/http/configuration.md
Original file line number Diff line number Diff line change
Expand Up @@ -114,9 +114,9 @@ The maximum estimated request queue time in milliseconds. When the queue exceeds

Type: `number`

Default: `1200` (bytes)
Default: `0` (compression disabled)
Comment thread
kriszyp marked this conversation as resolved.

For clients that support Brotli encoding (`Accept-Encoding: br`), responses larger than this threshold are compressed. Streaming query responses are always compressed for supporting clients, regardless of this setting (since their size is unknown upfront).
The threshold is also the on/off switch: `0` disables compression rather than compressing every response, and any non-zero byte count enables it. For clients that send `Accept-Encoding: br`, responses larger than this threshold are Brotli-compressed; Brotli is the only encoding Harper applies, so a client that accepts only `gzip` or `deflate` receives an uncompressed body. A string body, such as serialized JSON, is measured by its JavaScript `length` (UTF-16 code units) rather than its UTF-8 byte size, so text with non-ASCII characters can be over the threshold in bytes and still be sent uncompressed. A response the content type serializes as a stream (query results, for example) is compressed for those clients whenever the threshold is non-zero, regardless of size, since its size is unknown upfront; an iterable body that the content type serializes to a single buffer, such as a plain array sent as MessagePack, is compressed only above the threshold. Server-Sent Events are never compressed. `1200` bytes, about one TCP packet, is a reasonable starting value.

```yaml
http:
Expand Down
2 changes: 1 addition & 1 deletion reference/http/overview.md
Original file line number Diff line number Diff line change
Expand Up @@ -111,7 +111,7 @@ HTTP/2 can be enabled with the `http2: true` option in `harper-config.yaml`. Whe

## Compression

Harper automatically compresses HTTP responses using Brotli for clients that advertise `Accept-Encoding: br`. Compression applies when the response body exceeds the configured `compressionThreshold` (default 1200 bytes). Streaming query responses are always compressed for clients that support it (since their size is not known upfront).
Response compression is off by default. Setting [`http.compressionThreshold`](./configuration#httpcompressionthreshold) to a non-zero byte count enables it: Harper then Brotli-compresses responses larger than the threshold for clients that advertise `Accept-Encoding: br`, and compresses streamed responses regardless of size (since their size is not known upfront). Server-Sent Events are never compressed.

## Logging

Expand Down
2 changes: 1 addition & 1 deletion reference/rest/headers.md
Original file line number Diff line number Diff line change
Expand Up @@ -94,7 +94,7 @@ If the record has not changed, Harper returns `304 Not Modified` with no body. T

### Accept-Encoding

Harper supports standard HTTP compression. Including this header enables compressed responses:
When response compression is enabled with [`http.compressionThreshold`](../http/configuration.md#httpcompressionthreshold) (it is off by default), Harper Brotli-compresses responses for clients that include `br` in this header. Brotli is the only encoding Harper applies, so a client that accepts only `gzip` receives an uncompressed body:

```http
Accept-Encoding: gzip, br
Expand Down
Loading