websocket
stableWebSocket client plugin providing a WsClient class for connecting to servers plus utility functions for frame encoding/decoding, URL parsing, and handshake validation.
use plugin websocket::{WsClient.new, send, receive, …} Functions (16)
- WsClient.new Connect to a WebSocket server URL
- send Send a text or binary message
- receive Receive the next message from the server
- ping Send a ping control frame
- pong Send a pong response frame
- send_binary Send raw bytes as a binary frame
- ready_state Get the connection state string
- close Close the WebSocket connection
- encode_frame Encode a raw WebSocket frame
- decode_frame Decode a WebSocket frame from bytes
- build_handshake_request Build an HTTP upgrade request string
- validate_handshake_response Validate a server handshake response
- generate_key Generate a random WebSocket key
- encode_close_frame Encode a close frame payload
- parse_close_frame Parse a close frame payload
- parse_url Parse a ws:// or wss:// URL
Overview
websocket is a synchronous WebSocket client built on a WsClient handle: call WsClient.new(url) to dial a ws:// or wss:// server, then send, receive, ping, and close on the returned handle. Calls block until the operation completes, and the handle owns the live connection, so the same object is threaded through every interaction. Use it whenever you need a simple request/response or streaming exchange with a WebSocket endpoint.
Alongside the client class, the plugin exposes a set of stateless protocol helpers — encode_frame/decode_frame, parse_url, generate_key, build_handshake_request/validate_handshake_response, and the close-frame codecs. These let you inspect or assemble the raw RFC 6455 wire format, or implement a custom client over a plain TCP socket, without touching the WsClient class at all.
Common patterns
Connect, exchange a few messages, then close cleanly:
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080/chat")
ws.send("hello")
let reply = ws.receive()
print("server says: {reply["data"]}")
ws.close()
Drive a receive loop until the server sends a close frame:
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://echo.example.com")
ws.send("first")
ws.send("second")
while ws.ready_state() == "open" {
let msg = ws.receive()
if msg["type"] == "close" {
print("closed: {msg["reason"]}")
break
}
print("got {msg["type"]}: {msg["data"]}")
}
Build the raw handshake yourself with the protocol helpers (for a custom TCP client):
use plugin websocket::{parse_url, generate_key, build_handshake_request, validate_handshake_response}
let parts = parse_url("wss://example.com/chat")
let key = generate_key()
let request = build_handshake_request(parts["host"], parts["path"], key)
// ...send `request` over a socket, read the HTTP response...
if validate_handshake_response(http_response, key) {
print("upgrade accepted")
}
Connect to a WebSocket server URL
Connects to a WebSocket server at url (must be a ws:// or wss:// URL) and returns a WsClient handle. Blocks until the connection and handshake complete.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080/chat")
ws.send("Hello, server!")
Send a text or binary message
Sends a message over the connection. Pass a string to send a text frame, or bytes to send a binary frame.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080")
ws.send("ping")
ws.send_binary([0x01, 0x02, 0x03])
Receive the next message from the server
Blocks until a message arrives and returns a table with a type field ("text", "binary", "ping", "pong", or "close") and a data or reason field.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080")
ws.send("hello")
let msg = ws.receive()
if msg["type"] == "text" {
print("server says: {msg["data"]}")
}
Branch on the frame type to handle control frames and binary data separately:
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080")
let msg = ws.receive()
if msg["type"] == "binary" {
print("binary payload of {msg["data"].len()} bytes")
} else if msg["type"] == "close" {
print("server closed: {msg["reason"]}")
}
Send a ping control frame
Sends a bare ping control frame. The server should respond with a pong. Use to keep idle connections alive or to measure round-trip latency.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://echo.example.com")
ws.ping()
let resp = ws.receive()
print("pong type: {resp["type"]}")
Send a pong response frame
Sends a pong frame, optionally echoing the payload from a received ping. Use when handling ping frames manually.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080")
let msg = ws.receive()
if msg["type"] == "ping" {
ws.pong(msg["data"])
}
Send raw bytes as a binary frame
Sends raw bytes as a WebSocket binary frame.
Get the connection state string
Returns "open" if the connection is active, or "closed" if it has been shut down.
use plugin websocket::{WsClient}
let ws = WsClient.new("ws://localhost:8080")
print(ws.ready_state()) // "open"
ws.close()
print(ws.ready_state()) // "closed"
Close the WebSocket connection
Sends a close frame and shuts down the connection. Subsequent calls to send or receive will error.
Encode a raw WebSocket frame
Encodes a WebSocket frame with the given opcode (1=text, 2=binary, 8=close, 9=ping, 10=pong), payload, and masking flag. Client frames must be masked per RFC 6455.
use plugin websocket::{encode_frame}
let frame = encode_frame(1, "hello", true)
Encode an unmasked ping control frame (opcode 9) with an empty payload — a server-side or test frame that you can feed straight to decode_frame:
use plugin websocket::{encode_frame, decode_frame}
let ping = encode_frame(9, "", false)
let parsed = decode_frame(ping)
print("opcode {parsed["opcode"]} masked={parsed["masked"]}")
Decode a WebSocket frame from bytes
Parses a WebSocket frame from raw bytes. Returns full metadata including the decoded (unmasked) payload.
use plugin websocket::{decode_frame}
let f = decode_frame(raw)
print("opcode {f["opcode"]} payload: {f["payload"]}")
Build an HTTP upgrade request string
Builds a valid HTTP/1.1 WebSocket upgrade request string. Use when implementing a custom WebSocket client over a raw TCP connection.
use plugin websocket::{build_handshake_request, generate_key}
let key = generate_key()
let req = build_handshake_request("example.com", "/chat", key)
Validate a server handshake response
Verifies that the server's HTTP 101 response contains a valid Sec-WebSocket-Accept header derived from the original client key.
use plugin websocket::{validate_handshake_response}
let ok = validate_handshake_response(http_response, original_key)
if ok {
print("handshake valid")
}
Generate a random WebSocket key
Generates a random 16-byte base64-encoded string suitable for use as a Sec-WebSocket-Key request header.
use plugin websocket::{generate_key}
let key = generate_key()
print("key: {key}")
Encode a close frame payload
Encodes the payload for a WebSocket close frame: 2-byte big-endian status code followed by the UTF-8 reason string.
use plugin websocket::{encode_close_frame, parse_close_frame}
let payload = encode_close_frame(1000, "normal shutdown")
let info = parse_close_frame(payload)
print("code={info["code"]} reason={info["reason"]}")
Parse a close frame payload
Parses the payload of a close frame into a code integer and a reason string.
use plugin websocket::{parse_close_frame}
let info = parse_close_frame(close_payload)
print("code={info["code"]} reason={info["reason"]}")
Parse a ws:// or wss:// URL
Parses a ws:// or wss:// URL into its components. Default port is 80 for ws and 443 for wss.
use plugin websocket::{parse_url}
let parts = parse_url("wss://example.com:8443/chat")
print("{parts["scheme"]} {parts["host"]}:{parts["port"]}{parts["path"]}")