Skip to content

beryl_mist

Mist WebSocket transport for beryl

This module provides the bridge between Mist's native WebSocket handling and the beryl runtime using Mist request and response types directly.

Transport configuration (path, on_connect authentication, origin policy) lives in beryl/transport/server; build a server.TransportConfig with its config builders and pass it to handler or upgrade. This module supplies only the Mist-specific glue: the WebSocket upgrade call, frame sending, and peer IP extraction.

pub fn handler(
beryl.Sockets,
server.TransportConfig(http.Connection),
fn(request.Request(http.Connection)) -> response.Response(mist.ResponseData)
) -> fn(request.Request(http.Connection)) -> response.Response(mist.ResponseData)

Build a combined request handler that serves both WebSocket upgrades and regular HTTP from a single Mist listener.

The returned function inspects and routes each request:

  • It passes WebSocket upgrade requests for the configured socket path to upgrade, which also runs any on_connect callback.
  • It passes all other requests to http_fallback. This includes non-upgrade requests and upgrades for a different path.

This removes the need to write an upgrade guard:

mist_transport.handler(sockets, server.default_config("/socket"), http_handler)
|> mist.new
|> mist.port(8000)
|> mist.start
pub fn upgrade(
request.Request(http.Connection),
beryl.Sockets,
server.TransportConfig(http.Connection),
fn() -> response.Response(mist.ResponseData)
) -> response.Response(mist.ResponseData)

Upgrade a request to WebSocket if it matches the configured path.

Usage in your Mist handler:

fn handle_request(http_request: Request(Connection), sockets: Sockets) -> Response(ResponseData) {
use <- mist_transport.upgrade(http_request, sockets, server.default_config("/socket"))
// Fall through to regular HTTP routing
case request.path_segments(http_request) {
[] -> index_page()
_ -> response.new(404) |> response.set_body(mist.Bytes(bytes_tree.new()))
}
}

Path matching, origin policy, ?vsn version negotiation, connection limits (per-IP and per beryl system on the current node, rejected with 429 Too Many Requests), and the on_connect callback use the shared admission pipeline. See beryl/transport/server.upgrade for the full contract. Enforcement uses the real socket peer IP from the TCP connection; forwarded headers such as X-Forwarded-For are not trusted.