The coquic::http3 layer translates HTTP/3 requests and responses into QUIC connection inputs. It does not own a UDP socket or a QUIC endpoint.
Use it as application protocol state above the QUIC transport. It can be paired with the low-level coquic::core API or with the coquic::quic facade.
#include "coquic/http3.h"Use this layer together with coquic::core or coquic::quic:
- Drive the QUIC endpoint from the runtime.
- Pass QUIC results into
http3::Clientorhttp3::Server. - Feed returned
quic_inputsback to the matching QUIC connection.
Use client_endpoint_config() and server_endpoint_config() to set endpoint role and ALPN to h3.
Data Types
HTTP messages use simple value types:
Field: one header field.Headers: vector of fields.RequestHead: method, scheme, authority, path, content length, headers.ResponseHead: status, content length, headers.Request: head, body, trailers.Response: interim heads, final head, body, trailers.Settings: local HTTP/3 and QPACK settings.
Errors use http3::ErrorCode and http3::Error. API calls that can fail use http3::Result<T>.
Client
http3::Client exposes:
submit_request(Request): enqueue a request and return its stream ID.on_quic_result(core::Result, TimePoint): consume QUIC events and emit HTTP/3 work.poll(TimePoint): produce pending HTTP/3 work without new QUIC input.has_failed(): terminal client failure state.
ClientUpdate contains:
quic_inputs: inputs to feed to the matching QUIC connection.responses: completed response events.request_errors: request cancellation/error events.has_pending_work: poll again without waiting for network input.terminal_failure: HTTP/3 layer failure.handled_local_error: whether a QUIC local error was consumed.
#include "coquic/http3.h"
void submit_http3_request(coquic::http3::Client &client) {
auto submitted = client.submit_request(coquic::http3::Request{
.head =
{
.method = "GET",
.scheme = "https",
.authority = "example.test",
.path = "/",
},
});
if (!submitted.has_value()) {
// Inspect submitted.error().
return;
}
coquic::core::Result ready;
ready.effects.push_back(coquic::core::StateEvent{
.connection = 1,
.change = coquic::core::StateChange::handshake_ready,
});
auto update = client.on_quic_result(ready, coquic::core::Clock::now());
for (auto &input : update.quic_inputs) {
// Feed input to the QUIC connection with core::ConnectionCommand or
// quic::Connection::advance.
}
}Server
http3::Server exposes:
on_quic_result(core::Result, TimePoint): consume QUIC events and emit HTTP/3 work.poll(TimePoint): produce pending HTTP/3 work.has_failed(): terminal server failure state.
ServerConfig provides request handlers:
request_head_handler: optional early response after the request head.request_handler: response after the full request is available.fallback_request_handler: explicit fallback path.
ServerUpdate contains QUIC inputs, cancelled request events, pending-work state, terminal failure state, and local-error handling state.
#include "coquic/http3.h"
#include <optional>
coquic::http3::Server make_server() {
return coquic::http3::Server({
.request_head_handler =
[](const coquic::http3::RequestHead &head)
-> std::optional<coquic::http3::Response> {
if (head.path == "/healthz") {
return coquic::http3::Response{
.head = {.status = 204, .content_length = 0},
};
}
return std::nullopt;
},
.request_handler =
[](const coquic::http3::Request &request) {
return coquic::http3::Response{
.head =
{
.status = 200,
.content_length = request.body.size(),
},
.body = request.body,
};
},
});
}Integration Notes
HTTP/3 objects are per-connection protocol state. They do not route QUIC connection handles by themselves. Feed each quic_inputs item to the QUIC connection that produced the corresponding HTTP/3 event stream.