Echo Chat Application
Explore how to create a simple echo chat application using AWS API Gateway's WebSocket API. Learn about the key WebSocket event routes—$connect, $disconnect, and $default—and how to integrate them with AWS Lambda to handle real-time messaging in a serverless environment.
We'll cover the following...
WebSocket on AWS
The AWS API Gateway enables simple implementation of Websocket API. When configuring a WebSocket API, we don’t have to worry about the server-side protocol. Instead, we can create a new entity when we’re ready to use it.
A WebSocket API configuration requires integrations for specific events or routes in the incoming request.
On Connect: When a new connection is established.
On Disconnect: When an existing connection is terminated.
Additional custom action (optional): We can specify custom actions in the API.
Default action (optional): Invoked when the action in the incoming message isn’t configured explicitly.
We can provide individual integrations for these routes when configuring a WebSocket API. Let’s look at a small example of how a WebSocket is implemented with the API Gateway.
Chat application
Online chat is a classic use case for WebSockets, where the server pushes chat messages back to the client. WebSocket API is the best way to implement such applications. Let’s see how we can implement this in the code. We can start with a simple echo chat application. This application simply echoes the message back to the same client.
import { ApiGatewayManagementApiClient, PostToConnectionCommand } from "@aws-sdk/client-apigatewaymanagementapi";
export const handler = async (event) => {
if (event.requestContext.routeKey === "$default") {
const apigwManagementApi = new ApiGatewayManagementApiClient({
endpoint: `https://${event.requestContext.apiId}.execute-api.us-east-1.amazonaws.com/v1`,
});
await apigwManagementApi.send(
new PostToConnectionCommand({
ConnectionId: event.requestContext.connectionId,
Data: event.body,
})
);
}
return { statusCode: 200, body: event.body || "{}" };
};Click "Run" to deploy and test the API in your AWS account. First, the script installs the WebSocket API along with its dependencies. It then installs the wscat utility, which we use to check the WebSockets. Finally, it prompts us to type something. Anything we type here is pushed to the cloud over the WebSocket connection. The Echo API then sends it back in a separate message. Let’s explore this code in detail.
A WebSocket API has three primary routes, namely $connect, $disconnect and $default. We can have more, but AWS defines these three. As should be clear, $connect is invoked when the API Gateway establishes a new connection. A WebSocket disconnect triggers the $disconnect route. Finally, the $default is called when the request doesn’t match any other defined routes. We can specify the usual API Gateway integration for each route to invoke the appropriate service on the API call.
The value of this routeKey is available in the Lambda function. It can implement the business logic based on the value of this routeKey.
In line 52,
template.ymlcreates a new WebSocket API. It defines the protocol type asWEBSOCKET.In lines 58 and 65,
template.ymldefines the$connectroute and its integration with the WebSocketEcho Lambda function.In lines 77 and 84,
template.ymldefines the$disconnectroute with its integration to the WebSocketEcho Lambda function.In lines 96 and 103,
template.ymldefines the$defaultroute along with its integration with the WebSocketEcho Lambda function.In line 4,
index.mjschecks the route that has triggered the Lambda function. In our case, we have all three routes pointing to the same Lambda. We want to echo the input event body for the$defaultroute.In line 5,
index.mjsinstantiates the API Gateway handler of the JavaScript SDK.In line 9,
index.mjsinvokes the API to reply to the client using the WebSocket connection. The Connection ID of the calling client is available in the event object itself.
Web console
Let’s check out how this looks on the API Gateway console. Open the EducativeWebSocket API. Notice the three integration routes, $connect, $disconnect, and $default, there. Click each of them and see their integration with the Lambda function. Unlike the REST API, we don’t have a response integration in the WebSockets. We can add a response integration if we like, but WebSocket API doesn’t require one.