【问题标题】:Getting multiple CORS errors while using POST API使用 POST API 时出现多个 CORS 错误
【发布时间】:2019-12-28 20:05:26
【问题描述】:

我在尝试通过 POST 请求上传图像时遇到多个 CORS 错误。我在 AWS API Gateway 上创建了一个 POST API,它触发了一个用 Node js 编写的 lambda 函数。该 API 可以与 Postman 一起正常工作,因为它允许 CORS,但在不同的浏览器上会出现多个错误。

错误如下:-

  • 在 Firefox 上

  • 在 Chrome 上

以下是请求标头:-

Method request headers: {
        sec - fetch - mode = cors,
        sec - fetch - site = cross - site,
        accept - language = en - US,
        en;q = 0.9,
        hi;q = 0.8,
        access - control - allow - headers = Origin,
        X - Requested - With,
        Content - Type,
        Accept,
        Authorization,
        origin = null,
        User - Agent = Mozilla / 5.0(Windows NT 10.0; Win64; x64) AppleWebKit / 537.36(KHTML, like Gecko) Chrome / 76.0 .3809 .100 Safari / 537.36,
        X - Forwarded - Proto = https,
        Host = xxxxxxx.execute - api.us - east - 2. amazonaws.com,
        X - Forwarded - Port = 443,
        X - Amzn - Trace - Id = Root = 1 - 5 d5fd816 - 4 c1ac880ed09a50047ecda00,
        accept = * /*, access-control-allow-origin=*, X-Forwarded-For=103.97.240.210, content-type=application/json, accept-encoding=gzip, deflate, br}

Chrome 上的请求标头

以下是**响应标头:-**

Endpoint response headers: {
    Date = Fri,
    23 Aug 2019 12: 12: 07 GMT,
    Content - Type = application / json,
    Content - Length = 1077,
    Connection = keep - alive,
    x - amzn - RequestId = 46 a264c2 - 44 d7 - 4026 - 9168 - f227e758f078,
    X - Amz - Function - Error = Unhandled,
    x - amzn - Remapped - Content - Length = 0,
    X - Amz - Executed - Version = $LATEST,
    X - Amzn - Trace - Id = root = 1 - 5 d5fd816 - 4 c1ac880ed09a50047ecda00;sampled = 0
}

邮递员的响应标头

下面是我的代码 客户端:index.html

<body>

<form method="post" enctype="application/json">

    Enter the Employee Id: <input type="text" name="empId"><br>
    Upload the Employee Photo: </h2><input type="file" name="PhotoName"> <br>
    <input type="submit" name="PhotoContent" value="Upload Photo"><br><br>
</form>
</div>

 <script src="upload.js"></script>

</body>

客户端:upload.js

const url = 'https://xxxxxxx.execute-api.us-east-2.amazonaws.com/test/upload';
const form = document.querySelector('form');

form.addEventListener('submit', e => {
    e.preventDefault();

    const files = document.querySelector('[type=file]').files;


    const reader = new FileReader() 
    reader.onload = handleFileLoad;
    reader.readAsBinaryString(files[0]);
    for (let i = 0; i < files.length; i++) {
        let file = files[i];
        console.log(file);

    }

});

function handleFileLoad(event){ 
    console.log(event);
    let formData = new FormData();
    formData.append('data', event.target.result);
    console.log('final file ', formData.get('data'));

    let data = {
        "fileName" : 'tmp123',
        "user_avatar" : event.target.result
    };

    fetch(url, {
        method: 'POST',
        body: JSON.stringify(data),
        headers : {
            'Origin' : 'https://xxxxxxx.execute-api.us-east-2.amazonaws.com/test/upload',
            'content-type' : 'application/json',
            'Access-Control-Allow-Origin' : '*',
            'Access-Control-Allow-Headers' : 'Origin, X-Requested-With, Content-Type, Accept, Authorization',
        },
    }).then(response => {
        console.log(response);
    });
}

服务器端(lambda):index.js

const AWS = require('aws-sdk');
const { parse } = require('querystring');
var s3 = new AWS.S3();
exports.handler = (event, context, callback) => {   
    if (event.method === 'POST') {
    let body = '';
    event.on('data', chunk => {
        body += chunk.toString();
    });
    req.on('end', () => {
        console.log(
            parse(body)
        );
        res.end('ok');
    });
}
    //  var event = '{ "user_avatar": "asas" }' ;

    let encodedImage = JSON.parse(event.body).user_avatar;
    let decodedImage = Buffer.from(encodedImage, 'base64');
    //  var filePath = "avatars/" + event.queryStringParameters.username + ".jpg"
     var filePath = JSON.parse(event.body).file_name

     var params = {
       "Body": decodedImage,
       "Bucket": "test-bkt-rahul",
       "Key": filePath  
    };
    s3.upload(params, function(err, data){
       if(err) {
           callback(err, null);
       } else {
           let response = {
        "statusCode": 200,
        "headers": {
            "Access-Control-Allow-Origin": ""
        },
        "body": JSON.stringify(data),
        "isBase64Encoded": false
    };
           callback(null, response);
    }
    });

};

任何建议将不胜感激。提前致谢。

【问题讨论】:

  • CORS 标头应该在服务器端设置。尝试将 'Access-Control-Allow-Origin' : '*''Access-Control-Allow-Headers' : 'Origin, X-Requested-With, Content-Type, Accept, Authorization' 添加到服务器的响应中。
  • 嗨@Teh,即使在将上述标头添加到服务器端Node js代码之后,我仍然遇到同样的错误。
  • @Teh 我还有一个疑问是,如果我已经在 OPTIONS 方法上启用了 CORS 标头,我是否还必须为同一资源下的 POST 方法添加相同的标头?因为目前,我已经在 OPTIONS 方法上启用了 CORS,并且还从 POST 方法的 Node Js 代码发送了相同的标头。它会在标题中产生冲突吗?

标签: node.js post aws-lambda cors aws-api-gateway


【解决方案1】:

将 Access-Control-Allow-Oriigin 设置为 null 将禁止所有来源。改为将其设置为 *

"headers": {
            "Access-Control-Allow-Origin": "*"
        },

【讨论】:

  • 我已经在服务器端和客户端代码中添加了 "Access-Control-Allow-Origin": "*" 标头。我仍然收到相同的 CORS 错误。
  • 您发布的代码另有说明,但没关系。客户端不需要它,它是一个响应头。
【解决方案2】:

终于,问题解决了。

  • 我收到了 403 响应代码,因为我使用了不正确的端点。
  • 我收到 CORS 错误,因为我的服务器端代码没有进行异常处理。异常情况下,代码未在响应中发送 CORS 标头。

【讨论】:

    【解决方案3】:

    您需要为您的资源创建一个 OPTIONS 方法,并使用一个 MOCK 响应将这些标头发回,并在 API 网关上允许这些标头。如果您在 api gateway 上选择您的资源并单击顶部下拉菜单,单击启用 cors,它将为您设置该资源/方法,并带您完成一个直观的工作流程,以允许这些并在它们之间来回传递它们的值客户端和您的后端(在本例中为 lambda)。

    您还可以指定允许的方法,'*' 或子集('GET,POST')

    试试这些:

    "Access-Control-Allow-Methods": "'*'",
    "Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
    "Access-Control-Allow-Origin": "'*'"
    

    AWS API Gateway CORS 文档https://docs.aws.amazon.com/apigateway/latest/developerguide/how-to-cors.html

    【讨论】:

    • 感谢您的回复。我在创建 API 时启用了 CORS,并且当时还创建了 OPTIONS 方法。我已尝试根据您的建议更新 OPTIONS 方法标头,但它仍然给出相同的错误。但是当我从浏览器调用 API 时,我只看到 POST 方法而不是 OPTIONS 方法。还好吗?
    • 我还在 POST 请求中看到 403 响应代码,在 Firefox 上带有响应 - {"message":"Missing Authentication Token"},在 Chrome 上没有响应。我认为这不是身份验证问题,因为我可以在没有令牌的情况下从邮递员访问 API。
    • 我还有一个疑问是,如果我已经在 OPTIONS 方法上启用了 CORS 标头,我是否还必须为同一资源下的 POST 方法添加相同的标头。因为目前,我已经在 OPTIONS 方法上启用了 CORS,并且还从 POST 方法的 Node Js 代码发送标头。
    • 奇怪。您能否发布选项和发布方法的请求方法配置?我会尝试在舞台上启用 CloudWatch 访问日志,然后尝试从浏览器和邮递员访问 API 端点几次,然后发布这些。
    • 我已启用 CloudWatch 日志。问题已解决。以前,我收到了 403 响应代码,因为我使用了不正确的端点。即使在更正它之后,我也收到了 CORS 错误,因为我的服务器端代码没有进行异常处理。出错时,它没有发送 CORS 标头。感谢您的帮助。
    猜你喜欢
    • 2018-04-01
    • 1970-01-01
    • 1970-01-01
    • 2016-06-10
    • 2021-12-13
    • 2020-09-07
    • 2018-04-07
    • 1970-01-01
    • 2017-10-17
    相关资源
    最近更新 更多