Skip to content

Router

Reference doc for the `sst.aws.Router` component.

The Router component lets you use a CloudFront distribution to direct requests to various parts of your application. The routes prop can route requests to function URLs, different domains, or any component that has an associated URL.

Minimal example

sst.config.ts
new sst.aws.Router("MyRouter", {
routes: {
"/*": "https://some-internal-service.com"
}
});

Route to a function URL

sst.config.ts
const myFunction = new sst.aws.Function("MyFunction", {
handler: "src/api.handler",
url: true,
});
new sst.aws.Router("MyRouter", {
routes: {
"/*": myFunction.url
}
});

Route to a bucket

sst.config.ts
const myBucket = new sst.aws.Bucket("MyBucket", {
access: "cloudfront"
});
new sst.aws.Router("MyRouter", {
routes: {
"/files/*": {
bucket: myBucket
}
}
});

Make sure to allow CloudFront access to the bucket by setting the access prop on the bucket.

Route all API requests separately

sst.config.ts
new sst.aws.Router("MyRouter", {
routes: {
"/*": "https://myapp.com",
"/api/*": myFunction.url
}
});

Add a custom domain

sst.config.ts
new sst.aws.Router("MyRouter", {
domain: "myapp.com",
routes: {
"/*": myFunction.url
}
});

Constructor

new Router(name, args, opts?)

Parameters

RouterArgs

domain?

Type Input<string | Object>

Set a custom domain for your Router.

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()
}
}

Specify a www. version of the custom domain.

{
domain: {
name: "domain.com",
redirects: ["www.domain.com"]
}
}

domain.aliases?

Type Input<string[]>

Alias domains that should be used. Unlike the redirect option, this keeps your visitors on this alias domain.

So if your users visit app2.domain.com, they will stay on app2.domain.com in their browser.

{
domain: {
name: "app1.domain.com",
aliases: ["app2.domain.com"]
}
}

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.

