nhttp_h2 (nhttp_lib v1.0.0)
View SourceHTTP/2 protocol layer.
This module implements RFC 9113 HTTP/2 connection and stream state machines. It sits between the framing layer (nhttp_h2_frame) and the application layer, providing:
- Connection lifecycle management (preface, settings, shutdown)
- Stream state machine (RFC 9113 Section 5.1)
- Flow control (connection and stream level)
- Header block assembly (CONTINUATION handling)
- Error handling (connection vs stream errors)
Usage
Conn0 = nhttp_h2:new(client),
Preface = nhttp_h2:preface(Conn0),
ok = ssl:send(Socket, Preface),
{ok, Events, Conn1} = nhttp_h2:recv(Conn0, Data),
lists:foreach(fun handle_event/1, Events),
{ok, Conn2, Frames} = nhttp_h2:send_headers(Conn1, StreamId, Headers, fin),
ok = ssl:send(Socket, Frames).Sending bodies and trailers
The HTTP/2 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 + optional CONTINUATION).- 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.
For a one-shot send when the body is already a single iodata(), call
send_headers/4 with nofin followed by send_data/4 with fin.
Flow-control and END_STREAM ride on the DATA frame.
Summary
Functions
Create a new HTTP/2 connection with default settings.
Create a new HTTP/2 connection with custom settings.
Open a new stream and return its ID.
Generate the connection preface for this role. Client sends: magic + SETTINGS. Server sends: SETTINGS.
Process incoming data and return events. May return frames to send (e.g., SETTINGS_ACK, PING_ACK, WINDOW_UPDATE).
Send DATA frame(s).
Send GOAWAY to initiate graceful shutdown.
Send HEADERS frame for a new request/response or trailers.
Send PING frame with caller-supplied 8-byte opaque data. The caller is
responsible for generating the opaque value (e.g. via
crypto:strong_rand_bytes(8)) and matching it against the PING_ACK event.
Send RST_STREAM to cancel a stream.
Send WINDOW_UPDATE for connection or stream.
Record the peer address on the connection. Called once after the socket is
accepted (or connected) so server-built nhttp_lib:request/0 maps and
client-built nhttp_lib:response/0 events carry the correct remote peer.
Types
-opaque conn()
-type error_code() :: nhttp_lib:error_code().
-type event() :: nhttp_lib:event_common() | {stream_closed, nhttp_lib:stream_id(), error_code()} | {stream_refused, nhttp_lib:stream_id()} | {window_update, nhttp_lib:stream_id(), pos_integer()} | {settings, settings()} | settings_ack | {ping, binary()} | {ping_ack, binary()}.
-type fin() :: nhttp_lib:fin().
-type priority() :: #{exclusive := boolean(), stream_dependency := nhttp_lib:stream_id(), weight := 1..256}.
-type role() :: nhttp_lib:role().
-type send_error() :: connection_closing | {unknown_stream, nhttp_lib:stream_id()} | {stream_closed, nhttp_lib:stream_id()} | {stream_error, nhttp_lib:stream_id(), error_code(), binary()}.
-type settings() :: #{header_table_size => non_neg_integer(), enable_push => boolean(), max_concurrent_streams => pos_integer() | infinity, initial_window_size => 1..2147483647, max_frame_size => 16384..16777215, max_header_list_size => pos_integer() | infinity, enable_connect_protocol => boolean()}.
-type stream_state() ::
idle | reserved_local | reserved_remote | open | half_closed_local | half_closed_remote |
closed.
Functions
Create a new HTTP/2 connection with default settings.
Create a new HTTP/2 connection with custom settings.
-spec open_stream(conn()) -> {ok, nhttp_lib:stream_id(), conn()} | {error, connection_closing | max_streams_reached}.
Open a new stream and return its ID.
Generate the connection preface for this role. Client sends: magic + SETTINGS. Server sends: SETTINGS.
-spec recv(conn(), binary()) -> recv_result().
Process incoming data and return events. May return frames to send (e.g., SETTINGS_ACK, PING_ACK, WINDOW_UPDATE).
-spec send_data(conn(), nhttp_lib:stream_id(), iodata(), fin()) -> send_result().
Send DATA frame(s).
-spec send_goaway(conn(), error_code(), binary()) -> send_result().
Send GOAWAY to initiate graceful shutdown.
-spec send_headers(conn(), nhttp_lib:stream_id(), nhttp_lib:headers(), fin()) -> send_result().
Send HEADERS frame for a new request/response or trailers.
-spec send_ping(conn(), <<_:64>>) -> send_result().
Send PING frame with caller-supplied 8-byte opaque data. The caller is
responsible for generating the opaque value (e.g. via
crypto:strong_rand_bytes(8)) and matching it against the PING_ACK event.
-spec send_rst_stream(conn(), nhttp_lib:stream_id(), error_code()) -> send_result().
Send RST_STREAM to cancel a stream.
-spec send_window_update(conn(), nhttp_lib:stream_id() | connection, pos_integer()) -> send_result().
Send WINDOW_UPDATE for connection or stream.
-spec set_peer(conn(), nhttp_lib:peer()) -> conn().
Record the peer address on the connection. Called once after the socket is
accepted (or connected) so server-built nhttp_lib:request/0 maps and
client-built nhttp_lib:response/0 events carry the correct remote peer.