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

  • Normal

    The handler closed it.

  • Remote

    The client sent a close frame.

  • Shutdown

    The handler closed it while the listener drained.

  • Timeout

    The 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 Subject that on_init got, or one selected by with_selector.

  • Draining(remaining: Int)

    The listener is draining: close the session within remaining milliseconds, or it is closed for you.

What to do after a callback, built with continue or close and the functions that follow them.

pub opaque type Next(state, custom)

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 continue(state: state) -> Next(state, custom)

Keep the session open.

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.

✨ Search Document