brijesh chavda
brijesh chavda

Reputation: 81

AWS SAM configure cors to run locally

How can I configure cors to run lambda function locally

I have tried different ways but not able to get proper solution.

Below is my template.yml

Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: dev
      Cors:
        AllowHeaders: "'Content-Type,Authorization,Origin,X-Requested-With,Accept,x-id-token,x-custom-header'"
        AllowOrigin: "'*'"
        AllowMethods: "'OPTIONS,POST,GET,PUT,DELETE'"
        AllowCredentials: "'*'"
      Auth:
        AddDefaultAuthorizerToCorsPreflight: False
        DefaultAuthorizer: MyLambdaTokenAuthorizer
        Authorizers:
          MyLambdaTokenAuthorizer:
            FunctionArn: !GetAtt MyAuthFunction.Arn

  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: functions/hello/handler.hello
      CodeUri: "."
      Events:
        HelloAPI:
          Type: Api
          Properties:
            Path: /hello
            Method: GET
            RestApiId: !Ref MyApi

And this is my handler function

exports.hello = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Origin": "*", // Required for CORS support to work
            "Content-Type": "application/json",
            "Access-Control-Allow-Credentials": true, // Required for cookies, authorization headers with HTTPS
        },
        body: JSON.stringify({ message: "Hello World!" }),
    };

    callback(null, response);
};

still getting error:

 No 'Access-Control-Allow-Origin' header is present on the requested resource.

Upvotes: 1

Views: 1171

Answers (2)

Nim
Nim

Reputation: 33655

Going to answer this question for future reference due to really bad AWS documentation on API Gateway for CORS. Having battled with this shite for nearly three days, the end result is as follows.

First, in the AWS::Serverless::Api segment in your SAM template, configure CORS, for example:

    Type: AWS::Serverless::Api
    Properties:
      StageName: prod
      Cors:
        AllowHeaders: "'*'"
        AllowOrigin: "'*'"
        AllowCredentials: "'*'"
        AllowMethods: "'*'"

Next, create a stupid, dummy lambda to handle any OPTIONS request, make sure this lambda sets the headers on the response. Something like this:

export const handler = async (
  event: APIGatewayProxyEvent
): Promise<APIGatewayProxyResult> => {
  return {
    headers: {
      "Access-Control-Allow-Origin" : "*", // Required for CORS support to work
      "Access-Control-Allow-Headers" : "*", // Required for CORS support to work
      "Access-Control-Allow-Credentials" : true // Required for cookies, authorization headers with HTTPS
    },
    statusCode: 200
  };
}

Finally, in your SAM template, collect all the endpoints and point them to this stupid lambda.

  OptionHandler:
    Type: AWS::Serverless::Function
    Properties:
      Handler: <lambda above>
      Runtime: nodejs14.x
      Architectures:
        - arm64
      Timeout: 2
      Events:
        Method1APIOptions:
          Type: Api
          Properties:
            Path: /path/{param}
            Method: options
            RestApiId:
              Ref: ApiGatewayApi
        Method2APIOptions:
          Type: Api
          Properties:
            Path: /path2/{param}
            Method: options
            RestApiId:
              Ref: ApiGatewayApi
        Method3APIOptions:
          Type: Api
          Properties:
            Path: /path3/{params}
            Method: options
            RestApiId:
              Ref: ApiGatewayApi

Now every time you deploy this API using sam deploy, CORS will not be messed up.

Upvotes: 3

Shahar Yakov
Shahar Yakov

Reputation: 426

try this:

Resources:
  MyApi:
    Type: AWS::Serverless::Api
    Properties:
      StageName: dev
      Cors:
        AllowOrigin: "'*'"
        AllowHeaders: "'*'"
      Auth:
        AddDefaultAuthorizerToCorsPreflight: False
        DefaultAuthorizer: MyLambdaTokenAuthorizer
        Authorizers:
          MyLambdaTokenAuthorizer:
            FunctionArn: !GetAtt MyAuthFunction.Arn

  HelloFunction:
    Type: AWS::Serverless::Function
    Properties:
      Handler: functions/hello/handler.hello
      CodeUri: "."
      Events:
        HelloAPI:
          Type: Api
          Properties:
            Path: /hello
            Method: get
            RestApiId: !Ref MyApi
        HelloAPIOptions:
          Type: Api
          Properties:
            Path: /hello
            Method: options
            RestApiId: !Ref MyApi

I changed the cores policies and added a endpoint for OPTIONS /hello.

Upvotes: 0

Related Questions