简体   繁体   中英

CORS on AWS API Gateway and S3

I am calling an AWS API which uses lambda function. I am calling it from a HTML page which is hosted in S3 (static web hosting). While calling the API I get CORS error:

Access to XMLHttpRequest at '' from origin '' has been blocked by CORS policy: No 'Access-Control-Allow-Origin' header is present on the requested resource.

I have tried it after enabling CORS on API, Specifying CORS on S3 bucket but it is not working. Seems, I am missing the right place where CORS headers are to be specifies.

Additional information: I get following information in chrome developer tool

**Response Headers**
content-length: 42
content-type: application/json
date: Mon, 24 Feb 2020 04:28:51 GMT
status: 403
x-amz-apigw-id: IYmYgFQvoAMFy6Q=
x-amzn-errortype: MissingAuthenticationTokenException
x-amzn-requestid: 79b18379-383d-4ddb-a061-77f55b5727c3

**Request Headers**
authority: apiid-api.us-east-1.amazonaws.com
method: POST
path: /Prod
scheme: https
accept: application/json, text/javascript, */*; q=0.01
accept-encoding: gzip, deflate, br
accept-language: en-US,en;q=0.9,hi;q=0.8
access-control-allow-headers: Origin, X-Requested-With, Content-Type, Accept, Authorization
access-control-allow-methods: GET, OPTIONS
access-control-allow-origin: https://apiid.execute-api.us-east-1.amazonaws.com/Prod
content-length: 117
content-type: application/json; charset=UTF-8
origin: http://example.com
referer: http://example.com/
sec-fetch-mode: cors
sec-fetch-site: cross-site
user-agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/79.0.3945.130 Safari/537.36

Lambda function code:

var AWS = require('aws-sdk');
var ses = new AWS.SES();

var RECEIVER = 'example@gmail.com';
var SENDER = 'example@gmail.com';

var response = {
 "isBase64Encoded": false,
 "headers": { 'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'},
 "statusCode": 200,
 "body": "{\"result\": \"Success.\"}"
 };

exports.handler = function (event, context) {
    console.log('Received event:', event);
    sendEmail(event, function (err, data) {
        context.done(err, null);
    });
};

function sendEmail (event, done) {
    var params = {
        Destination: {
            ToAddresses: [
                RECEIVER
            ]
        },
        Message: {
            Body: {
                Text: {
                    Data: 'name: ' + event.name + '\nphone: ' + event.phone + '\nemail: ' + event.email + '\ndesc: ' + event.desc,
                    Charset: 'UTF-8'
                }
            },
            Subject: {
                Data: 'Website Referral Form: ' + event.name,
                Charset: 'UTF-8'
            }
        },
        Source: SENDER
    };
    ses.sendEmail(params, done);
}

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

This is saying that the resource you requested, your Lambda via API Gateway, is not returning an Access-Control-Allow-Origin header in its response; the browser is expecting the CORS headers in the response from the API (possibly because of an OPTIONS request), but the response doesn't have them.

You've not said so specifically but I'm assuming you're using a Lambda proxy integration on your API gateway. To solve your issue, add a Access-Control-Allow-Origin: * header to the response your Lambda returns. You've not specified the language your Lambda is written in, or provided your Lambda code, but if it was in NodeJS, a snippet of what you'd return might look something like:

    const result = {
        statusCode: 200,
        headers: {
            'Access-Control-Allow-Origin': '*',
            // other required headers
        },
        body: object_you_are_returning
    };

    return result;

Very surprisingly, the reason seems to be “the client-side shouldn't have 'Access-Control-Allow-Origin': '*'. That should only be in the Lambda code, apparently, and adding it to the jQuery code will cause the preflight to fail for some reason.” https://github.com/serverless/serverless/issues/4037#issuecomment-320434887

Supplement information following the comment:

I also tried to use ajax hosted in S3 to call my Lambda function through API Gateway. I have tried many suggestions especially this solution ( http://stackoverflow.com/a/52683640/13530447 ), but none of them works for me. In the developer-mode of Chrome, I kept seeing the error "Access to XMLHttpRequest at '[my API]' from origin '[my S3 website]' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response." I solved this by removing 'Access-Control-Allow-Origin': '*' in ajax. Still take the solution ( http://stackoverflow.com/a/52683640/13530447 ) as an example, it will work by changing

$.ajax(
{
    url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
    headers: {'Content-Type': 'application/json', 'Access-Control-Allow-Origin': '*'
},
    crossDomain: true,
    type:'GET',
    dataType: 'text',
    success: function(data)
    {
        window.alert(data);
    }
}); 

into

$.ajax(
{
    url: 'https://npvkf9jnqb.execute-api.us-east-1.amazonaws.com/v1',
    headers: {'Content-Type': 'application/json'},
    crossDomain: true,
    type:'GET',
    dataType: 'text',
    success: function(data)
    {
        window.alert(data);
    }
});

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM