h2 (h2 v0.6.0)
View SourceHTTP/2 Public API
This module provides the public API for HTTP/2 client and server operations. It wraps the h2_connection state machine with a clean interface.
Client Usage
%% Connect to a server
{ok, Conn} = h2:connect("example.com", 443, #{}).
%% Send a request
{ok, StreamId} = h2:request(Conn, <<"GET">>, <<"/">>, [
{<<"host">>, <<"example.com">>}
]).
%% Receive response (messages sent to caller)
receive
{h2, Conn, {response, StreamId, Status, Headers}} ->
io:format("Status: ~p~n", [Status]);
{h2, Conn, {data, StreamId, Data, IsFin}} ->
io:format("Data: ~p~n", [Data])
end.
%% Close connection
ok = h2:close(Conn).Server Usage
%% Start server
{ok, Server} = h2:start_server(8443, #{
cert => "server.pem",
key => "server-key.pem",
handler => fun(Conn, StreamId, Method, Path, Headers) ->
h2:send_response(Conn, StreamId, 200, [{<<"content-type">>, <<"text/plain">>}]),
h2:send_data(Conn, StreamId, <<"Hello World!">>, true)
end
}).
%% Stop server
ok = h2:stop_server(Server).Event Messages
The owner process receives the following messages:
Client: - {h2, Conn, {response, StreamId, Status, Headers}} - {h2, Conn, {data, StreamId, Data, IsFin}} - {h2, Conn, {trailers, StreamId, Trailers}} - {h2, Conn, {stream_reset, StreamId, ErrorCode}} - {h2, Conn, {goaway, LastStreamId, ErrorCode}} - {h2, Conn, closed}
Server handler receives direct calls.
Summary
Functions
Cancel a stream.
Cancel a stream with a specific error code.
Close the connection immediately.
Connect to an HTTP/2 server. Uses TLS by default on port 443.
Connect to an HTTP/2 server with options.
Transfer connection ownership.
Get peer settings.
Get local settings.
Initiate graceful connection shutdown.
Initiate connection shutdown with error code.
Send an HTTP/2 request with pre-built headers (matches quic_h3:request/2). Headers should include pseudo-headers (:method, :path, :scheme, :authority).
Send an HTTP/2 request. For body-less requests (GET, HEAD, etc.), sends HEADERS with END_STREAM. For CONNECT (RFC 7540 §8.3) leaves the stream open so the caller can send tunnel bytes via send_data.
Send an HTTP/2 request with body. Sends HEADERS without END_STREAM, then sends DATA with END_STREAM.
Send data on a stream.
Send data on a stream with end_stream flag.
Send an HTTP/2 response (server mode).
Send trailers on a stream.
Return the TCP port the server is actually listening on.
Register a pid to receive body data for a stream. By default the connection replays any DATA frames buffered before the handler was registered as {h2, Conn, {data, StreamId, Data, Fin}} messages, and the call returns ok. Pass #{drain_buffer => true} to receive the buffered frames in the reply ({ok, [{Data, Fin}, ...]}) and forward them yourself — useful for tests, rarely for production code.
Start an HTTP/2 server.
Start a named HTTP/2 server (matches quic_h3:start_server/3).
Stop an HTTP/2 server.
Wait for a client connection to reach the connected state.
Types
-type connect_opts() :: #{transport => tcp | ssl, ssl_opts => [ssl:tls_client_option()], cert => binary() | string(), key => binary() | string(), cacerts => [binary()], verify => verify_none | verify_peer, settings => h2_settings:settings(), timeout => timeout(), connect_timeout => timeout(), sync => boolean()}.
-type connection() :: pid().
-type error_code() :: h2_error:error_code().
-type server_opts() :: #{transport => ssl | tcp, cert => binary() | string(), key => binary() | string(), cacerts => [binary()], verify => verify_none | verify_peer, ssl_opts => [ssl:tls_option()], handler := fun((connection(), stream_id(), binary(), binary(), headers()) -> any()), settings => h2_settings:settings(), acceptors => pos_integer(), enable_connect_protocol => boolean()}.
-type server_ref() :: {pid(), reference(), inet:port_number()}.
-type status() :: 100..599.
-type stream_id() :: non_neg_integer().
Functions
-spec cancel(connection(), stream_id()) -> ok | {error, term()}.
Cancel a stream.
-spec cancel(connection(), stream_id(), error_code()) -> ok | {error, term()}.
Cancel a stream with a specific error code.
-spec cancel_stream(connection(), stream_id()) -> ok | {error, term()}.
-spec cancel_stream(connection(), stream_id(), error_code()) -> ok | {error, term()}.
-spec close(connection()) -> ok.
Close the connection immediately.
-spec connect(string() | binary(), inet:port_number()) -> {ok, connection()} | {error, term()}.
Connect to an HTTP/2 server. Uses TLS by default on port 443.
-spec connect(string() | binary(), inet:port_number(), connect_opts()) -> {ok, connection()} | {error, term()}.
Connect to an HTTP/2 server with options.
-spec controlling_process(connection(), pid()) -> ok | {error, term()}.
Transfer connection ownership.
-spec get_peer_settings(connection()) -> h2_settings:settings().
Get peer settings.
-spec get_settings(connection()) -> h2_settings:settings().
Get local settings.
-spec goaway(connection()) -> ok | {error, term()}.
Initiate graceful connection shutdown.
-spec goaway(connection(), error_code()) -> ok | {error, term()}.
Initiate connection shutdown with error code.
-spec request(connection(), headers()) -> {ok, stream_id()} | {error, term()}.
Send an HTTP/2 request with pre-built headers (matches quic_h3:request/2). Headers should include pseudo-headers (:method, :path, :scheme, :authority).
-spec request(connection(), headers(), map()) -> {ok, stream_id()} | {error, term()}.
Send an HTTP/2 request. For body-less requests (GET, HEAD, etc.), sends HEADERS with END_STREAM. For CONNECT (RFC 7540 §8.3) leaves the stream open so the caller can send tunnel bytes via send_data.
-spec request(connection(), binary(), binary(), headers(), binary()) -> {ok, stream_id()} | {error, term()}.
Send an HTTP/2 request with body. Sends HEADERS without END_STREAM, then sends DATA with END_STREAM.
-spec send_data(connection(), stream_id(), binary()) -> ok | {error, term()}.
Send data on a stream.
-spec send_data(connection(), stream_id(), binary(), boolean()) -> ok | {error, term()}.
Send data on a stream with end_stream flag.
-spec send_response(connection(), stream_id(), status(), headers()) -> ok | {error, term()}.
Send an HTTP/2 response (server mode).
-spec send_trailers(connection(), stream_id(), headers()) -> ok | {error, term()}.
Send trailers on a stream.
-spec server_port(server_ref()) -> inet:port_number().
Return the TCP port the server is actually listening on.
-spec set_stream_handler(connection(), stream_id(), pid()) -> ok | {ok, [{binary(), boolean()}]} | {error, term()}.
Register a pid to receive body data for a stream. By default the connection replays any DATA frames buffered before the handler was registered as {h2, Conn, {data, StreamId, Data, Fin}} messages, and the call returns ok. Pass #{drain_buffer => true} to receive the buffered frames in the reply ({ok, [{Data, Fin}, ...]}) and forward them yourself — useful for tests, rarely for production code.
Backpressure: incoming DATA is rate-limited at the HTTP/2 flow-control layer only after we dispatch it to the handler. If the handler pid cannot keep up, its mailbox grows unbounded — bound your own consumer (e.g. with a selective receive + flow-control settings) when streaming large bodies from an untrusted peer.
-spec start_server(inet:port_number(), server_opts()) -> {ok, server_ref()} | {error, term()}.
Start an HTTP/2 server.
-spec start_server(atom(), inet:port_number(), server_opts()) -> {ok, server_ref()} | {error, term()}.
Start a named HTTP/2 server (matches quic_h3:start_server/3).
-spec stop_server(server_ref()) -> ok.
Stop an HTTP/2 server.
-spec unset_stream_handler(connection(), stream_id()) -> ok.
-spec wait_connected(connection()) -> ok | {error, term()}.
Wait for a client connection to reach the connected state.
-spec wait_connected(connection(), timeout()) -> ok | {error, term()}.