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

时间:2016-08-17 02:37:00

标签: api amazon-web-services cors aws-api-gateway

CORS 真的让我发疯,我真的没有想法让它变得有用。

我创建了一个名为'abc'的简单APIG Api,并添加了2个方法 GET POST ,并且授权设置为 NONE API Key Required 设置为 false ,所有内容都部署到名为“dev”的阶段。

当然我在两种方法上都启用了 CORS ,我看到3个标题 Access-Control-Allow-Origin Access-Control-Allow-Headers < / strong>和 Access-Control-Allow-Methods 添加到 OPTIONS 方法,并且 Access-Control-Allow-Origin 添加到< em> POST 和 GET 方法。

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

然后我在 S3 上创建了一个我作为静态网站托管的简单html页面,使用 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并且所有标题都在那里,但POST调用返回该错误和400 Bad Request。

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

谢谢你们。

已编辑 - 从Google Chrome复制:

POST Raw Request Headers:

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 Raw Response Headers:

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

9 个答案:

答案 0 :(得分:17)

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

这个问题实际上就是我调用jQuery.ajax的方式,我认为它足够智能,当contentType是&#39; application / json&#39;时,我的参数转换为JSON字符串。 看来我必须手动字符串化JSON参数而不是传递JSON并让jQuery对其进行字符串化。

所以这是不好的电话:

$.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代码 No&#39; Access-Control-Allow-Origin&#39; 标题都是有意义的。

我希望这会有所帮助。

答案 1 :(得分:12)

我有类似的问题,但使用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的代码中耦合CORS,如果你知道的话请告诉我。

答案 2 :(得分:3)

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

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

答案 3 :(得分:3)

如果您在API Gateway中使用代理集成,则无法从API Gateway启用CORS。您必须从Lambda代码本身设置标头“ Access-Control-Allow-Origin”。

它在doc中提到。

Python代码示例:

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

答案 4 :(得分:2)

解决此问题,我将在apy网关中提供Post配置的配置

选项方法 - 集成REsponse - 标题映射

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'

发布方法 - 集成响应 - 标题映射

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

我希望这有助于你

答案 5 :(得分:0)

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

答案 6 :(得分:0)

我也陷于此错误中,在挖掘之后,我发现在非2XX响应中,API没有在响应中提供Access-Control-Allow-Origin标头。因此,尽管OPTION方法和成功的(2XX)响应都具有此标头,但4XX5XX没有。也可以使用PostMan并检查不良响应的标头来确认这一点。

调整配置后,我确保在所有响应中都返回该标头。

答案 7 :(得分:0)

如果lambda超时很小,有时会发生CORS错误。

答案 8 :(得分:0)

到2020年,API网关CORS问题仍在寻找其他原因。对我来说(不使用lambda代理),即使在使用API​​下拉菜单启用CORS之后,甚至在我的Lambda函数的响应中添加了“ Access-Control-Allow-Origin”标头之后,我仍然收到CORS错误。

在默认网关响应中添加“ Access-Control-Allow-Origin”后,它为我解决了什么。在API网关用户界面的左侧菜单中,找到网关响应。选择“默认4XX”并对其进行编辑以包含“访问控制允许来源”。我将'*'的值设置为在测试期间完全开放(包括引号)。对“默认5XX”执行相同的操作。我的ajax调用能够传递CORS错误,现在我看到了真正的原因-我为该方法设置的必需参数未正确传递。

但是,我不知道为什么会出现CORS错误。