Enable CORS when running AWS SAM CLI locally
Asked Answered
A

5

10

Whenever I try to access serverless lambda function via POST through the browser I get the error

Response to preflight request doesn't pass access control check: No >'Access-Control-Allow-Origin' header is present on the requested resource.

When it is a /GET it works fine I have read it is because it is not sending pre flight request. When I change it to POST this is when it fails.

The command I am running:

sam local start-api

And my template.yaml is:

...

Resources:
    PropertiesFunction:
        Type: AWS::Serverless::Function
        Properties:
            CodeUri: target/service-0.0.1-SNAPSHOT.jar
            Handler: com.aws.PropertiesHandler::handleRequest
            Runtime: java8
            Events:
                PropertiesApi:
                    Type: Api
                    Properties:
                        Path: /properties
                        Method: post

...

How can I enable CORS on these endpoints?

Abut answered 15/11, 2018 at 4:23 Comment(0)
B
13

I had the same error and I have already fixed it in 3 steps. (AWS Lambda in Java8, SAM CLI v0.37.0)

  1. Add options for your header:
    Map<String, String> headers = new HashMap<>();
    headers.put("Content-Type", "application/json");
    headers.put("X-Custom-Header", "application/json");
    headers.put("Access-Control-Allow-Origin", "*");
    headers.put("Access-Control-Allow-Methods", "GET, POST, OPTIONS, PUT, PATCH, DELETE");
    headers.put("Access-Control-Allow-Headers", "X-Requested-With,content-type");
  1. Add Option Cors into template.yaml
    Globals:
      Function:
        Timeout: 20
      Api:
        Cors:
          AllowMethods: "'GET,POST,OPTIONS'"
          AllowHeaders: "'content-type'"
          AllowOrigin: "'*'"
          AllowCredentials: "'*'"
  1. Update properties resource function in template.yaml
          Events:
            HelloWorld:
              Type: Api 
              Properties:
                # Path: /hello
                # Method: get
                Path: "/{proxy+}"
                Method: ANY
Bills answered 17/1, 2020 at 6:44 Comment(1)
you saved my day. My YAML was almost the same but in lamda I was missing the header so after adding the header it works for me.Kanishakanji
G
6

First, you will need to add the following section in the template.yml to enable cors in the API gateway:

Globals:
  Api:
    Cors:
      AllowMethods: "'GET,POST,OPTIONS'"
      AllowHeaders: "'content-type'"
      AllowOrigin: "'*'"
      AllowCredentials: "'*'"

Then in your lambda function response


        MultivaluedMap<String, Object> headers = responseContext.getHeaders();

        headers.add("Access-Control-Allow-Origin", "*");
        headers.add("Access-Control-Allow-Headers", requestContext.getHeaderString("Access-Control-Request-Headers"));
        headers.add("Access-Control-Allow-Methods", "GET,PUT,POST,DELETE,HEAD,OPTIONS");
Geter answered 20/1, 2020 at 0:53 Comment(1)
Thank you very much for the answer! Was having some trouble finding an answer to this yesterday.Piddle
A
4

You should be able to get around this for local testing by explicitly adding the following headers to your response, in your handler function:

    "Access-Control-Allow-Origin": "*"

You can use an environment variable that only adds the headers if you're running locally.

Here's a simple Python example from a handler function I have:

   if not all(field in values for field in required_fields):
    response = {
        'statusCode': 400,
        'body': json.dumps(
            {
                'message': 'Required data missing from request body'
            }
        )        
    }
    # explicitly add CORs headers for local testing
    response['headers'] = {"Access-Control-Allow-Origin": "*"}
    return response

This is only suitable for local testing, when you deploy to an API Gateway CORs is handled by configuration on the API Gateway.

This solution worked for me until I also added authorization to the API, with a Cognito user pool, which I'm currently trying to work through.

Here's a similar post on the issue: How to Enable CORS for an AWS API Gateway Resource

Here's reference to it in the official AWS documentation.

Anent answered 20/11, 2018 at 21:9 Comment(2)
Did you ever have any luck after adding the auth - I'm at the same point unfortunately.Maryrose
I am also at the point of adding the auth and I'm getting CORS errors. Did you ever have any luck?Jackleg
K
0

Try this on your serverless template file if you are using SAM

"Globals": {
    "Api": {
      "Cors": {
        "AllowMethods": "'POST, GET, PUT, DELETE'",
        "AllowHeaders": "'content-type'",
        "AllowOrigin": "'*'"
      }
    }
}
Koziarz answered 31/8, 2021 at 14:39 Comment(0)
F
0

Bit late to the party, but I've been struggling with this and found a solution. Hopefully will help someone else as well. I didn't want to polute my lambda code with additional, unsafe headers so looked into doing it within SAM.

I only use SAM for local development, not for deployment so this solution might not be for everyone as it requires changes to the template.

The solution to this is to use HttpApi in the SAM template instead of 'Api. I've added the following to the Globals section:

Globals:
  HttpApi:
    CorsConfiguration:
      AllowHeaders:
        - Content-Type
        - Authorization
        - Access-Control-Allow-Origin
      AllowMethods:
        - '*'
      AllowOrigins:
        - '*'

And then changed the Function resource to the HttpApi type:

MyFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: api/
      Handler: management.createHandler
      Runtime: nodejs20.x
      Architectures:
      - x86_64
      Events:
        HelloWorld:
          Type: HttpApi <-- Change here
          Properties:
            Path: /announcement
            Method: post

And now all responses when local start-api return the CORS headers.

One odd thing, I have many Functions defined in the template but I only had to change the Type on one of them to make the headers work for all.

Feedback answered 22/8 at 9:4 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.