tsoa icon indicating copy to clipboard operation
tsoa copied to clipboard

Middleware: AWS API Gateway V2 Support

Open simonireilly opened this issue 3 years ago • 3 comments

Sorting

  • I'm submitting a ...

    • [ ] bug report
    • [x] feature request
    • [ ] support request
  • I confirm that I

    • [x] used the search to make sure that a similar issue hasn't already been submit

Replaces: https://github.com/lukeautry/tsoa/issues/971 Enables: https://github.com/lukeautry/tsoa/issues/1105

Background

AWS APIGateway V2 is a high availability API as a Service that provides:

  • Authentication
  • Authorisation
  • Routing

It has native support for uploading an OPENAPI declaration as shown in https://github.com/lukeautry/tsoa/issues/1012

Proposal

This issue proposes supporting API Gateway V2 natively with the following API:

Generation of routes for an Lambda handler that supports TSOA

{
    "basePath": "/v1",
    "entryFile": "./src/handler.ts",
    "middleware": "api-gateway-v2"
}

Creation of the src/handler.ts

import { RegisteredRoutes } form './routes'

// A single lambda for all routes
export const handler = (event, context) => RegisteredRoutes

// A lambda solely for the get user route, which invokes the appropriate controller
const getUserHandler = (event, context) => RegisteredRoutes['GET /user/:userId']

The Lambda code above for NodeJS is deployed behind an AWS API Gateway V2 instance.

Justification

API Gateway V2 backed by Lambda is a very popular stack for constructing high availability (10,000 req/s) APIs. These API's are 100% free at low volume making them a good candidate for Start-ups, and established players alike.

There are few frameworks existing designed to make:

  • Type safety guarantees
  • Payload validation
  • Documentation generation

Easy for this environment.

As such users have previously attempted to use TSOA to enable a better developer experience. Those users and potential new users attracted to the framework by its support of lambda would be the target.

Alternatives

  • Just use express with Vendias serverless express https://github.com/vendia/serverless-express
  • Use NestJS with standalone deployment to serverless https://docs.nestjs.com/faq/serverless

API Gateway & Lambda Integration

AWS API Gateway handles authentication, authorisation, and routing. The template required for lambda would therefore not include those concerns.

Additionally an assumption would be made that File handling would be outside the scope of the initial implementation

API Gateway provides the (event, context) where event is basically (req) in javascript middleware frameworks.

Interfaces

Since API Gateway is mature and versioned semantically by AWS, it is a good candidate for an integration template.

Request/Response formats are typed by the @types/aws-lambda library as:

export interface APIGatewayProxyEventV2 {
    version: string;
    routeKey: string;
    rawPath: string;
    rawQueryString: string;
    cookies?: string[] | undefined;
    headers: APIGatewayProxyEventHeaders;
    queryStringParameters?: APIGatewayProxyEventQueryStringParameters | undefined;
    requestContext: {
        accountId: string;
        apiId: string;
        authorizer?: {
            jwt: {
                claims: { [name: string]: string | number | boolean | string[] };
                scopes: string[];
            };
        } | undefined;
        domainName: string;
        domainPrefix: string;
        http: {
            method: string;
            path: string;
            protocol: string;
            sourceIp: string;
            userAgent: string;
        };
        requestId: string;
        routeKey: string;
        stage: string;
        time: string;
        timeEpoch: number;
    };
    body?: string | undefined;
    pathParameters?: APIGatewayProxyEventPathParameters | undefined;
    isBase64Encoded: boolean;
    stageVariables?: APIGatewayProxyEventStageVariables | undefined;
}

Response:

export interface APIGatewayProxyStructuredResultV2 {
    statusCode?: number | undefined;
    headers?: {
        [header: string]: boolean | number | string;
    } | undefined;
    body?: string | undefined;
    isBase64Encoded?: boolean | undefined;
    cookies?: string[] | undefined;
}

simonireilly avatar Nov 20 '21 07:11 simonireilly

Hello there simonireilly 👋

Thank you for opening your very first issue in this project.

We will try to get back to you as soon as we can.👀

github-actions[bot] avatar Nov 20 '21 07:11 github-actions[bot]

+1

Being able to automatically ship to Lambda/API Gateway would be awesome!

moshe-shaham-dt avatar Nov 29 '21 09:11 moshe-shaham-dt

Seconding the above. Right now it looks like we'll be manipulating the YAML in Jenkins or Terraform during deploy.. which is exactly what the old system did that pushed us to move away from it 😂 Thanks for your work on this.

and0p avatar Mar 17 '22 01:03 and0p