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?

Eddie Martinez
  • 13,582
  • 13
  • 81
  • 106

4 Answers4

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
ngoctrambui
  • 141
  • 1
  • 4
  • 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. – Nirmal May 01 '20 at 23:17
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");
me2resh
  • 786
  • 6
  • 10
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.

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": "'*'"
      }
    }
}
CyborgHead
  • 11
  • 1
  • 7