Module std.net.websocket

WebSocket client and server for bidirectional communication.

Client and server connections share the Conn type: send_text, send_binary, recv and recv_timeout behave the same in both directions. A received Message is Text or Binary; recv returns .None once the peer closes. wss:// verifies the server with the same tls.Trust and deadline as std.net.tls.

Client example

import std.net.websocket;

fn main() {
    var options = websocket.options();
    options.subprotocols = ["chat"];
    let ws = websocket.connect("ws://localhost:8080/ws", options).expect("connect");
    ws.send_text("hello").expect("send");
    match ws.recv_timeout(3s) {
        .Ok(.Some(websocket.Message.Text(text))) => println(text),
        .Ok(.Some(websocket.Message.Binary(data))) => println(f"{data.len()} bytes"),
        .Ok(.None) => println("closed"),
        .Err(e) => println(f"ws: {e}"),
    }
}

Server example

import std.net.websocket;

fn main() {
    let server = websocket.listen("0.0.0.0:8080").expect("listen");
    let conn = server.accept().expect("accept connection");
    if let .Ok(.Some(message)) = conn.recv() {
        match message {
            websocket.Message.Text(text) => conn.send_text(f"got {text}").expect("send"),
            websocket.Message.Binary(data) => conn.send_binary(data).expect("send"),
        }
    }
}

Contents

Functions

Function options

pub fn options() -> ConnectOptions

No subprotocols and tls.options().

Function connect

pub fn connect(url: string, options: ConnectOptions) -> Conn fails net.NetError

Open a WebSocket connection to url (client).

ws:// and wss:// are supported; wss:// verifies the server with options.tls.trust. Up to three redirects are followed, but never from wss:// to ws:// or back (InvalidArgument). options.tls.handshake_timeout bounds the TCP connect, the TLS handshake and the upgrade together (TimedOut); resolving the host name is not bounded by it. options.tls.io_timeout bounds each send. A non-empty options.subprotocols must have one selected by the server. A bad URL or subprotocol name is InvalidArgument; the error carries the precise failure detail.

Examples

import std.net.websocket;

fn main() {
    match websocket.connect("ws://127.0.0.1:9001/", websocket.options()) {
        .Ok(conn) => conn.close(),
        .Err(e) => println(f"connect failed: {e}"),
    }
}

Function listen

pub fn listen(addr: string) -> Result<Server, net.NetError>

Start a WebSocket server listening on the given address.

Returns Err(net.NetError) when the address cannot be bound. Use the returned error for the precise detail.

Examples

import std.net;
import std.net.websocket;

fn main() {
    match websocket.listen("127.0.0.1:0") {
        .Ok(server) => server.close(),
        .Err(_) => println(f"listen failed"),
    }
}

Types

Enum Message

One received WebSocket data message.

Variants

Text(string)
Binary(bytes)

Struct ConnectOptions

How connect negotiates and verifies a client connection.

Fields

subprotocols: Vec<string>

Subprotocols offered in preference order; when non-empty the server must select one or the connect fails.

tls: tls.TlsOptions

Trust and deadlines for wss:// (and the deadlines for ws://).

Struct Conn

An open WebSocket connection handle.

Created by websocket.connect(url, options) or server.accept(). Released at scope exit or by close().

Methods

fn subprotocol(self) -> Option<string>

The subprotocol the server selected, or .None when none was offered or the connection was accepted by a server.

fn send_text(self, text: string) -> Result<(), net.NetError>

Send a text message. After an error the connection is unusable.

fn send_binary(self, data: bytes) -> Result<(), net.NetError>

Send a binary message. After an error the connection is unusable.

fn recv(self) -> Result<Option<Message>, net.NetError>

Wait for the next message; .None once the peer has closed.

fn recv_timeout(self, timeout: duration) -> Result<Option<Message>, net.NetError>

Wait at most timeout for the next message: Err(TimedOut(0)) when it passes, .None once the peer has closed.

fn attach(self, handler: WebSocketHandler)

Attach this connection to an actor (Erlang-style active mode). The runtime reads frames in a background thread and delivers each text message as an on_message actor message; binary messages are not delivered in active mode. The connection remains the caller's resource; attach transfers read authority only. Outbound sends and close remain valid.

handler is the actor that will receive on_message and on_close. The compiler synthesises both protocol message IDs from the concrete actor type behind the handle.

Struct Server

A WebSocket server listening for incoming connections.

Created by calling websocket.listen(addr), which returns Err when the address cannot be bound. Use accept() to wait for the next client connection.

Methods

fn accept(self) -> Conn fails net.NetError

Wait for the next client to complete a WebSocket handshake. A scope deadline cancels this wait without closing the listener.

fn port(self) -> i64

Get the port the server is listening on.

Traits

Trait WebSocketHandler

Trait for actors that handle WebSocket connections.

Implement this on an actor and call conn.attach(actor) to have the runtime deliver frames as actor messages. The actor never calls recv() — the runtime reads in a background thread.

Example

import std.net.websocket;

actor Echo {
    let conn: websocket.Conn;
    receive fn on_message(text: string) {
        let _ = conn.send_text("echo: " + text);
    }
    receive fn on_close() {
        println("disconnected");
    }
}

Methods

fn on_message(text: string)

Called when a text message arrives; binary messages are not delivered in active mode.

fn on_close()

Called when the connection closes or errors.

Inherent methods

impl Conn

fn close(consume self)

Release this connection early. Scope exit performs the same release.

impl Server

fn close(consume self)

Stop listening and release this server early.