'SAM local start-api CORS issue

I am using AWS CDK (Typescript) and running SAM local start-api to spin up an API tied to lambda resolvers and am running into a CORS issue when trying to hit the API from a browser. Here is my code:

lambda config

import { Construct } from 'constructs';
import {
  IResource,
  LambdaIntegration,
  MockIntegration,
  PassthroughBehavior,
  RestApi,
} from 'aws-cdk-lib/aws-apigateway';
import {
  NodejsFunction,
  NodejsFunctionProps,
} from 'aws-cdk-lib/aws-lambda-nodejs';
import { Runtime } from 'aws-cdk-lib/aws-lambda';

import { join } from 'path';
import * as lambda from 'aws-cdk-lib/aws-lambda';
import * as s3 from 'aws-cdk-lib/aws-s3';
import * as ec2 from 'aws-cdk-lib/aws-ec2';
import * as rds from 'aws-cdk-lib/aws-rds';
import * as cdk from 'aws-cdk-lib';

export function addCorsOptions(apiResource: IResource) {
  apiResource.addMethod(
    'OPTIONS',
    new MockIntegration({
      integrationResponses: [
        {
          statusCode: '200',
          responseParameters: {
            'method.response.header.Access-Control-Allow-Headers':
              "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
            'method.response.header.Access-Control-Allow-Origin': "'*'",
            'method.response.header.Access-Control-Allow-Credentials':
              "'false'",
            'method.response.header.Access-Control-Allow-Methods':
              "'OPTIONS,GET,PUT,POST,DELETE'",
          },
        },
      ],
      passthroughBehavior: PassthroughBehavior.NEVER,
      requestTemplates: {
        'application/json': '{"statusCode": 200}',
      },
    }),
    {
      methodResponses: [
        {
          statusCode: '200',
          responseParameters: {
            'method.response.header.Access-Control-Allow-Headers': true,
            'method.response.header.Access-Control-Allow-Methods': true,
            'method.response.header.Access-Control-Allow-Credentials': true,
            'method.response.header.Access-Control-Allow-Origin': true,
          },
        },
      ],
    }
  );
}

export class FrontendService extends Construct {
  constructor(scope: Construct, id: string) {
    super(scope, id);

    const vpc = new ec2.Vpc(this, 'HospoFEVPC');
    const cluster = new rds.ServerlessCluster(this, 'AuroraHospoFECluster', {
      engine: rds.DatabaseClusterEngine.AURORA_POSTGRESQL,
      parameterGroup: rds.ParameterGroup.fromParameterGroupName(
        this,
        'ParameterGroup',
        'default.aurora-postgresql10'
      ),
      defaultDatabaseName: 'hospoFEDB',
      vpc,
      scaling: {
        autoPause: cdk.Duration.seconds(0),
      },
    });

    const bucket = new s3.Bucket(this, 'FrontendStore');

    const nodeJsFunctionProps: NodejsFunctionProps = {
      environment: {
        BUCKET: bucket.bucketName,
        CLUSTER_ARN: cluster.clusterArn,
        SECRET_ARN: cluster.secret?.secretArn || '',
        DB_NAME: 'hospoFEDB',
        AWS_NODEJS_CONNECTION_REUSE_ENABLED: '1',
      },
      runtime: Runtime.NODEJS_14_X,
    };

    const registerLambda = new NodejsFunction(this, 'registerFunction', {
      entry: 'dist/lambda/register.js',
      memorySize: 1024,
      ...nodeJsFunctionProps,
    });

    const registerIntegration = new LambdaIntegration(registerLambda);

    const api = new RestApi(this, 'frontend-api', {
      restApiName: 'Frontend Service',
      description: 'This service serves the frontend.',
    });

    const registerResource = api.root.addResource('register');
    registerResource.addMethod('POST', registerIntegration);
    addCorsOptions(registerResource);
  }
}

lambda resolver

export async function handler(event: any, context: any) {
    return {
      statusCode: 200,
      headers: { 'Access-Control-Allow-Origin': '*' },
      body: JSON.stringify(body),
    };
}

When I deploy the function to AWS and try hitting the endpoint from the live URL it works fine without any CORS issue, so it looks like the error may be with the SAMS-CLI. Would love to know how to get around this

EDIT

Here is an image from the terminal where you can see the failed OPTIONS request.

enter image description here

Putting this up for another bounty as I did not get an appropriate answer the first time round



Solution 1:[1]

As per this docs, you don't need to manually configure the pre-flight OPTIONS method.

For example,

new apigateway.RestApi(this, 'api', {
  defaultCorsPreflightOptions: {
    allowOrigins: apigateway.Cors.ALL_ORIGINS,
    allowMethods: apigateway.Cors.ALL_METHODS // this is also the default
  }
})

Then you can do away with the manual addCorsOptions().

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1