How to serve WebTransport
View SourceProblem
You want to accept WebTransport sessions (bidi/uni streams and datagrams) over HTTP/3 (or HTTP/2), served by your Livery handler.
Solution
livery_wt:upgrade/3 accepts a WebTransport session on an
extended-CONNECT request and hands the stream to the
webtransport library, driven by a handler you implement
(webtransport_handler behaviour).
The listener must advertise the WebTransport settings. Merge
webtransport:h3_settings/0 (H3) or webtransport:h2_settings/0
(H2) into the listener options; the adapter forwards the SETTINGS,
datagram support, and stream routing to the wire library:
Handler = fun(Req) -> livery_wt:upgrade(Req, my_wt_handler, #{}) end,
Opts = maps:merge(webtransport:h3_settings(), #{
cert => Cert, key => Key, stack => [], handler => Handler
}),
{ok, _} = livery_h3:start(Opts).WebTransport runs over H3 and H2 (RFC 9220 extended CONNECT). On
H1, upgrade/3 returns 501.
Implement the session handler
my_wt_handler implements the webtransport_handler behaviour
(from erlang-webtransport). An echo handler:
-module(my_wt_handler).
-behaviour(webtransport_handler).
-export([init/3, handle_stream_fin/4, handle_datagram/2]).
init(Session, _Req, _Opts) -> {ok, #{session => Session}}.
handle_stream_fin(StreamId, bidi, Data, State) ->
{ok, State, [{send, StreamId, Data, fin}]};
handle_stream_fin(_StreamId, uni, _Data, State) ->
{ok, State}.
handle_datagram(Data, State) ->
{ok, State, [{send_datagram, Data}]}.Notes
- On success
upgrade/3returns thetaken_oversentinel; the session belongs to thewebtransportprocess after that, so do not stack response-mutating middleware after it. - Requires
webtransport>= 0.2.3 (soaccept/4works from Livery's per-request worker process). - See
livery_wt_SUITEfor an end-to-end bidi-stream and datagram echo over H3.
See also
- Reference:
livery_wt, and theerlang-webtransportdocs for the session API and handler behaviour. - Concept: Adapters