The certificate will be created in the us-east-1 region as required by AWS CloudFront. If you are creating your own certificate, you must also create it in us-east-1.

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 CloudFront distribution URL.
{
domain: {
name: "domain.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.redirects?

Type Input<string[]>

Alternate domains to be used. Visitors to the alternate domains will be redirected to the main name.

Use this to create a www. version of your domain and redirect visitors to the apex domain.

{
domain: {
name: "domain.com",
redirects: ["www.domain.com"]
}
}

invalidation?

Type Input<boolean | Object>

Default Invalidation is turned off

Configure how the CloudFront cache invalidations are handled.

Enable invalidations. Setting this to true will invalidate all paths. It is equivalent to passing in { paths: ["/*"] }.

{
invalidation: true
}

invalidation.paths?

Type Input<Input<string>[]>

Default [”/*”]

Specify an array of glob pattern of paths to invalidate.

Invalidate the index.html and all files under the products/ route. This counts as two invalidations.

{
invalidation: {
paths: ["/index.html", "/products/*"]
}
}

invalidation.token?

Type Input<string>

Default A unique value is auto-generated on each deploy

The invalidation token is used to determine if the cache should be invalidated. If the token is the same as the previous deployment, the cache will not be invalidated.

{
invalidation: {
token: "foo123"
}
}

invalidation.wait?

Type Input<boolean>

Default false

Configure if sst deploy should wait for the CloudFront cache invalidation to finish.

Waiting for this process to finish ensures that new content will be available after the deploy finishes. However, this process can sometimes take more than 5 mins.

{
invalidation: {
wait: true
}
}

routes

Type Input<Record<string, Input<string | RouterUrlRouteArgs | RouterBucketRouteArgs>>>

A map of routes to their destinations. The key is the route path and the value can be:

  • The destination URL as a string
  • Or, an object with
    • Args for a URL route
    • Args for a bucket route

For example, you can set the destination as a URL.

{
routes: {
"/*": "https://example.com"
}
}

Or, you can route to a bucket.

{
routes: {
"/files/*": {
bucket: myBucket
}
}
}

When router receives a request, the requested path is compared with path patterns in the order they are listed. The first match determines which URL the request is routed to.

The /* route is a default route, meaning that if no routes match, the /* route will be used. It does not matter where the /* route is listed in the routes object.

Suppose you have the following three routes.

{
routes: {
"/api/*.json": "https://example1.com",
"/api/*": "https://example2.com",
"/*.xml": "https://example3.com",
}
}

A request to /api/sample.xml will match /api/* first and route to it; even though it matches /*.xml.

However for this case, a request to /api/users will route to /api/* even though it comes after /*. This is because the /* route is the default route.

{
routes: {
"/*": "myapp.com",
"/api/*": myFunction.url
}
}

You can also customize the route behavior with injecting some code into the CloudFront Functions. To do so, pass in an object, with the destination as the url.

{
routes: {
"/*": {
url: "https://example.com",
edge: {
viewerRequest: {
injection: `event.request.headers["x-foo"] = "bar";`
}
}
}
}
}

You can also rewrite the request path.

{
routes: {
"/files/*": {
bucket: myBucket,
rewrite: {
regex: "^/files/(.*)$",
to: "/$1"
}
}
}
}

transform?

Type Object

Transform how this component creates its underlying resources.

transform.cachePolicy?

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

Transform the Cache Policy that’s attached to each CloudFront behavior.

transform.cdn?

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

Transform the CloudFront CDN resource.

Properties

distributionID

Type Output<string>

The ID of the Router distribution.

nodes

Type Object

The underlying resources this component creates.

nodes.cdn

Type Cdn

The Amazon CloudFront CDN resource.

url

Type Output<string>

The URL of the Router.

If the domain is set, this is the URL with the custom domain. Otherwise, it’s the autogenerated CloudFront URL.

SDK

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


This is accessible through the Resource object in the SDK.

  • url string

    The URL of the Router.

    If the domain is set, this is the URL with the custom domain. Otherwise, it’s the autogenerated CloudFront URL.

Methods

static get

Router.get(name, distributionID, opts?)

Parameters

  • name string

    The name of the component.
  • distributionID Input<string>

    The id of the existing Router distribution.
  • opts? ComponentResourceOptions

Returns Router

Reference an existing Router with the given Router distribution ID. This is useful when you create a Router in one stage and want to share it in another. It avoids having to create a new Router in the other stage.

Imagine you create a Router in the dev stage. And in your personal stage frank, instead of creating a new Router, you want to share the same Router from dev.

sst.config.ts
const router = $app.stage === "frank"
? sst.aws.Router.get("MyRouter", "E2IDLMESRN6V62")
: new sst.aws.Router("MyRouter");

Here E2IDLMESRN6V62 is the ID of the Router distribution created in the dev stage. You can find this by outputting the distribution ID in the dev stage.

sst.config.ts
return {
router: router.distributionID
};

RouterBucketRouteArgs

bucket?

Type Input<string | Bucket>

A bucket to route to.

For example, let’s say you have a bucket that gives CloudFront access.

sst.config.ts
const myBucket = new sst.aws.Bucket("MyBucket", {
access: "cloudfront"
});

You can then this directly as the destination for the route.

{
routes: {
"/files/*": {
bucket: myBucket
}
}
}

Or if you have an existing bucket, you can pass in its regional domain.

{
routes: {
"/files/*": {
bucket: "my-bucket.s3.us-east-1.amazonaws.com"
}
}
}

edge?

Type Object

Configure CloudFront Functions to customize the behavior of HTTP requests and responses at the edge.

edge.viewerRequest?

Type Input<Object>

Configure the viewer request function.

The viewer request function can be used to modify incoming requests before they reach your origin server. For example, you can redirect users, rewrite URLs, or add headers.

edge.viewerRequest.injection

Type Input<string>

The code to inject into the viewer request function.

By default, a viewer request function is created to add the x-forwarded-host header. The given code will be injected at the end of this function.

async function handler(event) {
// Default behavior code
// User injected code
return event.request;
}

To add a custom header to all requests.

{
server: {
edge: {
viewerRequest: {
injection: `event.request.headers["x-foo"] = "bar";`
}
}
}
}
edge.viewerRequest.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer request function.

Takes a list of CloudFront KeyValueStore ARNs.

{
routes: {
"/api/*": {
edge: {
viewerRequest: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}
}
}

edge.viewerResponse?

Type Input<Object>

Configure the viewer response function.

The viewer response function can be used to modify outgoing responses before they are sent to the client. For example, you can add security headers or change the response status code.

By default, no viewer response function is set. A new function will be created with the provided code.

Add a custom header to all responses

{
routes: {
"/api/*": {
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}
}
}
edge.viewerResponse.injection

Type Input<string>

The code to inject into the viewer response function.

By default, no viewer response function is set. A new function will be created with the provided code.

async function handler(event) {
// User injected code
return event.response;
}

To add a custom header to all responses.

{
server: {
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}
}
edge.viewerResponse.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer response function.

Takes a list of CloudFront KeyValueStore ARNs.

{
routes: {
"/api/*": {
edge: {
viewerResponse: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}
}
}

rewrite?

Type Input<Object>

Rewrite the request path.

By default, if the route path is /files/* and a request comes in for /files/logo.png, the request path the destination sees is /files/logo.png. In the case of a bucket route, the file logo.png is served from the files directory in the bucket.

If you want to serve the file from the root of the bucket, you can rewrite the request path to /logo.png.

{
routes: {
"/files/*": {
bucket: myBucket,
rewrite: {
regex: "^/files/(.*)$",
to: "/$1"
}
}
}
}

rewrite.regex

Type Input<string>

The regex to match the request path.

rewrite.to

Type Input<string>

The replacement for the matched path.

RouterUrlRouteArgs

edge?

Type Object

Configure CloudFront Functions to customize the behavior of HTTP requests and responses at the edge.

edge.viewerRequest?

Type Input<Object>

Configure the viewer request function.

The viewer request function can be used to modify incoming requests before they reach your origin server. For example, you can redirect users, rewrite URLs, or add headers.

edge.viewerRequest.injection

Type Input<string>

The code to inject into the viewer request function.

By default, a viewer request function is created to add the x-forwarded-host header. The given code will be injected at the end of this function.

async function handler(event) {
// Default behavior code
// User injected code
return event.request;
}

To add a custom header to all requests.

{
server: {
edge: {
viewerRequest: {
injection: `event.request.headers["x-foo"] = "bar";`
}
}
}
}
edge.viewerRequest.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer request function.

Takes a list of CloudFront KeyValueStore ARNs.

{
routes: {
"/api/*": {
edge: {
viewerRequest: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}
}
}

edge.viewerResponse?

Type Input<Object>

Configure the viewer response function.

The viewer response function can be used to modify outgoing responses before they are sent to the client. For example, you can add security headers or change the response status code.

By default, no viewer response function is set. A new function will be created with the provided code.

Add a custom header to all responses

{
routes: {
"/api/*": {
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}
}
}
edge.viewerResponse.injection

Type Input<string>

The code to inject into the viewer response function.

By default, no viewer response function is set. A new function will be created with the provided code.

async function handler(event) {
// User injected code
return event.response;
}

To add a custom header to all responses.

{
server: {
edge: {
viewerResponse: {
injection: `event.response.headers["x-foo"] = "bar";`
}
}
}
}
edge.viewerResponse.kvStores?

Type Input<Input<string>[]>

The KV stores to associate with the viewer response function.

Takes a list of CloudFront KeyValueStore ARNs.

{
routes: {
"/api/*": {
edge: {
viewerResponse: {
kvStores: ["arn:aws:cloudfront::123456789012:key-value-store/my-store"]
}
}
}
}
}

rewrite?

Type Input<Object>

Rewrite the request path.

By default, if the route path is /api/* and a request comes in for /api/users/profile, the request path the destination sees is /api/users/profile.

If you want to serve the route from the root, you can rewrite the request path to /users/profile.

{
routes: {
"/api/*": {
url: "https://api.example.com",
rewrite: {
regex: "^/api/(.*)$",
to: "/$1"
}
}
}
}

rewrite.regex

Type Input<string>

The regex to match the request path.

rewrite.to

Type Input<string>

The replacement for the matched path.

url

Type Input<string>

The destination URL.

{
routes: {
"/api/*": {
url: "https://example.com"
}
}
}