【问题标题】:AWS API Gateway - CORS + POST not workingAWS API Gateway - CORS + POST 不起作用
【发布时间】:2016-12-23 13:23:33
【问题描述】:

CORS 真的让我发疯了,我真的不知道如何让它发挥作用。

我创建了一个简单的 APIG Api,其中包含 1 个名为“abc”的资源,并添加了 2 个方法 GETPOST 都将 Authorization 设置为NONEAPI Key Required 设置为 false,所有内容都部署到名为“dev”的阶段。

当然,我在这两种方法上都启用了 CORS,我看到了 3 个标题 Access-Control-Allow-OriginAccess-Control-Allow-Headers 和 Access-Control-Allow-Methods 添加到 OPTIONS 方法中,Access-Control-Allow-Origin 添加到 em>POSTGET 方法。

两个调用都映射到相同的 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 并且所有标头都在那里,但 POST 调用返回该错误和 400 Bad Request。

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

谢谢各位。


已编辑 - 从谷歌浏览器复制:

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 错误请求

OPTIONS 原始请求标头:

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

OPTIONS 原始响应标头:

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

【问题讨论】:

  • 嗨,我来自 api 网关。我认为您设置 api 的方式没有任何问题。你能更新原始请求吗?这将有助于调试。
  • 感谢您回复@AbhignaNagaraja - 我用谷歌浏览器中的标题更新了帖子(我刚刚隐藏了真实域名)。

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


【解决方案1】:

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

问题实际上在于我调用 jQuery.ajax 的方式,我认为它足够聪明,可以在 contentType 为 'application/json' 时将我的参数转换为 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 开发工具包并尝试使用 AWS 提供的 apigClient 执行调用,并将标头与您通过自定义客户端获得的标头进行比较。 在检查我使用 jQueryapigClient 获得的 2 组标头时,我注意到 Request Payload 看起来不同,这就是我意识到格式错误的原因,然后是 400 代码No 'Access-Control-Allow-Origin' 标头存在都是有意义的。

我希望这会有所帮助。

【讨论】:

  • “看来我必须手动对 JSON 参数进行字符串化,而不是传递 JSON 并让 jQuery 对其进行字符串化。”: 如果是 json,jquery 就不需要把它串起来。你传递的是一个对象,而不是json,并且jquery将任何不是字符串的东西转换为字符串(参数字符串)。通过对它进行字符串化,您将它变成了一个字符串,因此 jquery 没有触及它。
  • 谢谢,字符串化为我解决了同样的问题。
  • 所以无效的 JSON 有效负载会导致 APIG 响应中缺少 CORS 标头是否有意义?
  • 我知道这是两年多以前的事了,但是您还记得您是否使用过 lambda 代理集成吗?
  • 在调用 Lambda 时对 json 对象进行字符串化为我解决了这个问题。谢谢。不知道为什么它首先给出关于 CORS 的错误。
【解决方案2】:

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

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

【讨论】:

    【解决方案3】:

    我遇到了类似的问题,但使用了 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,如果您知道,请告诉我。

    【讨论】:

    • 这在使用 Lambda 代理集成时确实有效。谢谢!
    • 旁注,我还在我的 API Gateway 实例中的每个资源上启用了 CORS...函数产生。
    【解决方案4】:

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

    【讨论】:

    • 谢谢您,先生。你的这个回答对我帮助很大
    【解决方案5】:

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

    选项方法 - 集成响应 - 标头映射

    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
    

    希望对你有帮助

    【讨论】:

    • 遇到了同样的问题,问题是我从“使用 Lambda 代理集成”开始,它一开始就不允许这种映射。
    • 嗨,你有截图吗?标题是某种隐藏的
    • 这仅在您禁用“Lambda 代理集成”时有效。否则,标头应该作为 lambda 响应的一部分发送。
    • 正是我的朋友
    【解决方案6】:

    如果您在 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
    

    【讨论】:

    • 这是正确答案。为我工作了 Node 和 Python。谢谢!
    • 谢谢。我一定花了 20 个小时与这些东西作斗争。这是“it doesn't work with proxy integration”文档的更直接链接
    • 从一个车厘子到另一个车厘子。谢谢
    • 这很奇怪。为什么它不起作用?
    【解决方案7】:

    我也陷入了这个错误,经过挖掘,我发现在非2XX响应中,API没有在响应中给出Access-Control-Allow-Origin标头。因此,虽然 OPTION 方法和成功的 (2XX) 响应具有此标头,但 4XX5XX 没有。也可以使用 PostMan 并检查错误响应的标头来确认这一点。

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

    【讨论】:

      【解决方案8】:

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

      【讨论】:

      • 谢谢!我不敢相信这是问题所在......我的应用程序的所有端点都在工作,除了一个,结果证明是超时问题。
      • 欢迎 :)。此外,内存不足也会出现同样的问题。
      【解决方案9】:

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

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

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

      【讨论】:

        【解决方案10】:

        到了 2021 年,这里仍然存在 CORS 问题。 我的设置是 React App -> API Gateway -> Lambda Application -> Dynamo DB。我的 API 需要一个 apiKey。

        如果你一路走到这里,以上都不像我的。这就是我调试问题的方式:

        • 我在我的 GET 请求中启用了 CORS,这反过来又生成了一个 OPTIONS 方法。注意 OPTIONS 方法不应该需要 apiKey。

        • 为 API 网关启用 Cloudwatch 日志,我在其中看到了 requires API Key and API Key is not associated with a Usage Plan for API Stage

        • 在使用计划中添加了 apiKey。

        • 在 Postman 上同时调用 GETOPTION 方法来测试它是否正常工作。 (都获得状态 200 OK)

        • 注意到仍然出现此错误

        • 但在进一步检查标头后,我仅在我的 API 网关上启用了 CORS 时才允许使用特定标头

        也就是说,Access-Control-Allow-Headers 需要与你在实际请求中添加的 headers 相匹配

                   {
                        'Content-Type': 'application/json',
                        'X-API-Key': 'secret',
                        //'Access-Control-Allow-Origin': '*',
                    }
        

        我补充说:'Access-Control-Allow-Origin': '*' 从请求的角度来看实际上是导致 CORS 问题的原因,因为它不是默认允许标头的一部分。

        【讨论】:

          【解决方案11】:

          2021年10月,我尝试了以上所有方法并解决了

          • 创建一个空模型
          • Options > Method Response > Response Body for 200 > Add Response Model > ‘application/json’ 并选择 Empty Model created above

          【讨论】:

            猜你喜欢
            • 2021-03-31
            • 2021-09-15
            • 2017-03-02
            • 2018-07-16
            • 2018-01-13
            • 2017-09-19
            • 1970-01-01
            • 2020-02-20
            • 2017-04-09
            相关资源
            最近更新 更多