Enabling Cors on API gateway

0

Hello,

I am practicing using SAM CLI to make and deploy Lambda functions as APIs. I am running into issues enabling CORS on the API gateway associated with my lambda function. I have tried both configuring CORS in my template.yaml file and going into the API gateway console and enabling CORS manually.

The lambda function is a simple hello world function that takes in 1 parameter which is a name and returns " {name} says hello world!". I have tested the api locally using a react app to invoke the api call and everything works fine. That is not the case for when its deployed to AWS.

Here is my template.yaml file:

AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: >
  apple-app Sample SAM Template for apple-app

# More info about Globals: 
Globals:
  Function:
    Timeout: 3
    MemorySize: 128

Resources:
  HelloWorldFunction:
    Type: AWS::Serverless::Function 
    Properties:
      CodeUri: hello_world/
      Handler: app.lambda_handler
      Runtime: python3.9
      Architectures:
        - x86_64
      Events:
        HelloWorld:
          Type: Api 
          Properties:
            Path: /hello
            Method: get
            RestApiId: !Ref AWS::ApiGateway::RestApi
            Cors:
              AllowMethods: "'GET, POST'"
              AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
              AllowOrigin: "'*'"

Outputs:
  HelloWorldApi:
    Description: "API Gateway endpoint URL for Prod stage for Hello World function"
    Value: !Sub "https://${ServerlessRestApi}.execute-api.${AWS::Region}.amazonaws.com/Prod/hello/"
  HelloWorldFunction:
    Description: "Hello World Lambda Function ARN"
    Value: !GetAtt HelloWorldFunction.Arn
  HelloWorldFunctionIamRole:
    Description: "Implicit IAM Role created for Hello World function"
    Value: !GetAtt HelloWorldFunctionRole.Arn

Am I configuring the implicit HelloWorld api correctly to enable CORS?

Since my configuration with the yaml file didn't work correctly. I tried manually enabling CORS by going into the API gateway console and clicking the button "Enable CORS and replace existing CORS headers". This is the response I get with an error:

✔ Add Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin Method Response Headers to OPTIONS method ✔ Add Access-Control-Allow-Headers, Access-Control-Allow-Methods, Access-Control-Allow-Origin Integration Response Header Mappings to OPTIONS method ✖ Add Access-Control-Allow-Origin Method Response Header to GET method ✖ Add Access-Control-Allow-Origin Integration Response Header Mapping to GET method Your resource has been configured for CORS. If you see any errors in the resulting output above please check the error message and if necessary attempt to execute the failed step manually via the Method Editor.

! The Empty Model does not exist, and retry resource creation without it.

I am not sure what I'm doing wrong, so any help would be greatly appreciated.

Thank you.

1 Answer
1

If you are using a Lambda custom (non-proxy) integration:

When you enable CORS by using the AWS Management Console, API Gateway creates an OPTIONS method and attempts to add the Access-Control-Allow-Origin header to your existing method integration responses. This doesn’t always work, and sometimes you need to manually modify the integration response to properly enable CORS. Usually this just means manually modifying the integration response to return the Access-Control-Allow-Origin header.

You may need to add OPTIONS to the AllowMethods in your template.yaml file:

Cors:
              AllowMethods: "'GET, POST, OPTIONS'"

If you are using a Lambda proxy integration or HTTP proxy integration:

Your backend is responsible for returning the Access-Control-Allow-Origin and Access-Control-Allow-Headers headers, because a proxy integration doesn't return an integration response.

You will need to ensure that your Lambda function returns the relevant headers:

import json

def lambda_handler(event, context):
    return {
        'statusCode': 200,
        'headers': {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': 'https://www.example.com',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        },
        'body': json.dumps('Hello from Lambda!')
    }

See: https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

profile pictureAWS
answered a year ago
  • Thank you for responding to my question.

    After some investigating, I learned that the SAM CLI templates performs a proxy lambda function. So I implemented the example lambda_handler and finally got a 200 response from my react app. With that said, I tried changing up the function by adding in a event['queryStringParameters']['name'] and returned that in the body, but Im getting CORS errors again. Is there something different I need to do with the parameters?

        # Retrieve name parameter from pathParameters
        name = event['queryStringParameters']['name']
    
        # Construct response body
        response_body = {'message': f'Hello, {name}!'}
    
        # Set headers for CORS
        headers = {
            'Access-Control-Allow-Headers': 'Content-Type',
            'Access-Control-Allow-Origin': '*',
            'Access-Control-Allow-Methods': 'OPTIONS,POST,GET'
        }
    
        # Construct response
        response = {
            'statusCode': 200,
            'headers': headers,
            'body': json.dumps(response_body)
        }
    
        return response

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions