export = WebsocketClient; /** * Typedef Imports * @typedef {import("../RestNio")} RestNio * @typedef {import("../util/Options").ClientProperties} ClientProperties * @typedef {import("../codec").Codec} Codec */ /** * @class WebSocketClient * @extends Client * @author 7kasper * @classdesc * Represents a websocket client. * A websocket client is backed by an open websocket connection. * Unlike the http connection, this client isn't restfull and can have * information stored on it (via {@link Client#state}) and be subscribed * to topics. * * Wire format is negotiated at handshake via `Sec-WebSocket-Protocol`: * - `restnio.json` (default) — envelopes travel as text frames. * - `restnio.msgpack` — envelopes travel as binary frames; disambiguated from * raw binary data via a cheap first-byte sniff plus shape check. * * Binary frame routing: * - If {@link WebSocketClient#binRoute} is set (via `setBinRoute(name)`) all * incoming binary frames go to the `wsBin-` route with * `params = { data: Buffer, size: number }`. * - Otherwise, for MessagePack clients the sniff may reclaim a frame as an * envelope; anything that isn't an envelope falls through to the default * `wsBin` route, which errors unless the application overrode it via * `router.wsBin(handler)`. */ declare class WebsocketClient extends Client { /** * Creates a new WebsocketClient instance. * @param {RestNio} restnio - reference to the server. * @param {websocket} ws - the websocket object wrapping * @param {request} request - the http request object. * @param {ClientProperties} [props] - optional extra client properties. */ constructor(restnio: RestNio, ws: websocket, request: request, props?: ClientProperties); ws: websocket; isActive: boolean; isAlive: boolean; /** * The wire-format codec negotiated for this client at handshake. * @type {Codec} */ codec: Codec; /** * Name of the currently-active binary route, or null when no explicit * route is bound. Incoming binary frames are dispatched to * `wsBin-` when set. Use {@link WebSocketClient#setBinRoute} * to mutate. * @type {string|null} */ binRoute: string | null; motd(): Promise; /** * Sends a plain string as a text frame. Text frames are always treated by * the server as JSON envelopes on the receive side, regardless of codec. * @param {string} str */ str(str: string): void; /** * Sends an object to the client, using the negotiated codec. * * - `Buffer` input is always sent as-is on a binary frame (no encoding). * - For JSON clients a plain string is sent as a text frame (unless * `jsonResponse` is truthy, in which case it is JSON-stringified). * - Otherwise the codec is asked to encode; string results go on a text * frame, `Buffer` results on a binary frame. * @param {*} obj */ obj(obj: any): void; err(err: any, code?: number): void; /** * Sets the active binary route name. While set, every incoming binary * frame on this client is dispatched as raw bytes to the matching * `wsBin-` route. Pass `null` (or call {@link WebSocketClient#clearBinRoute}) * to return to the default behavior. * @param {string|null} name */ setBinRoute(name: string | null): void; /** * Clears the active binary route. Equivalent to `setBinRoute(null)`. */ clearBinRoute(): void; /** * Calls all websocket onClose handlers. * They only get executed once on closure. * @param {*} reason reason for closing. */ callWSClose(reason: any): Promise; close(reason: any): void; /** * Sets up the keep alive on this websocket client. * Unlike http, websocket connections * remain open until one party closes * it. To prevent connections from * freezing, we ping on interval. * The client is disconnected if * it doesn't pong us back. */ setupKeepAlive(): void; /** * Catches per-socket errors emitted by the underlying `ws.WebSocket` * (most notably frame-decoding errors such as `WS_ERR_UNEXPECTED_RSV_2_3`) * so a single misbehaving peer can't take down the whole server. * * The `ws` Receiver passes the error through its writable callback, which * causes `ws` to emit `'error'` on the WebSocket instance. Without a * listener attached the EventEmitter rethrows and the Node process exits. * This handler tears down only the offending client: fires the configured * `wsClose` route with status 1002 (protocol error), drops subscriptions, * and force-closes the socket. */ setupErrorHandling(): void; /** * Sets up the action that happens when the websocket is externally closed. */ setupClose(): void; /** * Performs the tokencheck from websocket request if present. * Unlike http connections wich are RESTfull, websockets * can be upgraded once and their permissions will remain. * This means a client can send a token just once. */ tokenCheck(request: any): Promise; /** * Setup the websocket routing thingy. * * The `isBinary` second arg was added in ws 7+; we use it to split frames * into text (always JSON envelope) and binary (sniff + dispatch). */ setupRouting(): void; /** * Dispatches an incoming websocket frame, branching on frame type. * * Text frame → JSON envelope (regardless of negotiated codec: text frames * are unambiguous UTF-8 and therefore always JSON-parseable control * messages). * * Binary frame → if a binRoute is set, raw dispatch; otherwise ask the * codec to sniff & decode — if it looks like an envelope with a `.path` * string, dispatch it; otherwise fall back to the default `wsBin` route. * * @param {Buffer|string} message - raw frame payload. * @param {boolean} isBinary - whether the frame was a binary frame. */ routeBeat(message: Buffer | string, isBinary: boolean): Promise; /** * Routes a decoded envelope (from either a text frame or a sniffed binary * frame). * * Frames without a `path` field are dispatched to the `wsNoPath` * lifecycle hook (default NOOP) instead of being silently re-mapped to * '/'. This prevents the situation where `router.get('/')` handlers * (which by RestNio design also match `WS:/`) echo their HTTP body back * to the peer, producing reflective parse-error loops on path-less * error replies. * * @param {*} request */ routeEnvelope(request: any): Promise; /** * Promote this WebSocket client to a peer link. After this call, the * client is trusted to send/receive proxy-protocol frames * (`_proxyenv`, `_proxyclose`, `_proxyr`, `_proxyrchan`, `_proxyrsub`) * and acquires the matching ProxyClient table, pending session table, * and shadow coalescing buffer. * * Use from your inbound peer-registration route after authenticating * the peer: * ```js * router.ws('/peer/register', { ... }, ({pwd}, client) => { * if (pwd !== expected) return [403, 'denied']; * client.linkAsPeer({ shadowOut: ['WT*.*'], shadowIn: ['cmd_broadcast.*'] }); * return { ok: true }; * }); * ``` * * @param {import("../util/peerLink").PeerLinkOptions} [opts] */ linkAsPeer(opts?: import("../util/peerLink").PeerLinkOptions): void; /** * Dispatches a path-less envelope to the optional `wsNoPath` hook. * Errors from handlers are caught and logged; the frame is otherwise * silently dropped if no handler is registered. The full request object * is passed as `params` so handlers can inspect `code`, `error`, etc. * @param {Object} request */ _dispatchNoPath(request: any): Promise; /** * Dispatches an inbound error envelope (`{code, error}` with no path) * to the optional `wsError` hook. The default logs to stderr and * sends nothing back. * @param {Object} request */ _dispatchError(request: any): Promise; /** * Run every handler registered under `name` with `params` as the * payload. Lifecycle hooks (wsNoPath, wsError, ...) are deliberately * fired through this method instead of {@link Client#executeRoute} * because executeRoute writes a handler's return value back to the * client as a reply frame — which on an error-envelope hook would * restart the reflective echo storm the hook exists to prevent. We * call the handler function directly and discard its return value. * * Handler exceptions are caught and (optionally) logged so a buggy * lifecycle handler also can't bounce back through `client.err()`. * @param {string} name * @param {Object} params */ _dispatchLifecycle(name: string, params: any): Promise; /** * Handles a binary frame per the routing rules described on the class doc. * @param {Buffer} data */ handleBinaryFrame(data: Buffer): Promise; /** * Dispatches a raw binary payload to a named `wsBin-` route or to * the default `wsBin` route when `name` is null. * @param {string|null} name * @param {Buffer} data */ dispatchBinRoute(name: string | null, data: Buffer): Promise; } declare namespace WebsocketClient { export { RestNio, ClientProperties, Codec }; } import Client = require("./Client"); /** * Typedef Imports */ type RestNio = import("../RestNio"); /** * Typedef Imports */ type ClientProperties = import("../util/Options").ClientProperties; /** * Typedef Imports */ type Codec = import("../codec").Codec;