nhttp_h3 (nhttp_lib v1.0.0)
View SourceHTTP/3 protocol layer.
Pure functional HTTP/3 connection state machine (RFC 9114). Sits between
the QUIC transport (nquic) and the application layer. The caller manages
QUIC I/O and routes data to/from this module. Return values include
actions that the caller must execute via nquic.
Usage
H3 = nhttp_h3:new(server, #{}),
{ok, H3_1, Actions} = nhttp_h3:init_local_streams(H3, #{
control => CtrlId, encoder => EncId, decoder => DecId
}),
execute_actions(QConn, Actions),
loop(QConn, H3_1).Sending bodies and trailers
The HTTP/3 send surface is frame-oriented. The canonical
nhttp_lib:request/0 and nhttp_lib:response/0 maps can carry a body
and trailers field as a convenience for "everything is in memory", but
this layer does not consume those maps directly: the caller breaks the
exchange into discrete frame sends. The pattern is:
send_headers(Conn, StreamId, Headers, nofin)to emit pseudo-headers plus regular headers (HEADERS frame, QPACK-encoded).- Zero or more
send_data(Conn, StreamId, Chunk, nofin)calls. - Either
send_data(Conn, StreamId, FinalChunk, fin)to close on body, orsend_headers(Conn, StreamId, Trailers, fin)to close on trailers.
send_response/4 is the convenience one-shot for "headers + complete
body + END_STREAM" when the body is already a single iodata().
Summary
Functions
Register QUIC stream IDs for local unidirectional streams. Returns initial data to send on each (stream type prefix + settings on control).
Create a new HTTP/3 connection.
Process incoming data on any QUIC stream.
Encode and send data on a request stream.
Send GOAWAY on the control stream.
Encode and send headers on a request stream.
Encode and send a complete response (headers + body) on a request stream.
Combines HEADERS and DATA frames into a single send_fin action, avoiding
redundant stream lookups and state transitions compared to calling
send_headers/4 then send_data/4 separately.
Record the peer address on the connection. Called once after the QUIC
connection is established so server-built nhttp_lib:request/0 maps and
client-built nhttp_lib:response/0 events carry the correct remote peer.
Notify that the peer opened a new stream.
Handle a peer stream reset.
Types
-type action() :: {send, nhttp_lib:stream_id(), iodata()} | {send_fin, nhttp_lib:stream_id(), iodata()} | {close_connection, non_neg_integer(), binary()}.
-opaque conn()
-type error_code() :: nhttp_lib:error_code().
-type event() :: nhttp_lib:event_common() | {settings, h3_settings()} | {push_promise, nhttp_lib:stream_id(), non_neg_integer(), nhttp_lib:headers()}.
-type fin() :: nhttp_lib:fin().
-type h3_error() :: {connection_error, h3_error_code(), binary()} | {stream_error, nhttp_lib:stream_id(), h3_error_code(), binary()}.
-type h3_error_code() ::
h3_no_error | h3_general_protocol_error | h3_internal_error | h3_stream_creation_error |
h3_closed_critical_stream | h3_frame_unexpected | h3_frame_error | h3_excessive_load |
h3_id_error | h3_settings_error | h3_missing_settings | h3_request_rejected |
h3_request_cancelled | h3_request_incomplete | h3_message_error | h3_connect_error |
h3_version_fallback | qpack_decompression_failed | qpack_encoder_stream_error |
qpack_decoder_stream_error.
-type h3_settings() :: nhttp_h3_frame:h3_settings().
-type role() :: nhttp_lib:role().
Functions
-spec init_local_streams(conn(), #{control := nhttp_lib:stream_id(), encoder := nhttp_lib:stream_id(), decoder := nhttp_lib:stream_id()}) -> {ok, conn(), [action()]}.
Register QUIC stream IDs for local unidirectional streams. Returns initial data to send on each (stream type prefix + settings on control).
-spec new(role(), h3_settings()) -> conn().
Create a new HTTP/3 connection.
-spec recv(conn(), nhttp_lib:stream_id(), binary(), fin()) -> {ok, [event()], conn(), [action()]} | {error, h3_error()}.
Process incoming data on any QUIC stream.
-spec send_data(conn(), nhttp_lib:stream_id(), iodata(), fin()) -> {ok, conn(), [action()]} | {error, h3_error()}.
Encode and send data on a request stream.
Send GOAWAY on the control stream.
-spec send_headers(conn(), nhttp_lib:stream_id(), nhttp_lib:headers(), fin()) -> {ok, conn(), [action()]} | {error, h3_error()}.
Encode and send headers on a request stream.
-spec send_response(conn(), nhttp_lib:stream_id(), nhttp_lib:headers(), iodata()) -> {ok, conn(), [action()]} | {error, h3_error()}.
Encode and send a complete response (headers + body) on a request stream.
Combines HEADERS and DATA frames into a single send_fin action, avoiding
redundant stream lookups and state transitions compared to calling
send_headers/4 then send_data/4 separately.
-spec set_peer(conn(), nhttp_lib:peer()) -> conn().
Record the peer address on the connection. Called once after the QUIC
connection is established so server-built nhttp_lib:request/0 maps and
client-built nhttp_lib:response/0 events carry the correct remote peer.
-spec stream_opened(conn(), nhttp_lib:stream_id(), bidi | uni) -> {ok, conn()} | {error, h3_error()}.
Notify that the peer opened a new stream.
-spec stream_reset(conn(), nhttp_lib:stream_id(), non_neg_integer()) -> {ok, [event()], conn()}.
Handle a peer stream reset.