2.2 KiB
subprotocol
Purpose
Implements RFC 6455 §4.1 subprotocol negotiation as a tiny pure function. The server is supplied the client's requested protocols and the server-supported list; the function returns the first server-supported protocol the client requested, or null when the client requested nothing.
This is exposed as a public utility because callers occasionally need to short-circuit the full handshake — for example, an OpenAPI documentation route advertising the engine's supported subprotocols before any actual upgrade.
Features
- Strict RFC 6455 ordering — server-supported list determines priority, NOT the client's preference list.
- Throws
WS_BUN.SUBPROTOCOL_UNSUPPORTEDwhen the client requested any subprotocol but none match. - Returns
nullfor the common "client requested nothing" case.
Usage: Basic
import { resolveSubprotocol } from "@suaveplan/api-ws-bun";
const chosen = resolveSubprotocol(
["graphql-transport-ws"],
["suaveplan.v1", "graphql-transport-ws"]
);
// chosen === "graphql-transport-ws"
Usage: Advanced
import { WS_BUN_CODES, resolveSubprotocol } from "@suaveplan/api-ws-bun";
try {
resolveSubprotocol(["unknown"], ["suaveplan.v1"]);
} catch (err) {
if ((err as { code?: string }).code === WS_BUN_CODES.SUBPROTOCOL_UNSUPPORTED) {
// respond 400 with `Sec-WebSocket-Protocol: <server's list>`
}
}
API Reference
resolveSubprotocol(requested, supported): string | null— pure negotiation function.
Implementation Notes
Server-priority ordering matters: a client might list ["graphql-ws", "graphql-transport-ws"] expecting the older protocol, but if the server prefers the newer one and lists it first, the function returns "graphql-transport-ws". That matches the RFC and matches the behaviour Bun's native Server.upgrade would apply if the negotiation were delegated to Bun itself.
The empty-requested short-circuit returns null rather than throwing because RFC 6455 explicitly permits handshakes with no Sec-WebSocket-Protocol header — the connection is valid, it just has no negotiated subprotocol. This is the default state for a Bun client written against the foundation's plain-JSON envelope wire format.