API Gateway WebSocket:モック統合の実装

API Gateway WebSocket:モック統合の実装

バックエンドのLambdaを一切使わず、モック統合のみでAPI Gateway WebSocket APIを構築し、あらかじめ用意されたレスポンスを返します。

Takahiro Iwasa
5 min read

API Gatewayのモック統合を使えば、背後にバックエンドを一切置かずに、あらかじめ用意されたWebSocketレスポンスを返すことができます。これは、実際のビジネスロジックが完成する前にルーティングやレスポンスの形を検証するのに便利です。

Integrations for WebSocket APIs in API Gateway

構築

template.yaml
AWSTemplateFormatVersion: 2010-09-09
Description: API Gateway WebSocket with Mock Integration
Resources:
ApiGatewayV2Api:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: api-gateway-websocket-with-mock-integration
ProtocolType: WEBSOCKET
RouteSelectionExpression: $request.body.action
ApiGatewayV2Stage:
Type: AWS::ApiGatewayV2::Stage
Properties:
StageName: production
ApiId: !Ref ApiGatewayV2Api
AutoDeploy: true
ApiGatewayV2RouteOnConnect:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref ApiGatewayV2Api
RouteKey: $connect
RouteResponseSelectionExpression: $default
Target: !Sub integrations/${ApiGatewayV2IntegrationOnConnect}
ApiGatewayV2RouteOnMessage:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref ApiGatewayV2Api
RouteKey: message
RouteResponseSelectionExpression: $default
Target: !Sub integrations/${ApiGatewayV2IntegrationOnMessage}
ApiGatewayV2RouteResponseOnConnect:
Type: AWS::ApiGatewayV2::RouteResponse
Properties:
ApiId: !Ref ApiGatewayV2Api
RouteResponseKey: $default
RouteId: !Ref ApiGatewayV2RouteOnConnect
ApiGatewayV2RouteResponseOnMessage:
Type: AWS::ApiGatewayV2::RouteResponse
Properties:
ApiId: !Ref ApiGatewayV2Api
RouteResponseKey: $default
RouteId: !Ref ApiGatewayV2RouteOnMessage
ApiGatewayV2IntegrationOnConnect:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGatewayV2Api
ConnectionType: INTERNET
IntegrationType: MOCK
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
'$default': '{"statusCode": 200}'
TimeoutInMillis: 29000
PayloadFormatVersion: '1.0'
ApiGatewayV2IntegrationOnMessage:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref ApiGatewayV2Api
ConnectionType: INTERNET
IntegrationType: MOCK
PassthroughBehavior: WHEN_NO_MATCH
RequestTemplates:
'$default': '{"statusCode": 200, "messageId": $input.path(''$.messageId'')}'
TimeoutInMillis: 29000
PayloadFormatVersion: '1.0'
ApiGatewayV2IntegrationResponseOnConnect:
Type: AWS::ApiGatewayV2::IntegrationResponse
Properties:
ApiId: !Ref ApiGatewayV2Api
IntegrationId: !Ref ApiGatewayV2IntegrationOnConnect
IntegrationResponseKey: /200/
ApiGatewayV2IntegrationResponseOnMessage:
Type: AWS::ApiGatewayV2::IntegrationResponse
Properties:
ApiId: !Ref ApiGatewayV2Api
IntegrationId: !Ref ApiGatewayV2IntegrationOnMessage
IntegrationResponseKey: /200/
ResponseTemplates:
'1': '{"message": "Hello World"}'
'2': '{"message": "Hi!"}'
TemplateSelectionExpression: ${request.body.messageId}
Outputs:
ApiGatewayV2ApiEndpoint:
Value: !GetAtt ApiGatewayV2Api.ApiEndpoint

次のコマンドでCloudFormationスタックをデプロイします。

Terminal window
aws cloudformation deploy \
--template-file template.yaml \
--stack-name api-gateway-websocket-with-mock-integration

デプロイされたAPI Gatewayのエンドポイントを取得するには、次のコマンドを使用します。

Terminal window
aws cloudformation describe-stacks \
--stack-name api-gateway-websocket-with-mock-integration \
| jq ".Stacks[0].Outputs"

出力例:

[
{
"OutputKey": "ApiGatewayV2ApiEndpoint",
"OutputValue": "wss://<id>.execute-api.<region>.amazonaws.com"
}
]

テスト

WebSocketクライアントとしてwscatをインストールします。

Terminal window
npm i wscat

次のコマンドを実行してWebSocketエンドポイントに接続します。新規接続には$connectルートが使用されます。

Terminal window
wscat -c wss://<id>.execute-api.<region>.amazonaws.com/production/

テストメッセージを送信し、messageIdに応じたレスポンスを確認します。

Terminal window
> {"action": "message", "messageId": 1}
< {"message": "Hello World"}
> {"action": "message", "messageId": 2}
< {"message": "Hi!"}

クリーンアップ

次のコマンドで、この例でプロビジョニングしたすべてのAWSリソースをクリーンアップします。

Terminal window
aws cloudformation delete-stack \
--stack-name api-gateway-websocket-with-mock-integration

まとめ

モック統合だけでAPI Gateway WebSocket APIを構築したところ、バックエンドのLambdaを一切デプロイすることなく、受信したmessageIdに応じて異なるあらかじめ用意されたレスポンスが返ってきました。ここでモック統合が機能するのは、「バックエンド」がmessageIdをキーにした単なる静的なレスポンステンプレートに過ぎないからです。これは、実際のバックエンドが存在する前にWebSocket APIのルーティングとレスポンス形状をプロトタイピングするのに適しています。$connectルートとmessageルートが期待通りに動作するかを検証するためだけに、Lambda関数や永続的な接続処理を書く必要はありません。とはいえ、TemplateSelectionExpressionがサポートするのはここで示したような静的な値ベースの分岐だけです。実際の計算や永続化、他のサービスの呼び出しが必要になる場合は、VTLテンプレートだけではそれを表現できないため、モック統合をLambda統合やHTTP統合に置き換える必要があります。

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

This blog shares technical notes from hands-on projects—architecture, implementation, and AWS service integrations.