WebSockets Guide ​
httpx.zig provides RFC 6455 WebSocket primitives: upgrade handshake helpers and binary framing. Everything lives under httpx.websocket.
What WebSocket Is ​
WebSocket (RFC 6455) provides full-duplex communication over a single TCP connection. The protocol starts with an HTTP/1.1 upgrade handshake, then switches to a binary framing protocol for bidirectional messaging between client and server.
The upgrade sequence:
- Client sends a GET request with
Upgrade: websocket,Connection: Upgrade,Sec-WebSocket-Key: <base64-nonce>, andSec-WebSocket-Version: 13. - Server validates the request, computes the accept key, and responds with
101 Switching ProtocolsandSec-WebSocket-Accept: <computed-key>. - Both sides communicate using binary frames from that point on.
Computing the Accept Key ​
Handshake.computeAccept concatenates the client key with the RFC 6455 magic GUID, SHA-1 hashes the result, and base64-encodes it:
var accept: [28]u8 = undefined;
httpx.websocket.computeAccept(clientKey, &accept);
// Set as Sec-WebSocket-Accept header value in your 101 responseUpgrade Requests ​
const req = try httpx.websocket.Handshake.buildUpgradeRequest(
allocator, host, path, key, &.{},
);
defer allocator.free(req);Validate a 101 response with Handshake.validateUpgradeResponse(head, &expectedAccept).
Encoding Frames ​
var hdr: [10]u8 = undefined;
const n = httpx.websocket.Frame.buildFrameHeader(&hdr, true, .text, payload.len, null);
// server-to-client frames are unmasked (maskKey = null)Client-to-server frames must be masked (pass a [4]u8 key) per RFC 6455; Frame.applyMask(data, key) masks payloads in place. Ping/pong/close use Opcode.ping, Opcode.pong, Opcode.close with Opcode.isControl().
Decoding Frames ​
Frame.parseFrameHeader(buf) parses one header and returns the header plus the number of bytes consumed:
const parsed = try httpx.websocket.Frame.parseFrameHeader(raw_bytes);
const hdr = parsed.hdr; // fin, opcode, masked, payloadLen, maskKey
// payload follows at raw_bytes[parsed.consumed..]Full Example ​
See examples/websocketServer.zig, which serves an interactive browser WebSocket client and verifies the endpoint:
var server = try httpx.Server.init(allocator, io, .{ .port = 0 });
defer server.deinit();
try server.get("/", htmlHandler); // serves the browser client page
const thread = try server.start();
defer thread.join();
defer server.requestShutdown();Types ​
| Type | Description |
|---|---|
Frame.Opcode | Frame opcode: continuation, text, binary, close, ping, pong |
Frame.FrameHeader | Decoded header: fin, opcode, masked, payloadLen, maskKey |
