WebSocket API
Learn about WebSocket APIs and how we can configure them using AWS API Gateway in AWS.
We'll cover the following
Unlike REST API, which is used for synchronous communication, WebSocket API is used for asynchronous communication. It enables real-time bidirectional communication between client and server. In contrast to the request/response model, where the client sends the request and the server responds, WebSocket API allows the server to send one-way messages to the client.
Bidirectional communication
But why do we need bidirectional communication when we have REST APIs? Consider a real time chat application as one shown in the figure below. Alice wants to send a message to Bob, so it sends a POST request to the server with the message payload. When the request arrives at the server, it does not know how to pass on the message to Bob. That’s when bidirectional communication and WebSocket API come in handy.
WebSocket API handles such scenarios by using the publish-subscriber model. It establishes a persistent connection between the publishers and the subscribers. Clients subscribe to specific channels, and the server can broadcast messages to all connected clients subscribed to those channels. Thus, Alice and Bob connect to the server, and when the request to send a message to Bob arrives, it knows how to send it through.
A significant drop in the connectivity cost and increased available bandwidth has led to an increase in the use of WebSockets API. Many mobile applications maintain constant connections to servers via WebSockets for real-time notifications. Online gaming apps rely on WebSockets to sustain ongoing connections with individual clients. Any scenario involving instant updates, notifications, or persistent connections to the server typically involves the utilization of WebSockets.
In WebSocket, API routes have an associated Route Key, a specific field within the WebSocket message that determines how API Gateway routes the message. When a message arrives at the WebSocket API, API Gateway examines the route key to determine the destination for the message. Different messages may have different route keys, allowing for versatile routing scenarios.
Example: Chat application
Let’s understand this concept with an example from a chat application that broadcasts messages to all the subscribers. By incorporating a route key based on the “action,” we can direct requests to different backend services. When the API receives a request, it examines the JSON payload containing the action
property. The route table then decides the action to take by comparing the action
value against predefined keys, allowing for dynamic routing of messages to different backend functionalities based on the specified actions.
The WebSocket API provides three predefined routes:
$connect
for initiating a connection$disconnect
for handling disconnected clients and servers$default
for directing requests when no matching route is found
What makes WebSocket API stand out among the other APIs is its ability to send back requests to the client. It achieves this functionality through two methods: either sends back the response according to the configured route response or sends a POST
request using the @connections
API. The latter works by storing the connection ID
of the client. Whenever the backend service has to send a request to the client, it initiates the @connection
API and provides it with the connection ID
of the client.
The illustration below shows the infrastructure of the chat application containing a DynamoDB table to store connection IDs and a Lambda function to provide business logic.
In our use case, the DynamoDB table stores the connection IDs of the subscribers.
Whenever a client connects to the API Gateway, the WebSocket API routes the information to the Lambda function, which stores the
connection ID
in the DynamoDB table.Similarly, whenever a client disconnects, the Lambda function integrated at
$disconnect
route deletes the connection ID from the database.The
$default
handles requests that are not routed properly by not performing any task.To broadcast messages to all the clients, we’ve configured a
$message
route that fetches the connection ID of the clients from the DynamoDB table and forwards the message to them all.
Security in WebSocket API
Due to the exposed nature of APIs, it is necessary to ensure the connections are secure. Since WebSocket APIs are stateful, we only need to verify a connection when it is first established. WebSocket APIs require a username and password from the client at the route to authenticate a client. For the subsequent authorization of the client, WebSocket API stores the session details. We can use the Lambda authorizer function to handle the authorization logic.
Get hands-on with 1300+ tech skills courses.