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

HBR*_*HBR 20 api amazon-web-services cors aws-api-gateway

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

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

当然,我在两种方法上都启用了CORS,我看到在OPTIONS方法和Access-Control-Allow-中添加了3个标题Access-Control-Allow-Origin,Access-Control-Allow-HeadersAccess-Control-Allow-Methods Origin添加到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团队也在关注......

多谢你们.


已编辑 - 从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
Run Code Online (Sandbox Code Playgroud)

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==
Run Code Online (Sandbox Code Playgroud)

这将返回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
Run Code Online (Sandbox Code Playgroud)

选项原始响应标头:

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
Run Code Online (Sandbox Code Playgroud)

这返回200 OK

HBR*_*HBR 18

好吧,我发现问题的根源,恰好与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);
        }
    });
Run Code Online (Sandbox Code Playgroud)

这是正确的电话:

 $.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);
        }
    });
Run Code Online (Sandbox Code Playgroud)

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

我希望这有帮助.

  • 因此,对于无效的JSON有效负载而言,在APIG响应中导致缺少CORS标头是否有意义? (2认同)

小智 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);
Run Code Online (Sandbox Code Playgroud)

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


mel*_*ngs 9

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

如果你一路走到这里,上面的方法都不像我的那样有效。这是我调试问题的方式:

  • 在 GET 请求上启用了 CORS,这又生成了一个OPTIONS方法。请注意,OPTIONS 方法不应需要 apiKey。

  • 为 API Gateway 启用 Cloudwatch Logs,我在其中看到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 需要与您在实际请求中添加的标头相匹配

           {
                'Content-Type': 'application/json',
                'X-API-Key': 'secret',
                //'Access-Control-Allow-Origin': '*',
            }
Run Code Online (Sandbox Code Playgroud)

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

  • 这个应该更高。AWS 文档中从未明确说明答案是从我的代码中删除这些标头。总是声明要确保一切都相同。这非常有效。 (2认同)

Chr*_*ith 6

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

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

然而,我不知道为什么会出现 CORS 错误。


Daw*_*ian 5

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

它在文档中提到。

Python代码示例:

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


Abh*_*hek 5

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

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