Skip to content

WebSocket サーバーを構築するとき、各接続されたクライアントに関連付けられた識別情報やコンテキストをいくつか保存するのが一般的です。

Bun.serve() では、この「コンテキストデータ」は接続が最初にアップグレードされるときに server.upgrade() 呼び出しで data パラメータを渡すことで設定されます。

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

    // HTTP リクエストを通常通り処理
    // ...
  },
  websocket: {
    // TypeScript: ws.data の型をこのように指定します
    data: {} as { socketId: number },

    // WebSocket ハンドラを定義
    async message(ws, message) {
      // コンテキストデータは WebSocket インスタンスの `data` プロパティとして利用可能です
      console.log(`${ws.data.socketId} から ${message} を受信しました`);
    },
  },
});

接続中のクライアントを識別するために、受信リクエストからクッキーやヘッダーを読み取るのが一般的です。

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

Bun.serve({
  async fetch(req, server) {
    // ライブラリを使用してクッキーを解析
    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: {
    // TypeScript: ws.data の型をこのように指定します
    data: {} as WebSocketData,

    async message(ws, message) {
      // メッセージをデータベースに保存
      await saveMessageToDatabase({
        message: String(message),
        userId: ws.data.userId,
      });
    },
  },
});

Bun by www.bunjs.com.cn 編集