首页 文章

AWS API网关 - CORS POST无法正常工作

提问于
浏览
16

CORS 真的让我发疯了,我真的没有想法,试图让它发挥作用 .

我创建了一个简单的APIG Api,其中包含1个名为'abc'的资源,并添加了2个GET和POST方法,其中Authorization设置为NONE,API Key Required设置为false,所有内容都部署到名为'dev'的阶段 .

当然我在两种方法上都启用了 CORS ,我看到3个 Headers Access-Control-Allow-OriginAccess-Control-Allow-HeadersAccess-Control-Allow-Methods 添加到OPTIONS方法, Access-Control-Allow-Origin 添加到POST和GET方法 .

两个调用都映射到相同的lambda函数,该函数只是将'Hello from Lambda'文本输出到控制台 .

然后我创建了一个简单的html页面,我在 S3 上作为静态网站托管,使用 Route53 指向一个域并开始使用 jQuery $.ajax 测试API来进行调用 .

一切看起来都很简单,直截了当,正如文档中所解释的那样,除了GET工作并按预期将文本输出到控制台 . POST版本导致以下错误:

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://example.com' is therefore not allowed access. The response had HTTP status code 400.

预检调用工作并返回200 OK并且所有 Headers 都在那里,但POST调用返回该错误和400 Bad Request .

请任何帮助非常感谢,我希望AWS团队也在关注......

多谢你们 .


已编辑 - 从Google Chrome复制:

POST原始请求标头:

POST /dev/urls HTTP/1.1
Host: kykul1mshe.execute-api.us-east-1.amazonaws.com
Connection: keep-alive
Content-Length: 73
Accept: application/json, text/javascript, */*; q=0.01
Origin: http://example.com
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36
Content-Type: application/json
Referer: http://example.com/dev.html
Accept-Encoding: gzip, deflate, br
Accept-Language: fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4

POST原始响应标头:

HTTP/1.1 400 Bad Request
Date: Fri, 19 Aug 2016 02:14:16 GMT
Content-Type: application/json
Content-Length: 177
Connection: keep-alive
x-amzn-RequestId: a1160e45-65b2-11e6-9766-cd61e49fbcdb
X-Cache: Error from cloudfront
Via: 1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id: N9mf7apicKbSM_MiZjePbEgZGIFKckWJ3lZljH8iHVKFVTcIIOQuHg==

这将返回400 Bad Request

选项原始请求标头:

Accept:*/*
Accept-Encoding:gzip, deflate, sdch, br
Accept-Language:fr-FR,fr;q=0.8,en-US;q=0.6,en;q=0.4
Access-Control-Request-Headers:accept, content-type
Access-Control-Request-Method:POST
Connection:keep-alive
Host:kykul1mshe.execute-api.us-east-1.amazonaws.com
Origin:http://example.com
Referer:http://example.com/dev.html
User-Agent:Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/51.0.2704.103 Safari/537.36

选项原始响应标头:

Access-Control-Allow-Headers:Content-Type,X-Amz-Date,Authorization,X-Api-Key,Cache-Control,X-Requested-With
Access-Control-Allow-Methods:POST,OPTIONS
Access-Control-Allow-Origin:*
Connection:keep-alive
Content-Length:79
Content-Type:application/json
Date:Fri, 19 Aug 2016 02:14:16 GMT
Via:1.1 d64756b4df47ce24d6c62b5a8de97e87.cloudfront.net (CloudFront)
X-Amz-Cf-Id:KpGEDmIuf5RHcUnBWuA3oEMZgWHwrjy3SpLuOflRhAD8IIx5vyKGSw==
x-amzn-RequestId:a10bae11-65b2-11e6-bcf7-63b49c24629e
X-Cache:Miss from cloudfront

这返回200 OK

