Current section
Files
Jump to
Current section
Files
CHANGELOG.md
# Changelog
All notable changes to this project will be documented in this file.
The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.1.0/),
and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
## [1.2.0] - 2026-09-28
### Added
- Listener options `h2_initial_window_size` and `h2_max_frame_size`, aliases of the `h2_settings` keys
- Listener option `h2_response_delay`, a fixed or uniform delay before the response headers of a `{reply, _, _}` result on HTTP/2
- Listener options `h2_connection_window_policy` and `h2_stream_window_policy`, credit policies for the HTTP/2 receive windows with the shapes `eager`, `{threshold, N}`, `{delay, Ms}` and `never`
- The `on_response` shape of both credit policies, which sends the credit for a request ahead of the HEADERS of its `{reply, _, _}` response, and the listener option `h2_credit_batch` that batches the connection credit
### Changed
- Updates `nhttp_lib` reference
- Response bodies, producer chunks and WebSocket frames on HTTP/2 go through the codec send queue. The server keeps no remainder buffer of its own, and one connection grant reaches every blocked stream, one frame per stream per turn
- Every RST_STREAM the server sends goes through the codec, which closes the stream and purges the octets it holds for it
- `h2_settings` accepts `max_send_buffer` and `max_queued_streams`, the bounds of the codec send queue. The server defaults both to `infinity`. A response body, producer chunk or WebSocket frame that the bound refuses ends its stream with RST_STREAM(ENHANCE_YOUR_CALM). A producer sees `{error, closed}` and a WebSocket session closes with `{transport, send_buffer_full}`
### Fixed
- A WebSocket-over-HTTP/2 frame that outran the send window was dropped without a record
- One large response was able to take a whole connection credit ahead of smaller ones
- The NO_ERROR RST_STREAM that asks a client to stop sending a request body went out before the response was complete, and the buffered body then followed it on a closed stream (RFC 9113 Section 5.1 and Section 8.1)
## [1.1.1] - 2026-09-10
### Changed
- Requires `nhttp_lib` 1.1.1
## [1.1.0] - 2026-09-10
### Changed
- Requires `nhttp_lib` 1.1.0
- Socket re-arming for the next read is centralized. A `setopts` error on a peer that closed ends the HTTP/1.1, HTTP/2, and WebSocket loops as a normal close
- The `nhttp.http.request.duration` metric records native time units. The consumer converts them
### Fixed
- `t:nhttp:start_error/0` includes `{already_started, pid()}`
## [1.0.4] - 2026-08-24
### Fixed
- HTTP/1.1 connections no longer crash when the peer closes the socket. A `setopts` call that gives an error now closes the connection normally. A body read that gives an error tells the handler that the peer closed the connection
## [1.0.3] - 2026-08-20
### Changed
- Requires `nhttp_lib` 1.0.4 for correct HTTP/1.1 `Content-Length` handling. An empty-body response now emits `Content-Length: 0`, a 1xx, 204, or 304 response emits no `Content-Length` field, and a 2xx response to a `CONNECT` request can suppress it (RFC 9110 Section 8.6)
## [1.0.2] - 2026-08-13
### Added
- Support for Erlang/OTP 29.
## [1.0.1] - 2026-08-12
### Fixed
- WebSocket fragmented messages on HTTP/1.1. The connection keeps decoder state across reads, so a message split over several frames is reassembled and delivered once (RFC 6455 section 5.4)
- WebSocket CLOSE codes for decode errors. A text payload or CLOSE reason that is not valid UTF-8 gives 1007, a message over `max_message_size` gives 1009, and other framing errors keep 1002. Before, every decode error gave 1002
### Changed
- Requires `nhttp_lib` 1.0.3 for the stateful frame decoder and incremental UTF-8 validation
### Added
- WebSocket RFC 6455 compliance tests with Autobahn. Run them with `make ws-compliance`
## [1.0.0] - 2026-06-01
Initial public release.
### Added
- HTTP/1.1 and HTTP/2 server with automatic protocol selection via TLS ALPN (RFC 9112, RFC 9113)
- HTTP/3 server over QUIC via in-process `nquic` library mode (RFC 9114)
- Handler behaviour (`nhttp_handler`) with a small callback set for request handling, streaming, and WebSocket sessions
- WebSocket support across HTTP/1.1, HTTP/2, and HTTP/3 with one callback set (RFC 6455, RFC 8441, RFC 9220)
- Streaming responses via producer funs with end-to-end backpressure
- Streaming request bodies with handler-driven backpressure
- Server-Sent Events helpers (`nhttp_sse`)
- CORS preflight and response header helpers (`nhttp_cors`)
- Response compression (gzip / deflate) with MIME-aware defaults
- PROXY protocol v1/v2 for HAProxy / AWS NLB deployments
- SNI with static lookup table and dynamic callback
- OpenTelemetry spans and metrics (opt-in)
- Graceful shutdown with connection draining
- One process per connection, with HTTP/2 and HTTP/3 streams multiplexed inside it
- Per-stream handler workers on HTTP/2 to isolate slow handlers