Getting Started with the AWS Websockets API
An introduction to the power of an AWS Lambda powered real-time AWS WebSocket API
On December 18, 2018, Amazon Web Services officially released support for WebSocket APIs in API Gateway. This is huge because we can now finally leverage the serverless architecture of AWS Lambda for WebSocket connections! There are 3 big pieces to this new service: routes, messaging connected clients, and authorizers. I’ve tried to provide many working examples that I use in my own projects to give you an idea of how you could utilize this service. Let’s jump in!
Routes are where you can attach AWS Lambda functions to your API. By default, AWS provides three routes that you will likely want to implement — $connect, $disconnect, and $default. You can also implement custom routes that follow a given route selection expression. This expression just tells AWS where to look for the route name. For example, it could be something like:
This route is used when a client connects to your API. You’ll (probably) want to attach an authorizer to this function so that you can store the connection id and any given authorized client information. Here’s what this could look like
This route is used when a client disconnects from your API. From my own experience, this is extremely unreliable as you will often need to manually detect if client connections are stale. I give an example of how you can do this under Messaging Clients in this post.
This route is used when the pattern does not match any of your custom patterns and acts as a catch-all.
Sending messages to a connected client is actually very simple. You’ll just need to make sure that you store the client’s connection id somewhere (a database or cache), and you could use something like the code below to achieve this.
You’ll want to watch out for 2 specific error codes, 410 and 504.
- 410 — indicates that the client is no longer available.
- 504 — the request timed out (usually after 30 seconds), and from my experience, this usually indicates that we are unable to communicate with the client.
Unfortunately, unlike the traditional REST API in API Gateway, you cannot attach an AWS Cognito Pool to automatically handle this for you.
At the time of writing, the only way to authorize WebSocket connections is by providing a custom authorizer lambda function. You will be prompted with this form when attaching an authorizer to your API.
This custom authorizer should dictate whether or not a request should be authenticated based on the given identity source. Essentially, you’ll just need to choose the method(s) by which you will be passing a means of authentication (e.g. an AWS Cognito ID token, a JWT access token, etc.) in every request to your WebSocket API.
You may only use ONE authorizer function for your entire API and attach it to your $connect route. The same authorizer function will then be used in all other requests to other routes as well.
An example authorizer function that uses AWS Cognito could look like:
I’m hoping that one-day AWS will add the automatic support for authorizing using AWS Cognito because this is a lot of ugly code that could be eliminated if we had the same support as the REST APIs.
Thanks for reading and good luck with your projects! Leave a comment or message me if you have any questions.