Elixir bindings for the WTransport WebTransport library.
WebTransport is a web API that uses the HTTP/3 protocol as a bidirectional transport. It's intended for two-way communications between a web client and an HTTP/3 server. It supports sending data both unreliably via its datagram APIs, and reliably via its streams APIs.
WTransport is a pure-rust implementation of the WebTransport protocol.
The Wtransport Elixir bindings implement the server part of WTransport with an API heavily inspired by Thousand Island.
- Erlang/OTP (version 24 or greater)
- Elixir (version 1.12 or greater)
- The Rust compiler + Cargo (WTransport is written in Rust)
You'll also need TLS certificate files, even for local development, as HTTP/3 mandates the use of TLS.
A tool like mkcert can be handy for generating certificate files suitable for local development.
The package can be installed by adding wtransport
to your list of dependencies in mix.exs
:
def deps do
[
{:wtransport, git: "https://github.com/bugnano/wtransport-elixir.git"}
]
end
Wtransport is implemented as a supervision tree which is intended to be hosted inside a host application.
Example:
def start(_type, _args) do
wtransport_options = [
host: "localhost",
port: 4433,
certfile: "cert.pem",
keyfile: "key.pem",
connection_handler: MyApp.ConnectionHandler,
stream_handler: MyApp.StreamHandler
]
children = [
{Wtransport.Supervisor, wtransport_options}
]
opts = [strategy: :one_for_one, name: MyApp.Supervisor]
Supervisor.start_link(children, opts)
end
Aside from supervising the WTransport process tree,
applications interact with WTransport primarily via the
Wtransport.ConnectionHandler
and Wtransport.StreamHandler
behaviours.
Note that you have to pass the name of the modules of your application that implement the
Wtransport.ConnectionHandler
and Wtransport.StreamHandler
behaviours, as options
to the Wtransport.Supervisor
.
The Wtransport.ConnectionHandler
behaviour defines the interface that Wtransport uses to pass Wtransport.Connection
s up to the application level;
it is used to handle:
- Session requests (via the
handle_session
callback) - Connection requests (via the
handle_connection
callback) - Unreliable, unordered datagrams (via the
handle_datagram
callback)
A simple implementation for a Wtransport.ConnectionHandler
would look like this:
defmodule MyApp.ConnectionHandler do
use Wtransport.ConnectionHandler
@impl Wtransport.ConnectionHandler
def handle_datagram(dgram, %Wtransport.Connection{} = connection, state) do
:ok = Wtransport.Connection.send_datagram(connection, dgram)
{:continue, state}
end
end
The Wtransport.StreamHandler
behaviour defines the interface that Wtransport uses to pass Wtransport.Stream
s up to the application level;
it is used to handle:
- Stream requests (via the
handle_stream
callback) - Reliable, ordered data (via the
handle_data
callback)
A simple implementation for a Wtransport.StreamHandler
would look like this:
defmodule MyApp.StreamHandler do
use Wtransport.StreamHandler
@impl Wtransport.StreamHandler
def handle_data(data, %Wtransport.Stream{} = stream, state) do
if stream.stream_type == :bi do
:ok = Wtransport.Stream.send(stream, data)
end
{:continue, state}
end
end
Wtransport comes with a simple echo server to serve as an example;
it can be found in the examples/wtransport_echo
folder of this project.
Before starting it, change the runtime.exs
file to point to the correct
certificate paths, and run it with:
mix run --no-halt
After the server has been started, you can test it by pointing your browser to
https://webtransport.day/
and connect to the URL https://localhost:4433
(or https://[::1]:4433
if the server is listening on IPv6 only).
Everything in this repository except for the files in the examples/wtransport_echo
directory and its subdirectories,
is licensed under the MPL-2.0
The files under the examples/wtransport_echo
directory and its subdirectories,
are licensed under the Unlicense