API Gateway WebSocket: Implementing a Mock Integration

API Gateway WebSocket: Implementing a Mock Integration

Building an API Gateway WebSocket API entirely with mock integrations, returning canned responses with no backend Lambda involved.

Takahiro Iwasa
3 min read

API Gateway’s mock integration can serve canned WebSocket responses without any backend behind it, which is useful for validating routing and response shapes before real business logic exists.

Integrations for WebSocket APIs in API Gateway

Building

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

Deploy the CloudFormation stack with the following command:

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

To get the deployed API Gateway endpoint, use the following command:

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

Example Output:

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

Testing

Install wscat as a WebSocket client:

Terminal window
npm i wscat

Run the following command to connect to the WebSocket endpoint. The $connect route is used for new connections.

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

Send test messages and observe the responses based on the messageId:

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

Cleaning Up

Clean up all the AWS resources provisioned during this example with the following command:

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

Conclusion

Building an API Gateway WebSocket API entirely with mock integrations returned different canned responses based on the incoming messageId, with no backend Lambda deployed. Mock integration works here because the “backend” is just static response templates keyed off messageId, which makes it a good fit for prototyping a WebSocket API’s routing and response shape before any real backend exists — no Lambda function or persistent connection handling needs to be written just to validate that $connect and message routes behave as expected. That said, TemplateSelectionExpression only supports the kind of static, value-based branching shown here; anything requiring actual computation, persistence, or a call to another service means swapping the mock integration for a Lambda or HTTP integration, since VTL templates alone can’t express that.

About the author

Takahiro Iwasa

Takahiro Iwasa

Software Developer

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