API Gateway の WebSocket API の作り方 ── Lambda と DynamoDB でコメントをリアルタイムに届ける
記事の「実践」を 1 項目ずつ進めるためのページです。AWS マネジメントコンソールで操作したら、右の一覧にチェックを入れてください。チェックはこのブラウザに保存されます。
前提条件
- リージョン:
ap-northeast-1(東京) - 以下のリソースが作成済みであること
まだ用意していない場合は、「作り方の参考」の記事の手順で作れます。リソース名は、この記事の名前に読み替えてください。
| リソース種別 | リソース名 | 内容 | 作り方の参考 |
|---|---|---|---|
| DynamoDB テーブル | dva-ws-connections | パーティションキー connectionId(文字列) | Amazon DynamoDB でテーブルを作り Lambda から読み書きする |
| Lambda 関数 | dva-ws-handler | Python 3.13。event["requestContext"]["routeKey"] でルートを見分け、$connect で接続 ID を保存、$disconnect で削除、sendcomment で全接続に PostToConnection で送る | AWS Lambda で関数を作成しイベント駆動で実行する |
| IAM ロール | dva-ws-handler-role | 上の関数の実行ロール。ログ出力、テーブルの PutItem・DeleteItem・Scan、execute-api:ManageConnections を許可 | ― |
作成するリソース一覧
| リソース種別 | リソース名 | 用途 |
|---|---|---|
| WebSocket API | dva-comments-ws | コメントを双方向でやり取りする API |
| ステージ | production | API の公開先 |
手順 1: WebSocket API を作る
AWS マネジメントコンソールにログインし、リージョンが ap-northeast-1(東京)であることを確認します。上部の検索バーに API Gateway と入力し、「API Gateway」を選択します。
「API を作成」をクリックし、「WebSocket API」の「構築」をクリックします。以下を設定して「次へ」をクリックします。
- API 名:
dva-comments-ws - ルート選択式:
request.body.action(入力欄の前に$が付いて$request.body.actionになります) - その他の項目(IP アドレスのタイプなど)はデフォルトのままにします
「ルートを追加」の画面で、「$connect ルートを追加」と「$disconnect ルートを追加」をクリックします(ボタンがルートキーの欄に変わります)。続けて「カスタムルートを追加」をクリックし、ルートキーに sendcomment と入力して「次へ」をクリックします。
「統合をアタッチ」の画面で、3 つのルートすべてについて、統合タイプ「Lambda」を選び、Lambda 関数に dva-ws-handler を指定して(一覧から選ぶか、関数の ARN を入力します)「次へ」をクリックします。
「ステージを追加」の画面で、ステージ名が production(デフォルト)になっていることを確認して「次へ」をクリックします。確認画面で「Create and deploy」をクリックすると、API が作成されて production ステージにデプロイされます。
手順 2: 接続先の URL を確かめる
作成した dva-comments-ws の左側ナビゲーションで「ステージ」を選択し、production を選択します。「WebSocket URL」(wss:// で始まる URL)と「@connections URL」(https:// で始まり /@connections で終わる URL)が表示されます。WebSocket URL をコピーしておきます。
コンソールで Lambda 統合を作ると、API Gateway から関数を呼び出す許可が関数のリソースベースポリシーに自動で追加されます。Lambda コンソールで dva-ws-handler の「設定」タブ →「アクセス許可」を開くと、「リソースベースのポリシーステートメント」に、プリンシパルが apigateway.amazonaws.com のステートメントが追加されていることを確認できます。
手順 3: 2 つのクライアントで接続する
コンソール上部の CloudShell のアイコンをクリックして、CloudShell を開きます。次のコマンドで、1 つ目のクライアントとして接続します(初回は wscat のダウンロードの確認が表示されるので y を入力します)。
npx wscat -c wss://<api-id>.execute-api.ap-northeast-1.amazonaws.com/production
Connected (press CTRL+C to quit) と表示されれば接続できています。CloudShell の右上の「アクション」→「列に分割」で画面を左右に分け、右側でも同じコマンドを実行してもう 1 つ接続します。
DynamoDB のコンソールの左側ナビゲーションで「項目を探索」を選択し、テーブルの一覧から dva-ws-connections を選ぶと、スキャンの結果に接続 ID が 2 件保存されていることを確認できます。
手順 4: コメントを送って両方に届くことを確かめる
左側(1 つ目)のクライアントで、次のメッセージを入力して Enter キーを押します。
{"action": "sendcomment", "comment": "猿山にバナナが届きました"}
メッセージの action が sendcomment なので、sendcomment ルートの Lambda が呼ばれ、保存されている接続 ID の全員にコメントを送ります。左右の両方に、< {"from": "xxxx", "comment": "猿山にバナナが届きました"} のように受信したコメントが表示されます(from は送り主の接続 ID の末尾 4 文字です)。右側のクライアントは何も問い合わせていないのに、サーバーから届いています。
試しに {"action": "unknown"} を送ると、どのルートにも当たらないので、{"message": "Forbidden", …} というエラーのメッセージが返ります(今回は $default ルートを作っていないため)。
左側のクライアントで Ctrl + C を押して切断すると、$disconnect ルートの Lambda が呼ばれ、DynamoDB の接続 ID が 1 件に減ります。