method
WebSocketHandler.error
Called when one of the other handlers throws. Without it, the error is an uncaught exception.
Not called when an async handler rejects. That's an unhandled rejection.
The value that was thrown
The websocket whose handler threw
Referenced types
interface ServerWebSocket<T = undefined>
A fast WebSocket designed for servers.
Features:
- Message compression - Messages can be compressed
- Backpressure -
send()reports when the client is not ready to receive data. - Dropped messages -
send()reports when the client cannot receive data. - Topics - Messages can be ServerWebSocket.published to a specific topic and the client can ServerWebSocket.subscribe to topics
This differs slightly from the browser WebSocket, which Bun supports for clients.
Powered by uWebSockets.
Bun.serve({
websocket: {
open(ws) {
console.log("Connected", ws.remoteAddress);
},
message(ws, data) {
console.log("Received", data);
ws.send(data);
},
close(ws, code, reason) {
console.log("Disconnected", code, reason);
},
}
});- binaryType?: 'arraybuffer' | 'blob' | 'uint8array' | 'nodebuffer'
Sets how binary data is returned in events.
- if
nodebuffer, binary data is returned asBufferobjects. (default) - if
arraybuffer, binary data is returned asArrayBufferobjects. - if
uint8array, binary data is returned asUint8Arrayobjects. - if
blob, binary data is returned asBlobobjects.
This applies to binary messages and to the payloads of pings and pongs.
Bun.serve({ websocket: { open(ws) { ws.binaryType = "uint8array"; }, message(ws, message) { console.log(message instanceof Uint8Array); // true, for a binary message }, }, // ... }); - if
- data: T
Custom data you can assign to a client. It can be read and written at any time.
import { serve } from "bun"; serve({ fetch(request, server) { const data = { accessToken: request.headers.get("Authorization"), }; if (server.upgrade(request, { data })) { return; } return new Response(); }, websocket: { data: {} as {accessToken: string | null}, message(ws) { console.log(ws.data.accessToken); } } }); - readonly readyState: WebSocketReadyState
The ready state of the client.
- if
1, the client is connected. - if
3, the client is closed, orclose()orterminate()was called.
A
ServerWebSocketis never0(connecting) or2(closing).console.log(socket.readyState); // 1 - if
- readonly remoteAddress: string
The IP address of the client.
console.log(socket.remoteAddress); // "127.0.0.1" - readonly subscriptions: string[]
Returns an array of all topics the client is currently subscribed to.
ws.subscribe("chat"); ws.subscribe("notifications"); console.log(ws.subscriptions); // ["chat", "notifications"] - code?: number,reason?: string): void;
Closes the connection.
Close codes:
1000means "normal closure" (default)1009means a message was too big and was rejected1011means the server encountered an error1012means the server is restarting1013means the server is too busy or the client is rate-limited3000through3999are reserved for libraries and frameworks4000through4999are reserved for applications
0,1005and1006send a Close frame with no code, so you can forward the code from aclosehandler unchanged.To close the connection abruptly, use
terminate().@param codeThe close code to send
@param reasonThe close reason to send. Truncated to 123 bytes of UTF-8, at a character boundary.
- ): R;
Batches
send()andpublish()operations, which makes it faster to send data.The
message,open, anddraincallbacks are automatically corked, so you only need to call this if you are sending messages outside of those callbacks or in async functions.@param callbackThe callback to run. It runs even if the socket is closed.
@returnsThe return value of
callback.ws.cork((ctx) => { ctx.send("These messages"); ctx.sendText("are sent"); ctx.sendBinary(new TextEncoder().encode("together!")); }); The number of bytes queued by
send()orpublish()that haven't been written to the socket yet.- @param topic
The topic name.
ws.subscribe("chat"); console.log(ws.isSubscribed("chat")); // true Stops reading from the socket, so the client sees TCP backpressure. The idle timeout is suspended until
resume(). Sending still works.Messages already read from the socket are still delivered.
message(ws, message) { if (!file.write(message)) { ws.pause(); file.once("drain", () => ws.resume()); } }- @param data
The data to send
- @param data
The data to send
- topic: string,compress?: boolean): number;
Sends a message to subscribers of the topic.
@param topicThe topic name.
@param dataThe data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.publish("chat", "Hello!"); ws.publish("chat", "Compress this.", true); ws.publish("chat", new Uint8Array([1, 2, 3, 4])); - topic: string,compress?: boolean): number;
Sends a binary message to subscribers of the topic.
@param topicThe topic name.
@param dataThe data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.publishBinary("chat", new TextEncoder().encode("Hello!")); ws.publishBinary("chat", new Uint8Array([1, 2, 3, 4]), true); - topic: string,data: string,compress?: boolean): number;
Sends a text message to subscribers of the topic.
@param topicThe topic name.
@param dataThe data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.publishText("chat", "Hello!"); ws.publishText("chat", "Compress this.", true); Starts reading from the socket again after
pause().- @param data
The data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.send("Hello!"); ws.send("Compress this.", true); ws.send(new Uint8Array([1, 2, 3, 4])); - compress?: boolean): number;
Sends a binary message to the client.
@param dataThe data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.sendBinary(new TextEncoder().encode("Hello!")); ws.sendBinary(new Uint8Array([1, 2, 3, 4]), true); - @param data
The data to send.
@param compressWhether to compress the data. Defaults to
false. Ignored if the client does not support compressionws.sendText("Hello!"); ws.sendText("Compress this.", true); - @param topic
The topic name.
@returnstrueif the client is now subscribed,falseif the socket is closed.ws.subscribe("chat"); Closes the connection abruptly, without sending a Close frame. Messages already queued by
send()andpublish()are flushed first.To close the connection gracefully, use
close().- @param topic
The topic name.
@returnstrueif the client was subscribed and is now unsubscribed,falseif the socket is closed or the client was not subscribed to the topic.ws.unsubscribe("chat");