Skip to content

WojciechMatuszewski/cdk-lambdaless-apigw-websockets

Repository files navigation

"Lambdaless" AWS API Gateway WebSockets

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.

Architecture

Here is a birds-eye view of the architecture that this repo deploys.

architecture

Please not that this repo uses the standard version of the Step Functions. One might swap to the express version without much trouble.

Deployment

This repo uses AWS CDK as the IaC tool. To deploy the infrastructure:

  1. Ensure that you have your AWS credentials set-up.
  2. Run npm run bootstrap if your environment is not bootstrapped by AWS CDK yet.
  3. Run npm run deploy.

Usage

  1. Copy the webSocketAPIurl from the deployment outputs.

  2. Connect to the webSocketAPIurl. There are many tools available to you to do that. One might use websocat or Postman

  3. Specify the pattern you want to filter the EventBridge events on. This is done by sending a message with a pattern property. The pattern 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"] } }
  1. 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.

  2. The pattern action type can be sent multiple times. Each time the pattern action is invoked, the payload specified in the previous pattern action will be overwritten.

Learnings

  • 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 the RequestParameters property, you will need to encode all of them within the RequestTemplate. Be mindful about the TemplateSelectionExpression property as it dictates which RequestTemplate 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 the requestTemplate is picked upon a request/response. The \\$default is a catch-all and will evaluate to a requestTemplate 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 the Integration, IntegrationResponse, and the RouteResponse. Keep in mind that the IntegrationResponse 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.

About

Abusing StepFunctions so that I do not have to write any Lambda code.

Resources

Stars

Watchers

Forks

Releases

No releases published

Packages

No packages published