コンテンツにスキップ

WebSocketサーバーを構築する

Durable ObjectsとWorkersを使用してWebSocketサーバーを構築します。

この例では、Durable ObjectsとWorkersを使用してWebSocketサーバーを構築する方法を示します。この例では、新しいWebSocket接続を作成するためのエンドポイントを公開します。このWebSocket接続は、メッセージをエコーし、現在確立されているWebSocket接続の総数を含みます。詳細については、WebSocketsでDurable Objectsを使用するを参照してください。

import { DurableObject } from "cloudflare:workers";
// Worker
export default {
async fetch(request, env, ctx) {
if (request.url.endsWith("/websocket")) {
// WebSocket Upgradeリクエストを受け取ることを期待します。
// もしあれば、リクエストを受け入れ、WebSocketレスポンスを返します。
const upgradeHeader = request.headers.get('Upgrade');
if (!upgradeHeader || upgradeHeader !== 'websocket') {
return new Response('Durable Object expected Upgrade: websocket', { status: 426 });
}
// この例では、名前「foo」がハードコーディングされているため、
// 同じDurable Objectインスタンスを参照します。
let id = env.WEBSOCKET_SERVER.idFromName("foo");
let stub = env.WEBSOCKET_SERVER.get(id);
return stub.fetch(request);
}
return new Response(null, {
status: 400,
statusText: 'Bad Request',
headers: {
'Content-Type': 'text/plain',
},
});
}
};
// Durable Object
export class WebSocketServer extends DurableObject {
currentlyConnectedWebSockets;
constructor(ctx, env) {
// このコンストラクタが実行されるたびにリセットされます。
// 通常のWebSocketはDurable Objectのリセットを生き延びません。
//
// 休眠APIを介して受け入れられたWebSocketは
// 特定のタイプの追放を生き延びることができますが、
// ここではそれについては説明しません。
super(ctx, env);
this.currentlyConnectedWebSockets = 0;
}
async fetch(request) {
// WebSocket接続の両端を作成します。
const webSocketPair = new WebSocketPair();
const [client, server] = Object.values(webSocketPair);
// `accept()`を呼び出すことで、このWebSocketが
// Durable Object内でリクエストを終了することを示します。
// これは接続を「受け入れる」効果があり、
// WebSocketがメッセージを送受信できるようにします。
server.accept();
this.currentlyConnectedWebSockets += 1;
// クライアントからメッセージを受信すると、サーバーは同じメッセージで応答し、
// "[Durable Object]: "プレフィックス付きで接続の総数を返します。
server.addEventListener('message', (event) => {
server.send(`[Durable Object] currentlyConnectedWebSockets: ${this.currentlyConnectedWebSockets}`);
});
// クライアントが接続を閉じると、ランタイムも接続を閉じます。
server.addEventListener('close', (cls) => {
this.currentlyConnectedWebSockets -= 1;
server.close(cls.code, "Durable Object is closing WebSocket");
});
return new Response(null, {
status: 101,
webSocket: client,
});
}
}

最後に、wrangler.tomlファイルを構成して、以前に選択した名前空間とクラス名に基づいてDurable Objectのバインディング移行を含めます。

name = "websocket-server"
[[durable_objects.bindings]]
name = "WEBSOCKET_SERVER"
class_name = "WebSocketServer"
[[migrations]]
tag = "v1"
new_classes = ["WebSocketServer"]

関連リソース