Skip to content

Building a REST API

Choosing an architecture

When building a serverless REST API, there are several architectural patterns you can apply. For most cases we recommend using an API Gateway with individual Lambda functions for each endpoint.

Adding API Gateway to CDK

To set up an API Gateway in your infrastructure code, we recommend to use the SpecRestApi construct from aws-cdk-lib/aws-apigateway.

This construct enables you to define your API mapping using OpenAPI specs.

ts
import { 
Stack
, StackProps } from 'aws-cdk-lib';
import {
Construct
} from 'constructs';
import {
SpecRestApi
,
ApiDefinition
,
EndpointType
} from 'aws-cdk-lib/aws-apigateway';
import * as
path
from 'node:path';
export class
AppStack
extends
Stack
{
constructor(
scope
:
Construct
,
id
: string,
props
?: StackProps) {
super(
scope
,
id
,
props
);
new
SpecRestApi
(this, 'MyRestApi', {
apiDefinition
:
ApiDefinition
.
fromAsset
(
path
.
join
(import.meta.
dirname
, '/path/to/openapi.json')
),
endpointTypes
: [
EndpointType
.
REGIONAL
],
}); // make sure to assign the correct permissions to your Lambdas. } }

Recommended settings for this construct can be found on our CDK snippet page.

Writing OpenAPI specs

You can use the OpenAPI extensions for API Gateway to add additional API Gateway metadata to your OpenAPI definitions.

A simple OpenAPI document with a single endpoint might look like this:

yaml
openapi: 3.0.1
info:
  title: Sample API
  version: 1.0.0
paths:
  /hello:
    get:
      responses:
        '200':
          description: A greeting
          content:
            application/json:
              schema:
                type: object
                properties:
                  message:
                    type: string
      x-amazon-apigateway-integration:
        httpMethod: POST
        passthroughBehavior: "when_no_match"
        type: aws_proxy
        uri:
          Fn::Sub: "arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${HelloWorld.Arn}/invocations"

In this case, the ${HelloWorld.Arn} refers to a Lambda function called "HelloWorld" that exists in the same CDK stack.

TIP

If you are writing your OpenAPI specifications manually, you can use Swagger Editor for validation and previewing.

Alternatively, you can generate your OpenAPI specifications using a code-first approach with libraries such as asteasolutions/zod-to-openapi.

Implementing a REST endpoint

To implement a REST endpoint, just add a Lambda function with REST integration.

When dealing with REST Lambdas, you will likely run into common problems that often require repetitive boilerplate code, such as normalising request headers, parsing and validating request parameters or handling errors.

Most of these challenges can be addressed with utilities from @backpack/aws-lambda:

ts
import { defineRestLambda } from "@backpack/aws-lambda";
import { parseRequest, jsonOk, defaultErrorHandler } from "@backpack/aws-lambda/rest";
import { AsyncResult } from "@backpack/error-handling/async-result";

export const handler = defineRestLambda(async (event) => {
  return AsyncResult
    // using `AsyncResult` from `@backpack/error-handling` to handle (async) errors
    .try(() => {
      const request = parseRequest(event);

      // parse a required header
      const callerId = request.getHeader("X-Caller-Id", { required: true });
      
      // parse a JSON body and validate it against a Zod schema 
      const book = request.getBody().json({ validated: BookSchema });

      // return a HTTP 200 result
      return jsonOk({ message: "Hello world" });
    })
    // apply the default error handler from `@backpack/aws-lambda/rest`
    .recover(defaultErrorHandler());
});

Check out the API reference of @backpack/aws-lambda to learn more. Or have a look at the Bookstore REST API demo.

Deploying with CDK

Now use the CDK CLI to deploy your API Gateway to your preferred environment:

bash
npx cdk deploy -c config=dev

After a successful deployment, you can trigger your endpoint from the AWS console.

Security and API Management

By default, your REST endpoints are publicly accessible. If you want to restrict access, you can integrate it with the API Management portal.