6 回答

  • 2

    如果您在API网关中使用代理集成,则从API网关启用CORS不起作用 . 您必须从Lambda代码本身设置Header'Access-Control-Allow-Origin' .

    它在doc中提到过 .

    Python代码示例:

    response = {
            'statusCode': 200,
            'headers': {
                'Access-Control-Allow-Origin': '*'
            },
            'body': json.dumps({'message': 'CORS enabled')
        }
        return response
    
  • 0

    好吧,我发现问题的根源,恰好与APIG完全无关,并确认了@AbhignaNagaraja提到的,我的APIG配置正确 .

    The issue is actually in the way I called jQuery.ajax, which I thought was smart enough to convert my parameters to a JSON string when contentType is 'application/json'. It seems I had to manually stringify the JSON params rather than passing a JSON and having jQuery stringify it.

    所以这是一个糟糕的电话:

    $.ajax({
            url: myEndpoint,
            type: 'POST',
            crossDomain: true,
            data: {
                url: $('#url').val()
            },
            headers: {
                "X-Api-Key": 'blablabla'
            },
            dataType: 'json',
            contentType: "application/json",
            success: function (data) {
                console.info(data);
            }
        });
    

    这是正确的电话:

    $.ajax({
            url: myEndpoint,
            type: 'POST',
            crossDomain: true,
            data: JSON.stringify({
                url: $('#url').val()
            }),
            headers: {
                "X-Api-Key": 'blablabla'
            },
            dataType: 'json',
            contentType: "application/json",
            success: function (data) {
                console.info(data);
            }
        });
    

    如果您正在使用CORS调试此问题,这可能是一个提示:只需下载AWS APIG SDK并尝试使用AWS提供的apigClient执行调用,并将标头与您在自定义客户端上获得的标头进行比较 . 在检查我使用jQuery和apigClient获得的两组头文件时,我注意到Request Payload看起来不同,这就是我如何意识到格式错误,然后 400 codeNo 'Access-Control-Allow-Origin' 头文件都是有意义的 .

    我希望这有帮助 .

  • 15

    我有一个类似的问题,但与lambda代理集成:

    • 使用浏览器在AWS API Gateway上激活CORS

    • lambda-proxy集成已激活

    使用lambda代理集成时,您可以从lambda代码中返回自定义标头:

    var result = {
            statusCode: data.statusCode | 200,
            headers: {
              "Access-Control-Allow-Origin": "*"
            },
            body: JSON.stringify(responseBody)
        };
        callback(null, result);
    

    这样就可以获得CORS标头了 . 我认为可能有更好的方法让它与lambda代理集成一起使用而不将lambda耦合到lambda的代码中,如果你知道的话请告诉我 .

  • 11

    我遇到了类似的问题 - 它与配置API的方式或我在前端发出的POST请求无关 . 解决这个问题的原因是在AWS API Gateway上部署API . 创建API方法/资源并将它们绑定到lambda函数后,它们不会自动部署 .

    您必须单击“操作”,然后单击“部署API”才能从前端访问这些MicroServices .

  • 0

    为了解决这个问题,我向你展示了我在apy网关中的Post配置的配置

    选项方法 - 集成REsponse - Headers 映射

    X-Requested-With '*'
    Access-Control-Allow-Headers 'Content-Type,x-requested-with,Access-Control-Allow-Origin,Access-Control-Allow-Headers,Access-Control-Allow-Methods'
    Access-Control-Allow-Origin 'http://localhost:4200'
    Access-Control-Allow-Methods 'POST,OPTIONS'
    

    Post方法 - 集成响应 - Headers 映射

    Access-Control-Allow-Origin "*" ---> can be changed by your ip obviously
    

    我希望这可以帮助你

  • 3

    有许多帖子指导您确保lambda函数返回相应的CORS标头,并且它们是正确的 . 但是,json对象使用JSON.stringify()进行字符串化也是 critical . 似乎Postman为我们做了这个,所以当Postman请求和$ .ajax请求发送相同的json对象时它会产生误导;然而一个成功,一个失败 .

相关问题