roadrunner_gleam/websocket
WebSocket sessions.
A handler upgrades a request by returning upgrade(builder). The
session then runs in the connection’s process: on_init runs once
after the handshake, handler gets every message, and on_close runs
when the session ends.
fn handle(request: Request) -> Response {
case request.path_segments(request) {
["ws"] ->
websocket.new(
on_init: fn(_subject) { websocket.continue(Nil) },
handler: fn(state, message) {
case message {
websocket.Text(text) ->
websocket.continue(state)
|> websocket.send([websocket.TextFrame(text)])
_ -> websocket.continue(state)
}
},
)
|> websocket.upgrade
_ -> response.new(404)
}
}
Roadrunner serves WebSocket over HTTP/1.1. An upgrade asked over
HTTP/2 or HTTP/3 is answered 501.
Types
A WebSocket session, built with new and the functions that follow it.
pub opaque type Builder(state, custom)
Why the session ended.
pub type CloseReason {
Normal
Remote
Shutdown
Timeout
Failed(String)
}
Constructors
-
NormalThe handler closed it.
-
RemoteThe client sent a close frame.
-
ShutdownThe handler closed it while the listener drained.
-
TimeoutThe client sent nothing for the session’s
idle_timeout. -
Failed(String)The connection or the client failed.
A frame to send to the client.
pub type Frame {
TextFrame(String)
BinaryFrame(BitArray)
PingFrame(BitArray)
}
Constructors
-
TextFrame(String) -
BinaryFrame(BitArray) -
PingFrame(BitArray)A ping, with at most 125 bytes of data: a longer one ends the session.
What the handler gets.
pub type Message(custom) {
Text(String)
Binary(BitArray)
Custom(custom)
Draining(remaining: Int)
}
Constructors
-
Text(String)A text message from the client.
-
Binary(BitArray)A binary message from the client.
-
Custom(custom)A message sent to the
Subjectthaton_initgot, or one selected bywith_selector. -
Draining(remaining: Int)The listener is draining: close the session within
remainingmilliseconds, or it is closed for you.
Values
pub fn close(state: state) -> Next(state, custom)
Close the session normally, with code 1000.
pub fn close_with(
state: state,
code code: Int,
reason reason: String,
) -> Next(state, custom)
Close the session with a close code and a reason. code must be one a
server may send: 1000 to 1003, 1007 to 1014, or 3000 to 4999. reason
must be at most 123 bytes.
pub fn compress(
builder: Builder(state, custom),
compress: Bool,
) -> Builder(state, custom)
Whether to accept the client’s offer to compress messages
(permessage-deflate). Defaults to the listener’s ws option.
pub fn hibernate_after(
builder: Builder(state, custom),
milliseconds: Int,
) -> Builder(state, custom)
Hibernate the session after this many milliseconds without messages, which saves memory on mostly idle sessions.
pub fn idle_timeout(
builder: Builder(state, custom),
milliseconds: Int,
) -> Builder(state, custom)
Close the session, with code 1001, when the client sends nothing for this many milliseconds.
pub fn max_frame_size(
builder: Builder(state, custom),
bytes: Int,
) -> Builder(state, custom)
The largest frame, in bytes, the client may send.
pub fn max_message_size(
builder: Builder(state, custom),
bytes: Int,
) -> Builder(state, custom)
The largest message, in bytes, the client may send.
pub fn new(
on_init on_init: fn(process.Subject(custom)) -> Next(
state,
custom,
),
handler handler: fn(state, Message(custom)) -> Next(
state,
custom,
),
) -> Builder(state, custom)
A session. on_init gets a Subject owned by the session: messages
sent to it reach handler as Custom, so other processes can push to
the client through it.
pub fn on_close(
builder: Builder(state, custom),
on_close: fn(state, CloseReason) -> Nil,
) -> Builder(state, custom)
Run on_close when the session ends in an orderly way. It does not run
when a callback crashes.
pub fn send(
next: Next(state, custom),
frames: List(Frame),
) -> Next(state, custom)
Send these frames to the client, before the close frame when closing.
pub fn upgrade(
builder: Builder(state, custom),
) -> response.Response(response.Body)
The response that upgrades the request to the session. Headers set on
it with gleam/http/response.set_header go on the 101 Switching Protocols
response, such as a set-cookie.
pub fn with_selector(
next: Next(state, custom),
selector: process.Selector(custom),
) -> Next(state, custom)
Also receive the messages this selector selects, as Custom, from now
on: monitors, messages to other subjects, or anything else. It replaces
the selector set before; messages to the session’s Subject always
arrive.