

# Overview of WebSocket APIs in API Gateway
Overview of WebSocket APIs

In API Gateway you can create a WebSocket API as a stateful frontend for an AWS service (such as Lambda or DynamoDB) or for an HTTP endpoint. The WebSocket API invokes your backend based on the content of the messages it receives from client apps.

Unlike a REST API, which receives and responds to requests, a WebSocket API supports two-way communication between client apps and your backend. The backend can send callback messages to connected clients.

In your WebSocket API, incoming JSON messages are directed to backend integrations based on routes that you configure. (Non-JSON messages are directed to a `$default` route that you configure.)

A *route* includes a *route key*, which is the value that is expected once a *route selection expression* is evaluated. The `routeSelectionExpression` is an attribute defined at the API level. It specifies a JSON property that is expected to be present in the message payload. For more information about route selection expressions, see [Route selection expressions](websocket-api-develop-routes.md#apigateway-websocket-api-route-selection-expressions).

For example, if your JSON messages contain an `action` property, and you want to perform different actions based on this property, your route selection expression might be `${request.body.action}`. Your routing table would specify which action to perform by matching the value of the `action` property against the custom route key values that you have defined in the table.

## Use routes for a WebSocket API


There are three predefined routes that can be used: `$connect`, `$disconnect`, and `$default`. In addition, you can create custom routes.
+ API Gateway calls the `$connect` route when a persistent connection between the client and a WebSocket API is being initiated.
+ API Gateway calls the `$disconnect` route when the client or the server disconnects from the API.
+ API Gateway calls a custom route after the route selection expression is evaluated against the message if a matching route is found; the match determines which integration is invoked.
+ API Gateway calls the `$default` route if the route selection expression cannot be evaluated against the message or if no matching route is found.

For more information about the `$connect` and `$disconnect` routes, see [Manage connected users and client apps: `$connect` and `$disconnect` routes](apigateway-websocket-api-route-keys-connect-disconnect.md).

For more information about the `$default` route and custom routes, see [Invoke your backend integration with the `$default` Route and custom routes in API Gateway](apigateway-websocket-api-routes-integrations.md).

## Send data to connected client apps


Backend services can send data to connected client apps. You can send data by doing the following:
+ Use an integration to send a response, which is returned to the client by a route response that you have defined.
+ You can use the `@connections` API to send a POST request. For more information, see [Use `@connections` commands in your backend service](apigateway-how-to-call-websocket-api-connections.md).

## WebSocket API status codes


API Gateway WebSocket APIs use the following status codes for communication from the server to client as described in the [WebSocket Close Code Number Registry](https://www.iana.org/assignments/websocket/websocket.xhtml#close-code-number):

1001  
API Gateway returns this status code when the client is idle for 10 minutes or reaches the maximum 2 hour connection lifetime.

1003  
API Gateway returns this status code when an endpoint receives a binary media type. Binary media types aren't supported for WebSocket APIs.

1005  
API Gateway returns this status code if the client sends a close frame without a closure code.

1006  
API Gateway returns this status code if there is an unexpected closure of the connection, such as the TCP connection closed without a WebSocket close frame.

1008  
API Gateway returns this status code when an endpoint receives too many requests from a particular client.

1009  
API Gateway returns this status code when an endpoint receives a message that is too big for it to process.

1011  
API Gateway returns this status code when there is an internal server error. 

1012  
API Gateway returns this status code if the service restarts.

# Manage connected users and client apps: `$connect` and `$disconnect` routes
Manage connected users and client apps

The following section describes how to use the `$connect` and `$disconnect` routes for your WebSocket API.

**Topics**
+ [

## The `$connect` route
](#apigateway-websocket-api-routes-about-connect)
+ [

## Passing connection information from the `$connect` route
](#apigateway-websocket-api-passing-connectionId-on-connect)
+ [

## The `$disconnect` route
](#apigateway-websocket-api-routes-about-disconnect)

## The `$connect` route


Client apps connect to your WebSocket API by sending a WebSocket upgrade request. If the request succeeds, the `$connect` route is executed while the connection is being established.

Because the WebSocket connection is a stateful connection, you can configure authorization on the `$connect` route only. `AuthN`/`AuthZ` will be performed only at connection time.

Until execution of the integration associated with the `$connect` route is completed, the upgrade request is pending and the actual connection will not be established. If the `$connect` request fails (e.g., due to `AuthN`/`AuthZ` failure or an integration failure), the connection will not be made.

**Note**  
If authorization fails on `$connect`, the connection will not be established, and the client will receive a `401` or `403` response.

Setting up an integration for `$connect` is optional. You should consider setting up a `$connect` integration if:
+ You want to enable clients to specify subprotocols by using the `Sec-WebSocket-Protocol` field. For example code, see [Set up a `$connect` route that requires a WebSocket subprotocol](websocket-connect-route-subprotocol.md).
+ You want to be notified when clients connect.
+ You want to throttle connections or control who connects.
+ You want your backend to send messages back to clients using a callback URL.
+ You want to store each connection ID and other information into a database (for example, Amazon DynamoDB).

## Passing connection information from the `$connect` route


 You can use both proxy and non-proxy integrations to pass information from the `$connect` route to a database or other AWS service. 

### To pass connection information using a proxy integration


You can access the connection information from a Lambda proxy integration in the event. Use another AWS service or AWS Lambda function to post to the connection. 

The following Lambda function shows how to use the `requestContext` object to log the connection ID, domain name, stage name, and query strings. 

------
#### [ Node.js ]

```
 export const handler = async(event, context) => {
    const connectId = event["requestContext"]["connectionId"]
    const domainName = event["requestContext"]["domainName"]
    const stageName = event["requestContext"]["stage"]
    const qs = event['queryStringParameters']
    console.log('Connection ID: ', connectId, 'Domain Name: ', domainName, 'Stage Name: ', stageName, 'Query Strings: ', qs )
    return {"statusCode" : 200}
};
```

------
#### [ Python ]

```
import json
import logging
logger = logging.getLogger()
logger.setLevel("INFO")


def lambda_handler(event, context):
    connectId = event["requestContext"]["connectionId"]
    domainName = event["requestContext"]["domainName"]
    stageName = event["requestContext"]["stage"]
    qs = event['queryStringParameters']
    connectionInfo = {
        'Connection ID': connectId,
        'Domain Name': domainName,
        'Stage Name': stageName,
        'Query Strings': qs}
    logging.info(connectionInfo)
    return {"statusCode": 200}
```

------

### To pass connection information using a non-proxy integration

+ You can access the connection information with a non-proxy integration. Set up the integration request and provide a WebSocket API request template. The following [Velocity Template Language (VTL)](https://velocity.apache.org/engine/devel/vtl-reference.html) mapping template provides an integration request. This request sends the following details to a non-proxy integration: 
  + Connection ID
  + Domain name
  + Stage name
  + Path
  + Headers
  + Query strings

  This request sends the connection ID, domain name, stage name, paths, headers, and query strings to a non-proxy integration.

  ```
  {
      "connectionId": "$context.connectionId",
      "domain": "$context.domainName",
      "stage": "$context.stage",
      "params": "$input.params()"
  }
  ```

  For more information about setting up data transformations, see [Data transformations for WebSocket APIs in API Gateway](websocket-api-data-transformations.md).

  To complete the integration request, set `StatusCode: 200` for the integration response. To learn more about setting up an integration response, see [Set up an integration response using the API Gateway console](apigateway-websocket-api-integration-responses.md#apigateway-websocket-api-integration-response-using-console).

## The `$disconnect` route


The `$disconnect` route is executed after the connection is closed.

The connection can be closed by the server or by the client. As the connection is already closed when it is executed, `$disconnect` is a best-effort event. API Gateway will try its best to deliver the `$disconnect` event to your integration, but it cannot guarantee delivery.

The backend can initiate disconnection by using the `@connections` API. For more information, see [Use `@connections` commands in your backend service](apigateway-how-to-call-websocket-api-connections.md).

# Invoke your backend integration with the `$default` Route and custom routes in API Gateway
Invoke your backend integration

The following section describes how to invoke your backend integration using either the `$default` route or a custom route for a WebSocket API.

**Topics**
+ [

## Using routes to process messages
](#apigateway-websocket-api-overview-routes)
+ [

## The `$default` route
](#apigateway-websocket-api-routes-about-default)
+ [

## Custom routes
](#apigateway-websocket-api-routes-about-custom)
+ [

## Using API Gateway WebSocket API integrations to connect to your business logic
](#apigateway-websocket-api-overview-integrations)
+ [

## Important differences between WebSocket APIs and REST APIs
](#apigateway-websocket-api-overview-integrations-differences)

## Using routes to process messages


In API Gateway WebSocket APIs, messages can be sent from the client to your backend service and vice versa. Unlike HTTP's request/response model, in WebSocket the backend can send messages to the client without the client taking any action.

Messages can be JSON or non-JSON. However, only JSON messages can be routed to specific integrations based on message content. Non-JSON messages are passed through to the backend by the `$default` route.

**Note**  
API Gateway supports message payloads up to 128 KB with a maximum frame size of 32 KB. If a message exceeds 32 KB, you must split it into multiple frames, each 32 KB or smaller. If a larger message (or frame) is received, the connection is closed with code 1009.  
Currently binary payloads are not supported. If a binary frame is received, the connection is closed with code 1003. However, it is possible to convert binary payloads to text. See [Binary media types for WebSocket APIs in API Gateway](websocket-api-develop-binary-media-types.md).

With WebSocket APIs in API Gateway, JSON messages can be routed to execute a specific backend service based on message content. When a client sends a message over its WebSocket connection, this results in a *route request* to the WebSocket API. The request will be matched to the route with the corresponding route key in API Gateway. You can set up a route request for a WebSocket API in the API Gateway console, by using the AWS CLI, or by using an AWS SDK.

**Note**  
In the AWS CLI and AWS SDKs, you can create routes before or after you create integrations. Currently the console does not support reuse of integrations, so you must create the route first and then create the integration for that route.

You can configure API Gateway to perform validation on a route request before proceeding with the integration request. If the validation fails, API Gateway fails the request without calling your backend, sends a `"Bad request body"` gateway response similar to the following to the client, and publishes the validation results in CloudWatch Logs: 

```
{"message" : "Bad request body", "connectionId": "{connectionId}", "messageId": "{messageId}"}
```

This reduces unnecessary calls to your backend and lets you focus on the other requirements of your API.

You can also define a route response for your API's routes to enable two-way communication. A route response describes what data will be sent to your client upon completion of a particular route's integration. It is not necessary to define a response for a route if, for example, you want a client to send messages to your backend without receiving a response (one-way communication). However, if you don't provide a route response, API Gateway won't send any information about the result of your integration to your clients.

## The `$default` route


Every API Gateway WebSocket API can have a `$default` route. This is a special routing value that can be used in the following ways:
+ You can use it together with defined route keys, to specify a "fallback" route (for example, a generic mock integration that returns a particular error message) for incoming messages that don't match any of the defined route keys.
+ You can use it without any defined route keys, to specify a proxy model that delegates routing to a backend component.
+ You can use it to specify a route for non-JSON payloads.

## Custom routes


If you want to invoke a specific integration based on message content, you can do so by creating a custom route.

A custom route uses a route key and integration that you specify. When an incoming message contains a JSON property, and that property evaluates to a value that matches the route key value, API Gateway invokes the integration. (For more information, see [Overview of WebSocket APIs in API Gateway](apigateway-websocket-api-overview.md).)

For example, suppose you wanted to create a chat room application. You might start by creating a WebSocket API whose route selection expression is `$request.body.action`. You could then define two routes: `joinroom` and `sendmessage`. A client app might invoke the `joinroom` route by sending a message such as the following:

```
{"action":"joinroom","roomname":"developers"}
```

And it might invoke the `sendmessage` route by sending a message such as the following:

```
{"action":"sendmessage","message":"Hello everyone"}
```

## Using API Gateway WebSocket API integrations to connect to your business logic


After setting up a route for an API Gateway WebSocket API, you must specify the integration you'd like to use. As with a route, which can have a route request and a route response, an integration can have an *integration request* and an *integration response*. An *integration request* contains the information expected by your backend in order to process the request that came from your client. An *integration response* contains the data that your backend returns to API Gateway, and that may be used to construct a message to send to the client (if a route response is defined).

For more information about setting up integrations, see [Integrations for WebSocket APIs in API Gateway](apigateway-websocket-api-integrations.md).

## Important differences between WebSocket APIs and REST APIs


Integrations for WebSocket APIs are similar to integrations for REST APIs, except for the following differences:
+ Currently, in the API Gateway console you must create a route first and then create an integration as that route's target. However, in the API and CLI, you can create routes and integrations independently, in any order.
+ You can use a single integration for multiple routes. For example, if you have a set of actions that closely relate to each other, you might want all of those routes to go to a single Lambda function. Rather than defining the details of the integration multiple times, you can specify it once and assign it to each of the related routes.
**Note**  
Currently the console does not support reuse of integrations, so you must create the route first and then create the integration for that route.  
In the AWS CLI and AWS SDKs, you can reuse an integration by setting the route's target to a value of `"integrations/{integration-id}"`, where `{integration-id}"` is the unique ID of the integration to be associated with the route.
+ API Gateway provides multiple [selection expressions](apigateway-websocket-api-selection-expressions.md) you can use in your routes and integrations. You don't need to rely on the content type to select an input template or output mapping. As with route selection expressions, you can define a selection expression to be evaluated by API Gateway to choose the right item. All of them will fall back to the `$default` template if a matching template is not found.
  + In integration requests, the template selection expression supports `$request.body.<json_path_expression>` and static values.
  + In integration responses, the template selection expression supports `$request.body.<json_path_expression>`, `$integration.response.statuscode`, `$integration.response.header.<headerName>`, and static values.

In the HTTP protocol, in which requests and responses are sent synchronously; communication is essentially one-way. In the WebSocket protocol, communication is two-way. Responses are asynchronous and are not necessarily received by the client in the same order as the client's messages were sent. In addition, the backend can send messages to the client.

**Note**  
For a route that is configured to use `AWS_PROXY` or `LAMBDA_PROXY` integration, communication is one-way, and API Gateway will not pass the backend response through to the route response automatically. For example, in the case of `LAMBDA_PROXY` integration, the body that the Lambda function returns will not be returned to the client. If you want the client to receive integration responses, you must define a route response to make two-way communication possible.

# WebSocket selection expressions
WebSocket selection expressions

API Gateway uses selection expressions as a way to evaluate request and response context and produce a key. The key is then used to select from a set of possible values, typically provided by you, the API developer. The exact set of supported variables will vary depending on the particular expression. Each expression is discussed in more detail below.

For all of the expressions, the language follows the same set of rules:
+ A variable is prefixed with `"$"`.
+ Curly braces can be used to explicitly define variable boundaries, e.g., `"${request.body.version}-beta"`.
+ Multiple variables are supported, but evaluation occurs only once (no recursive evaluation).
+ A dollar sign (`$`) can be escaped with `"\"`. This is most useful when defining an expression that maps to the reserved `$default` key, e.g., `"\$default"`.
+ In some cases, a pattern format is required. In this case, the expression should be wrapped with forward slashes (`"/"`), e.g. `"/2\d\d/"` to match `2XX` status codes.

**Topics**
+ [

## Route response selection expressions
](#apigateway-websocket-api-route-response-selection-expressions)
+ [

## API key selection expressions
](#apigateway-websocket-api-apikey-selection-expressions)
+ [

## API mapping selection expressions
](#apigateway-websocket-api-mapping-selection-expressions)
+ [

## WebSocket selection expression summary
](#apigateway-websocket-api-selection-expression-table)

## Route response selection expressions


A [route response](apigateway-websocket-api-route-response.md) is used for modeling a response from the backend to the client. For WebSocket APIs, a route response is optional. When defined, it signals to API Gateway that it should return a response to a client upon receiving a WebSocket message.

Evaluation of the *route response selection expression* produces a route response key. Eventually, this key will be used to choose from one of the [https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html](https://docs.aws.amazon.com/apigatewayv2/latest/api-reference/apis-apiid-routes-routeid-routeresponses.html) associated with the API. However, currently only the `$default` key is supported.

## API key selection expressions


This expression is evaluated when the service determines the given request should proceed only if the client provides a valid [API key](api-gateway-basic-concept.md#apigateway-definition-api-key).

Currently the only two supported values are `$request.header.x-api-key` and `$context.authorizer.usageIdentifierKey`.

## API mapping selection expressions


This expression is evaluated to determine which API stage is selected when a request is made using a custom domain.

Currently, the only supported value is `$request.basepath`.

## WebSocket selection expression summary


The following table summarizes the use cases for selection expressions in WebSocket APIs:


| Selection expression | Evaluates to key for | Notes | Example use case | 
| --- | --- | --- | --- | 
| Api.RouteSelectionExpression | Route.RouteKey | \$1default is supported as a catch-all route. | Route WebSocket messages based on the context of a client request. | 
| Route.ModelSelectionExpression | Key for Route.RequestModels | Optional. If provided for non-proxy integration, model validation occurs. `$default` is supported as a catch-all.  | Perform request validation dynamically within the same route. | 
| Integration.TemplateSelectionExpression | Key for Integration.RequestTemplates |  Optional. May be provided for non-proxy integration to manipulate incoming payloads. `${request.body.jsonPath}` and static values are supported. `$default` is supported as a catch-all.  | Manipulate the caller's request based on dynamic properties of the request. | 
| Integration.IntegrationResponseSelectionExpression | IntegrationResponse.IntegrationResponseKey |  Optional. May be provided for non-proxy integration. Acts as a pattern match for error messages (from Lambda) or status codes (from HTTP integrations). `$default` is required for non-proxy integrations to act as the catch-all for successful responses.  |  Manipulate the response from the backend. Choose the action to occur based on the dynamic response of the backend (e.g., handling certain errors distinctly).  | 
| IntegrationResponse.TemplateSelectionExpression | Key for IntegrationResponse.ResponseTemplates | Optional. May be provided for non-proxy integration. \$1default is supported.  |  In some cases, a dynamic property of the response may dictate different transformations within the same route and associated integration. `${request.body.jsonPath}`, `${integration.response.statuscode}`, `${integration.response.header.headerName}`, `${integration.response.multivalueheader.headerName}`, and static values are supported. `$default` is supported as a catch-all.  | 
| Route.RouteResponseSelectionExpression | RouteResponse.RouteResponseKey |  Should be provided to initiate two-way communication for a WebSocket route. Currently, this value is restricted to `$default` only.  |  | 
| RouteResponse.ModelSelectionExpression | Key for RouteResponse.RequestModels | Currently unsupported. |  | 