![]() |
Boost.Taar is a portable, header-only C++20 library that provides building blocks for writing HTTP servers on top of Boost.Asio, Boost.Beast, Boost.URL, and Boost.JSON.
The HTTP layer is organised around four ideas:
On top of that transport sit three optional protocol layers that reuse the same callables and the same state objects: a JSON-RPC 2.0 endpoint, a Model Context Protocol (MCP) server endpoint, and an OpenAPI document generator.
The library is header-only and does not require linking against a Taar binary. It does depend on the compiled Boost libraries that Boost.Asio, Boost.Beast, Boost.URL, Boost.JSON, and Boost.System require.
A matcher is a small object that inspects an HTTP request and answers the
question does this request belong to me?. Matchers compose
with the usual boolean operators (&&,
||, !)
and with relational operators (==,
!=) where it makes sense:
method == http::verb::get && target == "/api/sum/{a}/{b}"
Every matcher also carries a compile-time description of the constraints it imposes, which is what lets the OpenAPI generator document a route without re-parsing the expression.
A handler turns an HTTP request into an HTTP response. The library ships with two adapters:
taar::handler::rest wraps a plain callable. Arguments
declared on the callable are produced by argument providers
such as path_arg, query_arg, header_arg,
cookie_arg, string_body_arg, json_body_arg
and url_encoded_form_data_arg.
The return value of the callable is converted into an HTTP response via
the tag_invoke-based
response_from extension
point, so user-defined return types are supported out of the box.
taar::handler::htdocs serves static documents from
a root directory: safe path resolution, content types, validators and
conditional requests, ranges, precompressed variants and caching.
You can also supply a hand-written callable with the signature (request, context) -> http::message_generator,
or one returning a chunked_response
/ async_generator for streaming.
A callable may start with parameters of the form T&, T
const&
or std::shared_ptr<T> where
T is a context
type in scope. Those parameters are not fed by argument providers;
the library injects the matching object:
taar::session::basic_http<T>, one object per TCP connection, shared
by every request on it;
taar::handler::with_session,
looked up in a taar::context_store by a cookie or header
value, with idle expiry and per-key serialisation;
Mcp-Session-Id.
Asking for a type that is not in scope is a compile-time error at the registration site, so a handler cannot silently run without the state it expects.
The taar::session::http coroutine holds a list of (matcher,
handler) pairs registered through register_request_handler.
For each incoming request the session walks the list, runs the first matching
handler, writes the response, and continues to the next request on the same
keep-alive connection.
The session distinguishes soft errors (recoverable,
application-visible problems like a missing query parameter that can be turned
into a 400 response) from hard errors (connection-level
problems that take the connection down). Both have pluggable handlers, defaulting
to sane behaviour. A known path asked with the wrong method gets 405 with an Allow
header, and HEAD is served
from the matching GET route.
register_request_handler
accepts trailing registration observers, callables invoked
once with the route's matcher metadata and handler. This is how openapi::generator::describe learns about a route.
The taar::server::tcp coroutine binds, listens, and accepts
connections, spawning one HTTP session per connection. It integrates with
Asio cancellation signals so a single signal can shut down the whole server.
Each layer is an ordinary object you own. It keeps its own registry of callables and hands you a handler to register on one HTTP route.
taar::jsonrpc::endpoint<Context...>
implements JSON-RPC 2.0 on a single POST
route: named parameters bound with rpc_arg,
batches, notifications (answered 202),
the standard error codes, and a replaceable mapping from exceptions to
error objects.
taar::mcp::endpoint<Session,
Context...>
implements the Model Context Protocol over Streamable HTTP by composing
a JSON-RPC endpoint: tools with input schemas derived from parameter
types, resources and URI templates, the initialize
lifecycle, sessions identified by Mcp-Session-Id,
and a server-to-client event stream fed by notify
and broadcast.
taar::openapi::generator records REST routes at registration
time and renders an OpenAPI 3.1 document from the matcher metadata, the
argument providers and the callable's return type.
The same domain function can serve all three surfaces; each layer maps its arguments and its exceptions natively, so domain code stays protocol-agnostic. See the design notes for the rationale.