Inspired by this construct, I've decided to replicate it but put my little twist on the architecture - make it "Lambdaless".
Why? Mainly for learning purposes. I've only consumed the WebSockets part of the AWS API Gateway via Lambdas so far.
Here is a birds-eye view of the architecture that this repo deploys.
Please not that this repo uses the standard version of the Step Functions. One might swap to the express version without much trouble.
This repo uses AWS CDK as the IaC tool. To deploy the infrastructure:
- Ensure that you have your AWS credentials set-up.
- Run
npm run bootstrap
if your environment is not bootstrapped by AWS CDK yet. - Run
npm run deploy
.
-
Copy the
webSocketAPIurl
from the deployment outputs. -
Connect to the
webSocketAPIurl
. There are many tools available to you to do that. One might usewebsocat
orPostman
-
Specify the pattern you want to filter the EventBridge events on. This is done by sending a message with a
pattern
property. Thepattern
property corresponds to the (EventBridge event pattern)[https://docs.aws.amazon.com/eventbridge/latest/userguide/eb-event-patterns.html]Here is an example of a catch-all event pattern.
{ "action": "pattern", "pattern": { "version": ["0"] } }
-
Whenever an event is pushed to the EventBridge bus created by this construct the event payload will be matched against the pattern specified in the previous step. If the payload matches the pattern, the event payload will be sent to your WebSocket connection.
-
The
pattern
action type can be sent multiple times. Each time thepattern
action is invoked, the payload specified in the previouspattern
action will be overwritten.
- If you are not sure how the resource is structured and cannot export it (like in the case of APIGW v2, where the API definition cannot be exported), look into the network tab. You will most likely find useful resource information there.
- The data mapping mechanism for various request parameters for the integration is very similar to the one you do while working with APIGW Rest APIs. First, you must enable the parameters you want to map using on the route level when you can map them on the integration level.
Note that the semantics of enabling the parameters are different.
Here, we enable a given parameter by specifying
Required: true | false
on that parameter.
- The data mapping documentation lists various data mapping expressions but the examples show only a small subsection of all possible mappings.
According to the CloudFormation, only the
method.request.querystring | path | header
mapping is available in the WebSocket context.
- Since the APIGW WebSockets does not support the
IntegrationSubtype
CloudFormation property, we need to use the AWS integration type. This integration type works a bit differently than the AWS_PROXY one. Instead of specifying the payload of the service call within theRequestParameters
property, you will need to encode all of them within theRequestTemplate
. Be mindful about theTemplateSelectionExpression
property as it dictates whichRequestTemplate
will be used for a given request.
- When using direct service integrations be mindful of headers that the service call expects.
Sometimes you have to specify the
X-Amz-Target
, sometimes it's the path that dictates the routing.
- The
TemplateSelectionExpression
is an expression that will dictate which of therequestTemplate
is picked upon a request/response. The\\$default
is a catch-all and will evaluate to arequestTemplate
with a$default
key. This whole mechanism is very similar to creating a MOCK type integration via APIGW. It allows you to develop responses based on the integration response.
- I made the
$connect
route work by specifying theIntegration
,IntegrationResponse
, and theRouteResponse
. Keep in mind that theIntegrationResponse
will not show in the AWS console.
- There is no easy way to configure access logs / execution logs for the APIGW v2. You have to drill into L1 resources and monkey-patch properties.
- To invoke a given service operation directly, create a REST APIGW and use direct integration. Then hook the newly created APIGW to the state machine you are working with. Sadly I would not classify this method of creating an integration as very cost efficient.