2

I have encountered below error when I'm calling GET request in my frontend application
I tried to add the Access-Control-Allow-Origin: * to my template but it doesn't work.

Access to XMLHttpRequest at 'https://xxxxxx.execute-api.ap-southeast-1.amazonaws.com/dev/banner' from origin 'http://localhost:3000' has been blocked by CORS policy: Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource.

This is My lambda function for GET request(Updated according to comment but still not working)

'use strict'
const AWS = require('aws-sdk');

exports.handler = async function (event, context, callback) {
    const documentClient = new AWS.DynamoDB.DocumentClient();

    let responseBody = "";
    let statusCode = 0;

    const params = {
        TableName : "myTable",
    };

    try{
        const data = await documentClient.scan(params).promise();
        responseBody = JSON.stringify(data.Items);
        statusCode = 200
    }catch(err){
        responseBody = `Unabel to get products: ${err}`;
        statusCode = 403
    }

    const response = {
        statusCode: statusCode,
        headers:{
            "Content-Type": "application/json",
            'Access-Control-Allow-Origin': '*', // new line
            'Access-Control-Allow-Credentials': true, // new line
        body: responseBody
    }

    return response
}

This is My json template using cloudformation.

{
   "AWSTemplateFormatVersion": "2010-09-09",
         ...
   "Resources": {
         ...
     "getBannerHandler": {
       "Type": "AWS::Lambda::Function",
       "Properties": {
         "FunctionName": "getBanner",
         "Handler": "getBanner.handler",
         "Role": {
           "Fn::ImportValue": {
             "Fn::Sub": "${RolesStack}-LambdaRoleArn"
           }
         },
         "Code": {
           "S3Bucket": {
             "Ref": "HandlerCodeS3Bucket"
           },
           "S3Key":"getBanner.zip"
         },
         "Runtime": "nodejs12.x"
       }
     },
     "HelloWorldApi": {
       "Type": "AWS::ApiGateway::RestApi",
       "Properties": {
         "Name": "hello-api",
         "Description": "API used for practice",
         "FailOnWarnings": true
       }
     },
     "getBannerMethod": {
       "Type": "AWS::ApiGateway::Method",
       "DependsOn": ["HelloWorldApi"],
       "Properties": {
         "RestApiId": {
           "Ref": "HelloWorldApi"
         },
         "ResourceId": {
           "Ref": "BannerResource"
         },
         "HttpMethod": "GET",
         "MethodResponses":[
           {
             "ResponseModels" : {"application/json" : "Empty"},
             "ResponseParameters":{
               "method.response.header.Access-Control-Allow-Origin": "'*'"
             },
             "StatusCode" : "200"
           },
           {
             "StatusCode": "500"
           }
         ],
         "AuthorizationType": "NONE",
         "Integration": {
           "Credentials": {
             "Fn::ImportValue": {
               "Fn::Sub": "${RolesStack}-ApiGatewayRoleArn"
             }
           },
           "IntegrationHttpMethod": "POST",
           "IntegrationResponses": [{ 
             "ResponseParameters":{
                            "method.response.header.Access-Control-Allow-Origin": "'*'"
                          },  
              "StatusCode" : "200"
            }],
           "Type": "AWS_PROXY",
           "Uri": {
             "Fn::Join": ["",
               [
                 "arn:aws:apigateway:",
                 {
                   "Ref": "AWS::Region"
                 },
                 ":lambda:path/2015-03-31/functions/",
                 {
                   "Fn::GetAtt": ["getBannerHandler", "Arn"]
                 },
                 "/invocations"
               ]
             ]
           }
         }
       }
     }
   }
 }

How to deal with this kind of problems? I find I always encounter this kind of problem.

Update: my API Gateway enter image description here

CCCC
  • 5,665
  • 4
  • 41
  • 88

2 Answers2

1

If you want to use CORS with the lambda/aws-proxy integration, remember to include the Access-Control-Allow-* headers in your headers object.

e.g

'use strict';

module.exports.hello = function(event, context, callback) {
  const response = {
    statusCode: 200,
    headers: {
      'Access-Control-Allow-Origin': '*', // Required for CORS support to work
      'Access-Control-Allow-Credentials': true, // Required for cookies, authorization headers with HTTPS
    },
    body: JSON.stringify({ message: 'Hello World!' }),
  };

  callback(null, response);
};

ref: https://www.serverless.com/framework/docs/providers/aws/events/apigateway/

0

Another workaround is to deactivate the checkbox of Lambda Proxy integration and manually provide a Mapping template for application/json response like:

#set($payload = $util.parseJson($input.json('$')))
#set($context.responseOverride.status = $payload.statusCode)
$payload.body

The advantage or this workaround is that it propagates to all endpoints. No need to change/add code in lambdas.

If you also need to read GET parameters, check out this post.

Leopoldo Varela
  • 257
  • 3
  • 9