livery_h2 (livery v0.13.0)

View Source

HTTP/2 adapter on top of the h2 library.

Starts an h2 server bound to a Livery middleware stack and handler. h2 runs the handler fun in a process of its own for every request. In that process the adapter:

  1. Builds a #livery_req{} from the method, path, and headers delivered by h2.
  2. Registers the process as the h2 stream handler, so the body and trailer events of the stream (and any that arrived earlier) come to it.
  3. Hands over to livery_translator, which starts the livery_req_proc worker and turns the {h2, Conn, _} events into the {livery_body, Ref, _} messages the worker reads via livery_body, until the worker exits.

Response emission goes through livery:emit/3 and lands on the adapter callbacks (send_headers/4, send_data/3, send_trailers/2, reset/2), which call into h2:send_response/4, h2:send_data/3,4, and h2:send_trailers/3. extended_connect is reported as supported in capabilities/1.

Summary

Functions

Accept a WebSocket session on an extended-CONNECT stream.

Hand an extended-CONNECT stream to the webtransport library.

Build the h2:serve_socket/2 option map for a socket the caller already accepted and handshaked.

Start a listener with the given options.

Types

listen_opts()

-type listen_opts() ::
          #{port => inet:port_number(),
            ip => inet:ip_address(),
            inet6 => boolean(),
            transport => tcp | ssl,
            cert => binary() | string(),
            key => binary() | string(),
            cacerts => [binary()],
            verify => verify_none | verify_peer,
            ssl_opts => [ssl:tls_server_option()],
            acceptors => pos_integer(),
            enable_connect_protocol => boolean(),
            max_body => non_neg_integer() | infinity,
            config => term(),
            stack := livery_middleware:stack(),
            handler := livery_middleware:handler()}.

listener()

-type listener() :: h2:server_ref().

stream()

-type stream() :: {h2:connection(), h2:stream_id(), binary() | undefined}.

Functions

accept_ws/4

-spec accept_ws(stream(), livery_req:req(), module(), term()) -> {ok, pid()} | {error, term()}.

Accept a WebSocket session on an extended-CONNECT stream.

Validates the RFC 8441 handshake, replies 200 (extended CONNECT uses 200, not 101), then hands the stream to the ws library driven by the livery_ws_h2 transport.

accept_wt/4

-spec accept_wt(stream(), livery_req:req(), module(), term()) -> {ok, pid()} | {error, term()}.

Hand an extended-CONNECT stream to the webtransport library.

Reconstructs the CONNECT pseudo-headers from the request value (the adapter delivers method/path out of band, but webtransport:accept/4 expects them inline) and calls webtransport:accept/4 with transport => h2.

capabilities(Listener)

-spec capabilities(listener()) -> livery_adapter:capabilities().

peer_info/1

-spec peer_info(stream()) -> livery_adapter:peer_info().

reset/2

-spec reset(stream(), term()) -> ok.

send_data/3

send_full/5

-spec send_full(stream(), 100..599, [{binary(), binary()}], iodata(), livery_adapter:send_opts()) ->
                   livery_adapter:send_result().

send_headers/4

-spec send_headers(stream(), 100..599, [{binary(), binary()}], livery_adapter:send_opts()) ->
                      livery_adapter:send_result().

send_informational/3

-spec send_informational(stream(), 100..199, [{binary(), binary()}]) -> livery_adapter:send_result().

send_trailers/2

-spec send_trailers(stream(), [{binary(), binary()}]) -> livery_adapter:send_result().

serve_opts(Opts, Alpn)

-spec serve_opts(listen_opts(), binary() | undefined) -> map().

Build the h2:serve_socket/2 option map for a socket the caller already accepted and handshaked.

Used by livery_h1h2 after ALPN settles on h2. Opts is the listener's listen_opts(); Alpn is the protocol actually negotiated. Listen-time keys (cert, acceptors, ...) are dropped: the socket is already up, so only the per-connection options apply.

start(Opts)

-spec start(listen_opts()) -> {ok, listener()} | {error, term()}.

Start a listener with the given options.

Opts must include stack and handler. port defaults to 0 (random port). transport defaults to tcp for h2c; pass ssl plus cert and key to serve over TLS with ALPN-negotiated h2.

start(Name, Opts, StartOpts)

-spec start(atom() | undefined, listen_opts(), map()) -> {ok, listener()} | {error, term()}.

stop(Listener)

-spec stop(listener()) -> ok.