Bun

指南WebSocket

使用 Bun 在 WebSocket 上設定每個 socket 的上下文資料

在建立 WebSocket 伺服器時,通常需要儲存一些識別資訊或與每個已連線用戶端相關的內容。

使用 Bun.serve(),在連線最初升級時,透過在 server.upgrade() 呼叫中傳遞 data 參數來設定這個「上下文資料」。

Bun.serve<{ socketId: number }>({
  fetch(req, server) {
    const success = server.upgrade(req, {
      data: {
        socketId: Math.random(),
      },
    });
    if (success) return undefined;

    // handle HTTP request normally
    // ...
  },
  websocket: {
    // define websocket handlers
    async message(ws, message) {
      // the contextual dta is available as the `data` property
      // on the WebSocket instance
      console.log(`Received ${message} from ${ws.data.socketId}}`);
    },
  },
});

從傳入的請求中讀取 cookie/標頭以識別連線的用戶端是很常見的作法。

type WebSocketData = {
  createdAt: number;
  token: string;
  userId: string;
};

// TypeScript: specify the type of `data`
Bun.serve<WebSocketData>({
  async fetch(req, server) {
    // use a library to parse cookies
    const cookies = parseCookies(req.headers.get("Cookie"));
    const token = cookies["X-Token"];
    const user = await getUserFromToken(token);

    const upgraded = server.upgrade(req, {
      data: {
        createdAt: Date.now(),
        token: cookies["X-Token"],
        userId: user.id,
      },
    });

    if (upgraded) return undefined;
  },
  websocket: {
    async message(ws, message) {
      // save the message to a database
      await saveMessageToDatabase({
        message: String(message),
        userId: ws.data.userId,
      });
    },
  },
});