WebSockets APIの使用
WebSockets APIを使用して、Cloudflare Workersとリアルタイムで通信します。
WebSocketsを使用すると、Cloudflare Workersのサーバーレス関数とリアルタイムで通信できます。このガイドでは、Cloudflare WorkersにおけるWebSocketsの基本を学びます。これは、Workers関数内でWebSocketサーバーを作成する視点と、クライアントとしてそれらのWebSocketサーバーに接続して作業する視点の両方を含みます。
WebSocketsは、クライアントとオリジンサーバーの間で維持されるオープンな接続です。WebSocket接続内では、クライアントとオリジンがデータを行き来させることができ、セッションを再確立する必要がありません。これにより、WebSocket接続内でのデータ交換が迅速になります。WebSocketsは、ライブチャットやゲームなどのリアルタイムアプリケーションでよく使用されます。
Cloudflare WorkersのWebSocketサーバーを使用すると、クライアントからリアルタイムでメッセージを受信できます。このガイドでは、WorkersでWebSocketサーバーを設定する方法を示します。
クライアントは、WebSocketの新しいインスタンスを作成し、Workers関数のURLを渡すことで、ブラウザでWebSocketリクエストを行うことができます:
// クライアント側のJavaScriptで、WebSocketsを使用してWorkers関数に接続します:const websocket = new WebSocket('wss://example-websocket.signalnerve.workers.dev');受信したWebSocketリクエストがWorkers関数に到達すると、それにはUpgradeヘッダーが含まれ、文字列値websocketに設定されます。このヘッダーを確認してからWebSocketをインスタンス化する必要があります:
async function handleRequest(request) { const upgradeHeader = request.headers.get('Upgrade'); if (!upgradeHeader || upgradeHeader !== 'websocket') { return new Response('Expected Upgrade: websocket', { status: 426 }); }}Upgradeヘッダーを適切に確認した後、サーバーとクライアントのWebSocketを含む新しいWebSocketPairのインスタンスを作成できます。これらのWebSocketの1つはWorkers関数によって処理され、もう1つは101ステータスコード ↗を持つResponseの一部として返され、リクエストがプロトコルを切り替えていることを示します:
async function handleRequest(request) { const upgradeHeader = request.headers.get('Upgrade'); if (!upgradeHeader || upgradeHeader !== 'websocket') { return new Response('Expected Upgrade: websocket', { status: 426 }); }
const webSocketPair = new WebSocketPair(); const client = webSocketPair[0], server = webSocketPair[1];
return new Response(null, { status: 101, webSocket: client, });}WebSocketPairコンストラクタは、0と1のキーを持つオブジェクトを返し、それぞれがWebSocketインスタンスを値として保持します。このペアから2つのWebSocketを取得するために、Object.values ↗とES6の分割代入 ↗を使用することが一般的です。以下の例に示すように。
Worker内のclient WebSocketとの通信を開始するには、server WebSocketでacceptを呼び出します。これにより、WorkersランタイムはWebSocketデータをリッスンし、client WebSocketとの接続を維持する必要があることを示します:
async function handleRequest(request) { const upgradeHeader = request.headers.get('Upgrade'); if (!upgradeHeader || upgradeHeader !== 'websocket') { return new Response('Expected Upgrade: websocket', { status: 426 }); }
const webSocketPair = new WebSocketPair(); const [client, server] = Object.values(webSocketPair);
server.accept();
return new Response(null, { status: 101, webSocket: client, });}WebSocketsは、addEventListenerを使用して接続できる多くのイベントを発生させます。以下の例は、messageイベントにフックし、そのデータをconsole.logで出力します:
async function handleRequest(request) { const upgradeHeader = request.headers.get('Upgrade'); if (!upgradeHeader || upgradeHeader !== 'websocket') { return new Response('Expected Upgrade: websocket', { status: 426 }); }
const webSocketPair = new WebSocketPair(); const [client, server] = Object.values(webSocketPair);
server.accept(); server.addEventListener('message', event => { console.log(event.data); });
return new Response(null, { status: 101, webSocket: client, });}Workers関数と通信するWebSocketクライアントを書くことは、2段階のプロセスです。まず、WebSocketインスタンスを作成し、次にそれにイベントリスナーを追加します:
const websocket = new WebSocket('wss://websocket-example.signalnerve.workers.dev');websocket.addEventListener('message', event => { console.log('サーバーからメッセージを受信しました'); console.log(event.data);});WebSocketクライアントは、send関数を使用してサーバーにメッセージを送信できます:
websocket.send('MESSAGE');WebSocketのやり取りが完了したら、クライアントはcloseを使用して接続を閉じることができます:
websocket.close();これを実践での例として、websocket-template ↗を参照してWebSocketsを始めてください。
Cloudflare Workersはnew WebSocket(url)コンストラクタをサポートしています。Workerは、上記で説明したクライアント実装と同様に、リモートサーバーにWebSocket接続を確立できます。
さらに、Cloudflareは、Upgradeヘッダーが設定されたURLに対してフェッチリクエストを行うことでWebSocket接続を確立することをサポートしています。
async function websocket(url) { // `Upgrade: websocket`ヘッダーを含むフェッチリクエストを行います。 // Workersランタイムは、Sec-WebSocket-Keyヘッダーなど、WebSocketプロトコルの他の要件を自動的に処理します。 let resp = await fetch(url, { headers: { Upgrade: 'websocket', }, });
// WebSocketハンドシェイクが正常に完了した場合、レスポンスには`webSocket`プロパティがあります。 let ws = resp.webSocket; if (!ws) { throw new Error("サーバーがWebSocketを受け入れませんでした"); }
// accept()を呼び出して、ここでJavaScriptでソケットを処理することを示します。 // クライアントに返すのではなく。 ws.accept();
// これで、以前のようにメッセージを送受信できます。 ws.send('hello'); ws.addEventListener('message', msg => { console.log(msg.data); });}Cloudflare WorkersはWebSocket圧縮をサポートしています。詳細については、WebSocket圧縮を参照してください。