How it is put together

What a program sees is a handful of move-only handles, each a pointer to an implementation that the protocol backend provides: that is the type erasure. So a server::Request and a client::Response are a Reader, a server::Response and a client::Request are a Writer, and all of them have no data members but that pointer. Moving one into a Reader or Writer hands off that half with its ownership intact.

The classes of the library and how they relate

Layers

Each protocol lives in a directory of its own, in both include/anyhttp/ and src/. Only these may include the header of the protocol library that goes with them, which is what keeps nghttp2, ngtcp2 and nghttp3 from being compile-time dependencies of anyone who uses anyhttp:

Directory

Protocol

On top of

h1/

HTTP/1.1

Beast’s parser and serializer

h2/

HTTP/2

nghttp2

h2v2/

HTTP/2, an alternative to h2/, see The HTTP/2 library

nghttp2 version 2

quic/

QUIC transport, and plain QUIC streams

ngtcp2

h3/

HTTP/3

nghttp3, and quic/

asio/, corosio/

the runtime, see I/O runtimes: Asio and Corosio

Asio, or Corosio and Capy

Generic code (server_impl.*, client_impl.*) reaches a backend only through h1/backend.hpp, h2/backend.hpp, quic/backend.hpp and h3/backend.hpp, and the runtime only through anyhttp/runtime.hpp and anyhttp/net.hpp.

QUIC and HTTP/3 are two layers, and each shares one implementation between server and client. quic/session.* has all ngtcp2 callbacks, packet writing, timers and connection flow control, and quic/stream.* what every stream has. What runs on a connection is a QuicApplication, picked by ALPN: HTTP/3 is one (h3/application.*), and plain QUIC streams are the other (quic/streams.*). That no HTTP is in the transport is something the build can verify, see CLAUDE.md.

What gets installed is the public headers, the ones reachable from client.hpp, server.hpp, quic.hpp, session.hpp and the like: cmake/install.cmake leaves out the protocol directories, net.hpp and *_impl.hpp.

History

This project started as a hand-written replacement for nghttp2-asio. Once the concept was working, HTTP/1.1 was added, and both protocols were hidden behind a type-erased interface. Finally, HTTP/3 was added with the help of agentic coding.