aws / aws-sam-cli

CLI tool to build, test, debug, and deploy Serverless applications using AWS SAM
https://aws.amazon.com/serverless/sam/
Apache License 2.0
6.52k stars 1.17k forks source link

CORS doesn't work in sam for simple requests when using AWS::Serverless::HttpApi #3803

Open CraigStuntzWillowTree opened 2 years ago

CraigStuntzWillowTree commented 2 years ago

Description:

CORS doesn't work in sam for simple requests when using AWS::Serverless::HttpApi. It does work on preflighted requests, and it also works on "real" AWS.

Steps to reproduce:

AWSTemplateFormatVersion: "2010-09-09"
Transform: AWS::Serverless-2016-10-31
Globals:
  HttpApi:
    CorsConfiguration:
      AllowOrigins: 
        - https://localhost:8001
      AllowHeaders: 
        - Content-Type
      AllowMethods: 
        - "*"
Resources:
  APIGateway:
    Type: AWS::Serverless::HttpApi
    Properties:
      StageName: local
  GetTestFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: dist/GetTestFunction/index.handler
      Runtime: nodejs14.x
      Timeout: 10
      Events:
        GetEvent:
          Type: HttpApi
          Properties:
            Path: /test
            Method: GET

(I couldn't get this to work at all if I put the CorsConfiguration in the AWS::Serverless::HttpApi element instead of in Globals, despite your configurator saying it should work in either place. That's an issue for another ticket.)

import { APIGatewayProxyEventV2 } from "aws-lambda";

export async function handler(_event: APIGatewayProxyEventV2) {
    const response = {
        statusCode: 200,
        body: `Hello from Lambda`,
    };

    return response;
}

We are running this with npm run start:dev where:

    "start:dev": "npm run clean && webpack -w --config webpack.dev.js & sam local start-api --profile xxxxxxx --warm-containers LAZY",

Observed result:

$ curl -i -H "Origin: https://localhost:8001" http://localhost:3000/test
HTTP/1.0 200 OK
Content-Type: application/json
Content-Length: 17
Server: Werkzeug/1.0.1 Python/3.8.13
Date: Thu, 31 Mar 2022 19:09:58 GMT

Hello from Lambda⏎

(Note no Access-Control-Allow-Origin header.)

Expected result:

Here it is running on "real" AWS (we deploy with terraform, not sam, so I believe this is close to what SAM might deploy, but essentially I've just configured CORS on the API Gateway)

 $ curl -i -H "Origin: https://localhost:8001" https://xxxxxxxx.execute-api.us-west-2.amazonaws.com/sandbox/test
HTTP/2 200
date: Thu, 31 Mar 2022 19:11:21 GMT
content-type: text/plain; charset=utf-8
content-length: 17
access-control-allow-origin: https://localhost:8001
apigw-requestid: P3Rx-hT9vHcEPQg=

Hello from Lambda⏎

(Note Access-Control-Allow-Origin header is present.)

A preflight request against sam also works:

$ curl -i -X OPTIONS -H "Origin: https://localhost:8001" http://localhost:3000/test
HTTP/1.0 200 OK
Access-Control-Allow-Origin: https://localhost:8001
Access-Control-Allow-Methods: DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT
Access-Control-Allow-Headers: Content-Type
Content-Length: 0
Server: Werkzeug/1.0.1 Python/3.8.13
Date: Thu, 31 Mar 2022 19:23:02 GMT

Additional environment details (Ex: Windows, Mac, Amazon Linux etc)

  1. OS: macOS 12.3
  2. If using SAM CLI, sam --version: SAM CLI, version 1.43.0
  3. AWS region: Mostly local for this report, but us-west-2 is working correctly
qingchm commented 2 years ago

Thanks for reporting this to us! I will try to reproduce this to confirm the behaviour, then we can get back to this to discuss the following steps!

ericbn commented 1 year ago

Oddly, for me this was ignored (no updates in the actual API Gateway CORS configuration, and no errors during build or deploy):

    CorsConfiguration:
      AllowCredentials: true
      AllowHeaders:
        - Content-Type
        - X-Amz-Date
        - Authorization
        - X-Api-Key
        - X-Amz-Security-Token
        - X-Amz-User-Agent
        - X-Amzn-Trace-Id
      AllowMethods:
        - OPTIONS
        - GET
        - POST
        - PUT
      AllowOrigins: !FindInMap [StageMap, !Ref Stage, AllowedOrigins]

but this worked (the actual API Gateway CORS configuration was updated):

    CorsConfiguration:
      AllowCredentials: false
      AllowHeaders:
        - Content-Type
        - X-Amz-Date
        - Authorization
        - X-Api-Key
        - X-Amz-Security-Token
        - X-Amz-User-Agent
        - X-Amzn-Trace-Id
      AllowMethods:
        - OPTIONS
        - GET
        - POST
        - PUT
      AllowOrigins:
        - "*"