livery_ws (livery v0.6.0)
View SourceWebSocket integration on top of the ws library.
A handler that wants to upgrade a request to WebSocket calls
upgrade/3 inside its body. The function performs the
protocol-specific handshake by dispatching to the adapter's
accept_ws/4 helper. The return value is a sentinel response
(status = 101, body = taken_over) that tells livery:emit/3
no further bytes need to be written: the stream/socket now belongs
to the ws session.
my_ws_route(Req) ->
livery_ws:upgrade(Req, my_chat_handler, #{}).my_chat_handler is a module implementing the ws_handler
behaviour (defined by erlang_ws).
WebSocket runs over H1 (plain Upgrade), H2 (RFC 8441 extended
CONNECT, via livery_ws_h2), and H3 (RFC 9220 extended CONNECT,
via livery_ws_h3).
Summary
Functions
Split upgrade Opts into the two handshake option maps the adapters
need: {ValidateOpts, AcceptOpts}. ValidateOpts drives
ws_hN_upgrade:validate_request/2 (subprotocol negotiation) and
AcceptOpts drives ws:accept/6 (idle timeout). Both are #{} when the
respective key is absent, which makes the calls equivalent to the /1 and
/5 forms. Called by the H1/H2/H3 adapters.
Upgrade the current request to a WebSocket session.
Types
Functions
-spec handshake_opts(handler_opts()) -> {map(), map()}.
Split upgrade Opts into the two handshake option maps the adapters
need: {ValidateOpts, AcceptOpts}. ValidateOpts drives
ws_hN_upgrade:validate_request/2 (subprotocol negotiation) and
AcceptOpts drives ws:accept/6 (idle timeout). Both are #{} when the
respective key is absent, which makes the calls equivalent to the /1 and
/5 forms. Called by the H1/H2/H3 adapters.
-spec upgrade(livery_req:req(), handler_module(), handler_opts()) -> livery_resp:resp().
Upgrade the current request to a WebSocket session.
HandlerMod must implement the ws_handler behaviour. Opts
is a map forwarded as HMod:init(Req, Opts)'s second argument by
the ws library. Two keys are also interpreted by the handshake
(and left in Opts, so the handler still sees them):
subprotocols => [binary()]drives subprotocol negotiation: the first of these the client also offers is echoed in the responseSec-WebSocket-Protocol, and a client offering none of them is rejected. Omit to skip negotiation.idle_timeout => timeout()overrides the session idle timeout (infinitynever idle-closes). Omit for thewsdefault.
The handler's Req carries peer => {IpAddress, Port}, the client
address from the socket (H1), the h2 connection (H2), or the QUIC
connection (H3).
Returns a #livery_resp{} value:
status = 101, body = taken_overon a successful handshake. The adapter owns nothing further on this stream after this point.status = 400with a textual body when the inbound headers do not satisfy RFC 6455.status = 501when the adapter does not support WebSocket upgrades (H1, H2, and H3 all do).