AWS Deep Dive

Amazon API Gateway

Continued notes about the Amazon API Gateway.

Working With WebSocket APIs

Create a WebSocket API in API Gateway

WebSocket APIs require the use of TLS 1.2 (API Gateway doesn’t seem to support TLS 1.3).

WebSocket APIs cannot be converted into REST APIs, nor can REST APIs be turned into WebSocket APIs. (This makes sense.)

Working With Routes for WebSocket APIs in API Gateway

Route selection expressions are based around the form $request.body.<JSON_PATH_TO_PROPERTY>. Objects can be matched by the JSONPath, but the results will be stringified before evaluation. Multiple selection expressions can be combined into the final expression; static values can be included to make it easier to read/parse the evaluated route key’s value.

Note that the $ is not included in a custom route key name when setting up a route; only the built-in $default, $connect, and $disconnect route names can lead with this character.

The $connect route supports IAM (AWS_IAM) and Lambda Authorizers (CUSTOM) for authorization. There’s also a NONE option. API Gateway can also check for the presence of a valid API key when the $connect route is called.

Only the $default route can be used for responses, which is somewhat annoying as all of the (user-facing) machinery seems to exist to support route responses on custom route selections.

The $connect route allows a Lambda authorizer to reject connections for unsupported subprotocols (specified by the Sec-WebSocket-Protocol header). It’s not clear to me what this gets you, but I assume this is important functionality for people who work with WebSockets.

Controlling and Managing Access to a WebSocket API in API Gateway

IAM policies work basically the same for WebSocket APIs as REST APIs, except that (1) WebSockets support a ManageConnections action that controls access to the @connections API, and (2) non-@connections routes use a different ARN format (the @connections API is represented as arn:aws:execute-api:*:*:*/*/POST/@connections).

(It’s not 100% clear what the @connections API is. It seems to be different than the $connect route, and has something to do with response routes.)

The biggest difference when using a Lambda authorizer between WebSockets and REST APIs is that the event.methodArn is different (arn:aws:execute-api:*:*:*/*/$connect). Path variables (event.pathParameters) aren’t available and context variables (event.requestContext) are different too, but these pretty obviously need to be the case.

Setting up WebSocket API Integrations in API Gateway

The “Lambda Function” integration type is only for existing Lambda functions that don’t/won’t require special resource permissions. All other Lambda function requests (including the automatic creation of new Lambda functions) are handled with the “AWS Service” integration type. (This strikes me as a weird and really specific distinction.)

Regardless of the integration type, WebSockets APIs support a template selection process that parallels the route selection process - a template selection expression (like a route selection expression) will be used to determine a template key. The template corresponding to that key will then be used to determine which request mapping template is used to pre-process the incoming request before handing it off to the backend.

Integration responses can be pre-processed in a similar way as requests, using a “response key” that maps to a particular response template. Responses that don’t match this key are handled by the $default response key (and corresponding template). The big difference here is that the response key is a regular expression matching the returned backend HTTP status code, rather than a JSONPath.

Note that there is no response setup for proxy integrations; API Gateway simply passes these backend responses to the client unaltered (assuming that a response route has been configured).

Request Validation for WebSocket APIs in API Gateway

Incoming WebSocket requests can be validated by API Gateway before being passed to backend integrations, just like with REST APIs. As you might expect by this point, different JSON schema request models can be used for validation, each keyed off of a model selection expression (which works just like a route selection expression). A catch-all $default model can also be defined.

Models can be chosen at the same time (and by the same expression) as routes, which seems like how you’d normally want to handle things.