Skip to content
GitHub Discord

ApiGatewayWebSocket

The ApiGatewayWebSocket component lets you add an Amazon API Gateway WebSocket API to your app.

Create the API

sst.config.ts
const api = new sst.aws.ApiGatewayWebSocket("MyApi");

Add a custom domain

sst.config.ts
new sst.aws.ApiGatewayWebSocket("MyApi", {
domain: "api.example.com"
});

Add routes

sst.config.ts
api.route("$connect", "src/connect.handler");
api.route("$disconnect", "src/disconnect.handler");
api.route("$default", "src/default.handler");
api.route("sendMessage", "src/sendMessage.handler");

Constructor

new ApiGatewayWebSocket(name, args?, opts?)

Parameters

ApiGatewayWebSocketArgs

accessLog?

Type Input<Object>

Default {retention: “1 month”}

Configure the API Gateway logs in CloudWatch. By default, access logs are enabled and kept for 1 month.

{
accessLog: {
retention: "forever"
}
}

accessLog.retention?

Type Input<“1 day” | “3 days” | “5 days” | “1 week” | “2 weeks” | “1 month” | “2 months” | “3 months” | “4 months” | “5 months” | “6 months” | “1 year” | “13 months” | “18 months” | “2 years” | “3 years” | “5 years” | “6 years” | “7 years” | “8 years” | “9 years” | “10 years” | “forever”>

Default 1 month

The duration the API Gateway logs are kept in CloudWatch.

domain?

Type Input<string | Object>

Set a custom domain for your WebSocket API.

Automatically manages domains hosted on AWS Route 53, Cloudflare, and Vercel. For other providers, you’ll need to pass in a cert that validates domain ownership and add the DNS records.

By default this assumes the domain is hosted on Route 53.

{
domain: "example.com"
}

For domains hosted on Cloudflare.

{
domain: {
name: "example.com",
dns: sst.cloudflare.dns()
}
}

domain.cert?

Type Input<string>

The ARN of an ACM (AWS Certificate Manager) certificate that proves ownership of the domain. By default, a certificate is created and validated automatically.

To manually set up a domain on an unsupported provider, you’ll need to:

  1. Validate that you own the domain by creating an ACM certificate. You can either validate it by setting a DNS record or by verifying an email sent to the domain owner.
  2. Once validated, set the certificate ARN as the cert and set dns to false.
  3. Add the DNS records in your provider to point to the API Gateway URL.
{
domain: {
name: "example.com",
dns: false,
cert: "arn:aws:acm:us-east-1:112233445566:certificate/3a958790-8878-4cdc-a396-06d95064cf63"
}
}

domain.dns?

Type Input<false | sst.aws.dns | sst.cloudflare.dns | sst.vercel.dns>

Default sst.aws.dns

The DNS provider to use for the domain. Defaults to the AWS.

Takes an adapter that can create the DNS records on the provider. This can automate validating the domain and setting up the DNS routing.

Supports Route 53, Cloudflare, and Vercel adapters. For other providers, you’ll need to set dns to false and pass in a certificate validating ownership via cert.

Specify the hosted zone ID for the Route 53 domain.

{
domain: {
name: "example.com",
dns: sst.aws.dns({
zone: "Z2FDTNDATAQYW2"
})
}
}

Use a domain hosted on Cloudflare, needs the Cloudflare provider.

{
domain: {
name: "example.com",
dns: sst.cloudflare.dns()
}
}

Use a domain hosted on Vercel, needs the Vercel provider.

{
domain: {
name: "example.com",
dns: sst.vercel.dns()
}
}

domain.name?

Type Input<string>

The custom domain you want to use.

{
domain: {
name: "example.com"
}
}

Can also include subdomains based on the current stage.

{
domain: {
name: `${$app.stage}.example.com`
}
}

domain.nameId?

Type Input<string>

Use an existing API Gateway domain name.

By default, a new API Gateway domain name is created. If you’d like to use an existing domain name, set the nameId to the ID of the domain name and do not pass in name.

{
domain: {
nameId: "example.com"
}
}

domain.path?

Type Input<string>

The base mapping for the custom domain. This adds a suffix to the URL of the API.

