method

WebSocketHandler.message

message: string | Buffer<ArrayBuffer>
): void | Promise<void>;

Called when the server receives a message.

If the message is not a string, its type is based on the value of binaryType.

  • if nodebuffer, then the message is a Buffer.
  • if arraybuffer, then the message is an ArrayBuffer.
  • if uint8array, then the message is a Uint8Array.
  • if blob, then the message is a Blob.

The declared type of message is the one of the default binaryType.

@param ws

The websocket that sent the message

@param message

The message received

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 as Buffer objects. (default)
    • if arraybuffer, binary data is returned as ArrayBuffer objects.
    • if uint8array, binary data is returned as Uint8Array objects.
    • if blob, binary data is returned as Blob objects.

    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
        },
      },
      // ...
    });
  • 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 isPaused: boolean

    Whether the socket is paused. Always false on a closed socket.

  • readonly readyState: WebSocketReadyState

    The ready state of the client.

    • if 1, the client is connected.
    • if 3, the client is closed, or close() or terminate() was called.

    A ServerWebSocket is never 0 (connecting) or 2 (closing).

    console.log(socket.readyState); // 1
  • 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:

    • 1000 means "normal closure" (default)
    • 1009 means a message was too big and was rejected
    • 1011 means the server encountered an error
    • 1012 means the server is restarting
    • 1013 means the server is too busy or the client is rate-limited
    • 3000 through 3999 are reserved for libraries and frameworks
    • 4000 through 4999 are reserved for applications

    0, 1005 and 1006 send a Close frame with no code, so you can forward the code from a close handler unchanged.

    To close the connection abruptly, use terminate().

    @param code

    The close code to send

    @param reason

    The close reason to send. Truncated to 123 bytes of UTF-8, at a character boundary.

  • cork<R = unknown>(
    callback: (ws: ServerWebSocket<T>) => R
    ): R;

    Batches send() and publish() operations, which makes it faster to send data.

    The message, open, and drain callbacks are automatically corked, so you only need to call this if you are sending messages outside of those callbacks or in async functions.

    @param callback

    The callback to run. It runs even if the socket is closed.

    @returns

    The 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() or publish() that haven't been written to the socket yet.

  • topic: string
    ): boolean;

    Returns whether the client is subscribed to the topic.

    @param topic

    The topic name.

    ws.subscribe("chat");
    console.log(ws.isSubscribed("chat")); // true
  • pause(): void;

    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());
      }
    }
  • data?: string | Blob | BufferSource
    ): number;

    Sends a ping.

    @param data

    The data to send

  • data?: string | Blob | BufferSource
    ): number;

    Sends a pong.

    @param data

    The data to send

  • topic: string,
    data: string | Blob | BufferSource,
    compress?: boolean
    ): number;

    Sends a message to subscribers of the topic.

    @param topic

    The topic name.

    @param data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.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 topic

    The topic name.

    @param data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.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 topic

    The topic name.

    @param data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.publishText("chat", "Hello!");
    ws.publishText("chat", "Compress this.", true);
  • resume(): void;

    Starts reading from the socket again after pause().

  • data: string | Blob | BufferSource,
    compress?: boolean
    ): number;

    Sends a message to the client.

    @param data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.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 data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.sendBinary(new TextEncoder().encode("Hello!"));
    ws.sendBinary(new Uint8Array([1, 2, 3, 4]), true);
  • data: string,
    compress?: boolean
    ): number;

    Sends a text message to the client.

    @param data

    The data to send.

    @param compress

    Whether to compress the data. Defaults to false. Ignored if the client does not support compression

    ws.sendText("Hello!");
    ws.sendText("Compress this.", true);
  • topic: string
    ): boolean;

    Subscribes a client to the topic.

    @param topic

    The topic name.

    @returns

    true if the client is now subscribed, false if the socket is closed.

    ws.subscribe("chat");
  • terminate(): void;

    Closes the connection abruptly, without sending a Close frame. Messages already queued by send() and publish() are flushed first.

    To close the connection gracefully, use close().

  • topic: string
    ): boolean;

    Unsubscribes a client from the topic.

    @param topic

    The topic name.

    @returns

    true if the client was subscribed and is now unsubscribed, false if the socket is closed or the client was not subscribed to the topic.

    ws.unsubscribe("chat");

class ArrayBuffer

Represents a raw buffer of binary data, which is used to store data for the different typed arrays. ArrayBuffers cannot be read from or written to directly, but can be passed to a typed array or DataView Object to interpret the raw buffer as needed.

  • readonly [Symbol.toStringTag]: string
  • readonly byteLength: number

    Read-only. The length of the ArrayBuffer (in bytes).

  • newByteLength?: number
    ): void;

    Resizes the ArrayBuffer to the specified size (in bytes).

    MDN

    byteLength: number

    Resize an ArrayBuffer in-place.

  • begin: number,
    end?: number

    Returns a section of an ArrayBuffer.

  • newByteLength?: number

    Creates a new ArrayBuffer with the same byte content as this buffer, then detaches this buffer.

    MDN

  • newByteLength?: number

    Creates a new non-resizable ArrayBuffer with the same byte content as this buffer, then detaches this buffer.

    MDN