Current section
Files
Jump to
Current section
Files
CHANGELOG.md
# Changelog
All notable changes to this project are documented here. Format loosely
follows [Keep a Changelog](https://keepachangelog.com/en/1.1.0/); versions
follow [Semantic Versioning](https://semver.org/).
## [0.2.1] - 2026-04-19
### Fixed
- `h1:upgrade/4` crash when the `:path` pseudo-header is supplied (dead-code
path in `handle_client_upgrade/4` eagerly encoded pseudo-headers before
`upgrade_wire/1` stripped them).
## [0.2.0] - 2026-04-19
### Added
- `h1:accept_connect/3,4`: server-side reply of `200 Connection
Established` to a classic HTTP/1.1 CONNECT with atomic raw-socket
handoff (RFC 9110 §9.3.6, RFC 9112 §3.2.3). Mirrors
`h1:accept_upgrade/3` but writes status 200 and injects no
Connection/Upgrade/framing headers, so bytes past the terminating
CRLF belong to the tunnel.
## [0.1.1] — 2026-04-19
### Changed
- Hex package name is **`erlang_h1`** (the short `h1` is already taken
on hex.pm). The OTP application, module atom, and public API are
unchanged — call sites continue to use `h1:connect/2` etc.
## [0.1.0] — 2026-04-19
Initial release.
### HTTP/1.1 core
- Streaming pure-Erlang parser covering RFC 9110 / RFC 9112: request
and response lines, chunked transfer, trailers, obs-fold, 100-continue,
absolute-form / asterisk / authority request targets.
- Request / response / chunk / trailer encoder with CRLF-injection
guards on header names, methods, paths, and reason phrases.
- RFC 9297 capsule codec (`h1_capsule`) wire-compatible with the
equivalent module in `erlang_h2`.
- `h1_connection` `gen_statem` running in both client and server modes
with keep-alive, pipelining (in-order response delivery on the
server), `Expect: 100-continue`, and Upgrade / 101 Switching
Protocols with socket handoff.
### Public API
- `h1` module mirrors the surface of `h2` and `quic_h3` so callers can
swap protocols: `connect`, `request`, `send_data`, `send_trailers`,
`cancel`, `goaway`, `close`, `start_server`, `stop_server`,
`send_response`, plus H1-specific `upgrade`, `accept_upgrade`,
`continue`, `pipeline`.
- Event messages (`{h1, Conn, Event}`) match the `h2` / `h3` shape,
with an extra `{upgrade, ...}` / `{upgraded, ...}` pair for the
101 handoff.
### Hardening
- **Smuggling guards (RFC 9112 §6.1).** Reject messages carrying both
`Content-Length` and `Transfer-Encoding: chunked`; reject differing
`Content-Length` values across duplicates or in a comma-list; reject
`Transfer-Encoding` on HTTP/1.0.
- **DoS guards.** Chunk-size hex capped at 16 digits; configurable
`max_body_size` enforced per stream; idle and request timers armed
as `gen_statem` timeouts (slowloris guard).
- **Field validation.** Encoder rejects CRLF in header names, methods,
paths, and reason phrases; parser rejects forbidden fields in
trailers per RFC 9110 §6.5.1; obs-fold re-validates the unfolded
value against `max_header_value_size`.
- **Response framing (RFC 9110 §6.3).** HEAD / 1xx / 204 / 304
responses are body-less regardless of framing headers;
close-delimited bodies finalise on socket close.
- **TLS defaults.** Client connects with `verify_peer` + OS CA trust +
hostname check + automatic SNI; user-supplied `ssl_opts` win on
every key.
- **Host enforcement.** Client auto-adds the `Host:` header from the
connect hostname; server rejects HTTP/1.1 requests missing `Host`
with 400 and closes the connection.
### Listener + client integration
- Built-in acceptor pool + listener (`h1_acceptor`, `h1_listener`) and
per-connection server loop (`h1_server`) that preserves pipelined
response byte order on the wire (RFC 9112 §9.3).
- Client connect helper (`h1_client`) drives TCP / TLS handshake,
socket ownership, and `wait_connected` synchronisation.
- Reference `ranch_protocol` module + docs covering drop-in Ranch
integration and ALPN multiplexing with `h2`.
### Tests
- 52 EUnit tests + 4 PropEr roundtrip properties.
- 149 Common Test cases across parser, encoder, capsule codec,
connection state machine, end-to-end client/server, Upgrade +
capsule exchange, Ranch integration, compliance vectors
(smuggling / framing / chunked / DoS) and interop (curl, plus
`python:3-alpine` and `nginx:alpine` under Docker).
### Documentation
- `README.md` — install, quickstart, full client & server walkthroughs,
TLS guidance, tuning, events and error reference, Ranch snippet.
- `docs/features.md` — RFC coverage, in-scope vs. intentionally
out-of-scope, internal module map.
- `docs/ranch.md` — production-shape protocol module, ALPN multiplex,
graceful drain, gotchas.
[0.1.0]: https://github.com/benoitc/erlang_h1/releases/tag/0.1.0
[0.1.1]: https://github.com/benoitc/erlang_h1/releases/tag/0.1.1
[0.2.0]: https://github.com/benoitc/erlang_h1/releases/tag/0.2.0
[0.2.1]: https://github.com/benoitc/erlang_h1/releases/tag/0.2.1