aeronet v1.5.0
Permanent link:
cppdashboard.dev/r/2026/08/aeronet-v1-5-0Modern, fast and ergonomic C++ HTTP/1.1, HTTP/2 and WebSocket server & client library for Linux, macOS and Windows, perfect for microservices.
Release notes
# [1.5.0] - 2026-08-20
## Breaking changes
- **HTTP CONNECT tunneling is now disabled by default**: an empty `HttpServerConfig::connectAllowlist` now rejects every
CONNECT target with `403 Forbidden` instead of allowing every resolved host. This closes an unauthenticated SSRF/open
proxy in default configurations across HTTP/1.1 and HTTP/2. Applications that intentionally provide CONNECT tunnels
must explicitly configure every trusted target hostname or IP with `withConnectAllowlist()` (or the
`connectAllowlist` JSON/YAML setting). Setting the allowlist to `["*"]` deliberately restores the previous unrestricted
behavior, allowing every host and port including loopback, private-network, link-local, and cloud metadata targets.
- **HttpRequestView::headerValue, headerValueOrEmpty, trailerValue, trailerValueOrEmpty, hasHeader and hasTrailer** are now all expecting lower ASCII case keys. This is enforced by the new parameter `LowerAsciiKey` that will fail to compile for constant strings (for instance, `headerValue("Host")` does not compile, but `headerValue("host")` does)
- **HttpRequestView::headers() && trailers() now return a case-sensitive map with lower case keys**: header names are normalized to lower-case when parsed, but the returned map have case sensitive look-ups. For instance, the code `req.headers().find("X-Header")` is now wrong (it can never match) and should be replaced with `req.headers().find("x-header")`. For simple lookups, prefer above methods that are safer and simpler.
- **http::Connection, http::ContentType, http::Host, etc. are now `LowerAsciiKey` instead of `std::string_view`** (compile-time validated once at their definition instead of at every call site). Fully backward-compatible for typical usage (implicit conversion back to std::string_view is available) -- only generic/template code asserting the exact type `std::string_view` would need adjustment. Pure formatting helpers (`http::ContentTypeHeaderSep` and similar `*Sep` constants, which are not header-name lookup keys) are unaffected and remain `std::string_view`.
- **File::Identity becomes private and File::identity() has been replaced with File::appendIdentityData()**: `File::Identity` is now a private nested type, and the public `File::identity()` method has been removed. The new `File::appendIdentityData(char* pData)` method writes the file's current descriptor identity and metadata to the provided buffer, returning a pointer past the last written byte. The buffer must be at least `File::kIdentitySize` bytes long.
- **Global header values should be trimmed of OWS**. This is to save some work on the http message finalization path.
## Bug Fixes
- **Client: heap-buffer-overflow when adding a header to a body-less request built with reserved header capacity**: `HttpClient::makeRequest(additionalCapacity, method, url)` (the overload without a body) was incorrectly computing indexes to its internal buffer.
- **HTTP/1.1 request is now rejected if it does not contain a Host header**: the server now returns `400 Bad Request` for HTTP/1.1 requests that do not include a `Host` header, per RFC 9112 §3.2.
- **Router updates could race server startup**: a route update submitted while the server was preparing to run could mutate the router directly while startup clamped route configuration, causing intermittent literal-route assertions. Startup now publishes a synchronized `Starting` state before launching its thread, so subsequent updates are queued for the event-loop thread.
- **Predicate and stop-token shutdown could leave a listener open without an event loop**: when cancellation arrived between event-loop iterations, `runUntil()` could reset its lifecycle without closing the listener or active connections. New TCP connections then succeeded but were never serviced, most visibly as intermittent 10-second Windows CI stalls. Predicate-driven exits now perform teardown on the event-loop thread, and lifecycle tests use a bounde… Share this resource