Given the following base path and domain name.

{
domain: {
name: "api.example.com",
path: "v1"
}
}

The full URL of the API will be https://api.example.com/v1/.

By default there is no base path, so if the name is api.example.com, the full URL will be https://api.example.com.

transform?

Type Object

Transform how this component creates its underlying resources.

transform.accessLog?

Type LogGroupArgs | (args: LogGroupArgs, opts: ComponentResourceOptions, name: string) => void

Transform the CloudWatch LogGroup resource used for access logs.

transform.api?

Type ApiArgs | (args: ApiArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway WebSocket API resource.

transform.domainName?

Type DomainNameArgs | (args: DomainNameArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway WebSocket API domain name resource.

transform.route?

Type Object

Transform the routes. This can be used to customize the handler function and the arguments for each route.

{
transform: {
route: {
handler: {
link: [bucket, stripeKey]
},
args: {
auth: { iam: true }
}
}
}
}
transform.route.args?

Type ApiGatewayWebSocketRouteArgs | (args: ApiGatewayWebSocketRouteArgs, opts: ComponentResourceOptions, name: string) => void

Transform the arguments for the route.

transform.route.handler?

Type FunctionArgs | (args: FunctionArgs, opts: ComponentResourceOptions, name: string) => void

Transform the handler function for the route.

transform.stage?

Type StageArgs | (args: StageArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway WebSocket API stage resource.

Properties

managementEndpoint

Type Output<string>

The management endpoint for the API used by the API Gateway Management API client. This is useful for sending messages to connected clients.

nodes

Type Object

The underlying resources this component creates.

nodes.api

Type Api

The Amazon API Gateway V2 API.

nodes.logGroup

Type LogGroup

The CloudWatch LogGroup for the access logs.

nodes.domainName

Type Output<DomainName>

The API Gateway HTTP API domain name.

url

Type Output<string>

The URL of the API.

If the domain is set, this is the URL with the custom domain. Otherwise, it’s the auto-generated API Gateway URL.

SDK

Use the SDK in your runtime to interact with your infrastructure.


This is accessible through the Resource object in the SDK.

  • managementEndpoint string

    The management endpoint for the API used by the API Gateway Management API client. This is useful for sending messages to connected clients.

  • url string

    The URL of the API.

    If the domain is set, this is the URL with the custom domain. Otherwise, it’s the auto-generated API Gateway URL.

Methods

addAuthorizer

addAuthorizer(name, args)

Parameters

Returns ApiGatewayV2Authorizer

Add an authorizer to the API Gateway WebSocket API.

Add a Lambda authorizer.

sst.config.ts
const authorizer = api.addAuthorizer("MyAuthorizer", {
lambda: {
function: "src/authorizer.handler"
}
});

Then use it on the $connect route, where API Gateway checks auth.

sst.config.ts
api.route("$connect", "src/connect.handler", {
auth: {
lambda: authorizer.id
}
});

API Gateway doesn’t support JWT authorizers on WebSocket APIs. To accept a JWT, such as a Cognito token, have the Lambda authorizer verify it. Here a browser sends the token in the query string, since it can’t set headers on a WebSocket connection.

sst.config.ts
const pool = new sst.aws.CognitoUserPool("MyUserPool");
const client = pool.addClient("Web");
const authorizer = api.addAuthorizer("MyAuthorizer", {
lambda: {
function: {
handler: "src/authorizer.handler",
environment: {
USER_POOL_ID: pool.id,
USER_POOL_CLIENT_ID: client.id
}
},
identitySources: ["route.request.querystring.token"]
}
});
api.route("$connect", "src/connect.handler", {
auth: {
lambda: authorizer.id
}
});

The authorizer verifies the token with aws-jwt-verify, and returns a policy that allows the connection. Add the package to your app first.

Terminal window
npm install aws-jwt-verify
src/authorizer.ts
import { CognitoJwtVerifier } from "aws-jwt-verify";
const verifier = CognitoJwtVerifier.create({
userPoolId: process.env.USER_POOL_ID!,
clientId: process.env.USER_POOL_CLIENT_ID!,
tokenUse: "access"
});
export async function handler(event) {
try {
const claims = await verifier.verify(event.queryStringParameters.token);
return {
principalId: claims.sub,
policyDocument: {
Version: "2012-10-17",
Statement: [
{ Action: "execute-api:Invoke", Effect: "Allow", Resource: event.methodArn }
]
}
};
} catch {
throw new Error("Unauthorized");
}
}

The client connects with the token, as wss://<api>/<stage>?token=<token>. For another issuer, aws-jwt-verify’s JwtVerifier or the jose package can check the token against the issuer’s keys.

route

route(route, handler, args?)

Parameters

Returns ApiGatewayWebSocketRoute

Add a route to the API Gateway WebSocket API.

There are three predefined routes:

  • $connect: When the client connects to the API.
  • $disconnect: When the client or the server disconnects from the API.
  • $default: The default or catch-all route.

In addition, you can create custom routes. When a request comes in, the API Gateway will look for the specific route defined by the user. If no route matches, the $default route will be invoked.

Add a simple route.

sst.config.ts
api.route("sendMessage", "src/sendMessage.handler");

Add a predefined route.

sst.config.ts
api.route("$default", "src/default.handler");

Enable auth on the $connect route, where API Gateway checks it.

sst.config.ts
api.route("$connect", "src/connect.handler", {
auth: {
iam: true
}
});

Customize the route handler.

sst.config.ts
api.route("sendMessage", {
handler: "src/sendMessage.handler",
memory: "2048 MB"
});

Or pass in the ARN of an existing Lambda function.

sst.config.ts
api.route("sendMessage", "arn:aws:lambda:us-east-1:123456789012:function:my-function");

ApiGatewayWebSocketAuthorizerArgs

lambda?

Type Input<Object>

Create a Lambda authorizer that can be used by the $connect route.

The function returns an IAM policy that allows or denies execute-api:Invoke, or throws Unauthorized. This is also how to check a JWT, such as a Cognito token: WebSocket APIs don’t support JWT authorizers, so the function verifies the token. See addAuthorizer for an example.

Configure Lambda auth.

{
lambda: {
function: "src/authorizer.index"
}
}

lambda.function

Type Input<string | FunctionArgs>

The Lambda authorizer function. Takes the handler path or the function args.

Add a simple authorizer.

{
function: "src/authorizer.index"
}

Customize the authorizer handler.

{
function: {
handler: "src/authorizer.index",
memory: "2048 MB"
}
}

lambda.identitySources?

Type Input<Input<string>[]>

Default [“route.request.header.Authorization”]

Specifies where to extract the identity from. A request without it is rejected before the authorizer runs.

A browser can’t set headers on a WebSocket connection, so a browser client usually sends its token in the query string.

{
identitySources: ["route.request.querystring.token"]
}

transform?

Type Object

Transform how this component creates its underlying resources.

transform.authorizer?

Type AuthorizerArgs | (args: AuthorizerArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway authorizer resource.

ApiGatewayWebSocketRouteArgs

auth?

Type Input<false | Object>

Enable auth for your WebSocket API. By default, auth is disabled.

Auth only applies to the $connect route: API Gateway checks it once, when a client connects. Other routes ignore it.

{
auth: {
iam: true
}
}

auth.iam?

Type Input<boolean>

Enable IAM authorization for a given API route. When IAM auth is enabled, clients need to use Signature Version 4 to sign their requests with their AWS credentials.

auth.lambda?

Type Input<string>

Enable custom Lambda authorization for a given API route. Pass in the authorizer ID.

{
auth: {
lambda: myAuthorizer.id
}
}

Where myAuthorizer is created by calling the addAuthorizer method.

name?

Type string

The name of the route.

By default, SST generates a unique suffix from the route path. Setting name gives you a stable, human-readable name like MyApiRouteSendMessageHandler.

Must be unique across all routes.

{
name: "SendMessage"
}

transform?

Type Object

Transform how this component creates its underlying resources.

transform.integration?

Type IntegrationArgs | (args: IntegrationArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway WebSocket API integration resource.

transform.route?

Type RouteArgs | (args: RouteArgs, opts: ComponentResourceOptions, name: string) => void

Transform the API Gateway WebSocket API route resource.