AWS API Gateway 不存在“Access-Control-Allow-Origin”标头

Posted

技术标签:

【中文标题】AWS API Gateway 不存在“Access-Control-Allow-Origin”标头【英文标题】:AWS API Gateway No 'Access-Control-Allow-Origin' header is present 【发布时间】:2017-04-11 11:11:17 【问题描述】:

我被 API 网关的问题困住了,我已经阅读了有关此问题的所有其他 SO 答案,AWS 论坛,并阅读了他们的文档,但仍然没有乐趣。

我正在尝试使用 AWS API 网关设置一个 API,该网关调用一个读取/写入 DynamoDB 中表的 Lambda 函数。

DynamoDB 的 Lambda 函数正在运行。我在 AWS 中创建了一个 API,并为它创建了一个 GET 和 OPTIONS 方法。我读到 AWS 不会仅对 GET/POST 强制执行 OPTIONS,但是当没有 OPTIONS 方法时,我在 ajax 调用中遇到了预检错误,所以我添加了一个。

现在只是为了取得进展,我没有使用 API 密钥或授权。 我可以使用 POSTMAN 成功调用我的 GET 方法,该方法返回 DynamoDB 表的内容。

但是当我尝试使用 JQuery ajax 调用时,我得到了

No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'null' is therefore not allowed access.

我可以看到在网络选项卡下使用 Chrome 开发工具,OPTIONS 方法返回状态 200,GET 返回状态 200,但出现上述错误。

我尝试在 OPTIONS 和 GET 方法上启用 CORS,每次更改后都重新部署了 API,尝试了以下 (http://enable-cors.org/server_awsapigateway.html) 但在控制台中总是出现相同的错误。

我正在从桌面上的文件执行 ajax 调用,因此 origin 为 null,因为该页面将作为 JS 中的单个网页应用程序部署到 S3。

当我在我的 GET 和 OPTIONS 上启用 CORS 时,我可以看到 Access-Control-Allow-Headers 是 'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token' 而 Access-Control-Allow-Origin* 是 '*'

我的 Ajax 调用如下所示。我还尝试复制 POSTMAN 使用的确切标头,该标头设置了 Authorization 标头(我现在已在 AWS 中关闭)但我总是在上面得到相同的错误

var awsHeaders = ;
awsHeaders['X-Amz-Date'] = '20161127T171734';

$('#add, #cloud').click(function() 

    $.ajax(

        type: 'GET',
        headers: awsHeaders,
        dataType : "json",
        url: '...',
        success: function (res) 

            console.log('response in GET:');
            console.log(res);

        ,
        error: function(data) 
            console.log('in error');
            console.log(data);
        

    );

);

谁能解释一下我可能遗漏了什么?

非常感谢

更新 请参阅下面有关我如何根据 DigitalKapteain cmets 解决此问题的答案 - 通过在我的 Lambda 函数的响应中设置 'Access-Control-Allow-Origin':'*' 标头。我在 AWS 文档中查找了此内容,但找不到。此链接描述了 Lambda 和 Lambda Proxy 之间的区别,并说明了使用 CORS 时要做什么https://serverless.com/framework/docs/providers/aws/events/apigateway/

【问题讨论】:

这可能是您没有遗漏任何东西,也可能是 ISP 缓存问题,尝试不同的互联网连接和新的浏览器,如果没有,则可能是 CORS 问题 谢谢。我不认为这是一个 ISP 问题,因为我在不同的网络连接(咖啡馆、酒店等)上尝试过这个。还清除了缓存等并尝试了不同的浏览器 然后是它的 CORS @user12345 我想你已经看过这个文档,但试着仔细检查你是否再次完成了这些步骤,docs.aws.amazon.com/apigateway/latest/developerguide/… 谢谢@Waheedi。我已经关注了该文档,但我会再次仔细检查 嗨@Waheedi。重新阅读文档并根据下面的 Digitalkapitean anwser ,文档说“此外,实际启用 CORS 的方法还必须至少在其 200 响应中返回 Access-Control-Allow-Origin:'*' 标头。”因此,我在 API 网关的 GET 方法响应(200 响应)中添加了 Access-Control-Allow-Origin 标头,并重新部署了 API,但仍然看不到 GET 返回的此标头。知道还需要在哪里设置吗? 【参考方案1】:

对 Lambda 函数的 GET 请求的响应还必须包含 Access-Control-Allow-Originheader。

【讨论】:

感谢@Digitalkapitaen。查看从 OPTIONS 请求返回的响应标头,它包含 Access-Control-Allow-Methods:GET、OPTIONS 和 Access-Control-Allow-Origin:*,但我没有看到 Access-Control-Allow-Origin 响应标头GET 请求。我已经在 API 网关的 GET 方法方法响应中设置了它并重新部署了 API,但我没有看到它返回。知道还需要在哪里设置吗?非常感谢 @user12345 您是在使用 Lambda 代理集成还是在 API Gateway 中手动配置了 lambda 调用?如果您使用代理集成,您将在您的 Lambda 函数代码中设置标头。 我正在使用 Lambda 代理集成。所以我更改了 Lambda 函数以返回标题“Access-Control-Allow-Origin”:“*”,瞧,访问控制错误消失了。非常感谢您的帮助。那么在使用代理集成时,标头是由 Lambda 函数设置的,而不是 API 网关中的方法响应? @user12345 我在任何文档中都没有发现这一点,但实际行为表明应该在 Lambda 函数中设置标头。 说实话,使用集成不应该破坏 CORS 配置,因此浪费了很多时间,他们应该显示警告或其他东西。【参考方案2】:

Digitalkapitaen 的回答是正确的;这是省去查找how to set an HTTP response header in Lambda的麻烦的代码:

exports.handler = function(event, context, callback) 
    callback(null, 
        "statusCode": 200,
        "headers":  
            "Access-Control-Allow-Origin": "*" 
        
    );
;

【讨论】:

【参考方案3】:

如果这仍然不适合您,如果您使用 $.ajax,请确保 JSON.stringify() 您的 json 对象。如果不是,您仍然会收到一个声称是与 CORS 相关的错误的错误。但是如果你使用 Postman 发送相同的 json 对象,请求就会成功。试试看……

【讨论】:

这个。我看到了状态码 415,因为我发布的是表单数据而不是 JSON。虽然它在控制台中看起来像是一个与 CORS 相关的问题,但问题是这样的。【参考方案4】:

对于希望将@Digitalkapitaen 的解决方案集成到 Flask 中的人,代码如下:

app = Flask(__name__)
cors = CORS(app, resources=r"/*": "origins": "*")

@app.route("/")
def helloWorld():
  return "Hello, cross-origin-world!"

安装flask-cors模块:

pip install -U flask-cors

【讨论】:

【参考方案5】:

如果您只想更改一个标题而不是替换所有标题,如Words Like Jared 答案所示。您可以使用此代码:

'use strict';

module.exports.handler = (event, context, callback) => 
  const response = event.Records[0].cf.response;
  const headers = response.headers;

  headers['access-control-allow-origin'] = [ key: 'Access-Control-Allow-Origin', value: "*" ];

  return callback(null, response);
;

可以在Adding HTTP Security Headers Using Lambda@Edge and Amazon CloudFront 上找到其他示例。它适用于普通的 Lambda 函数。

【讨论】:

【参考方案6】:

我遇到了同样的问题:在 S3 中配置了一个网站并尝试在 API 网关中进行 ajax 调用。在 Lambda 代码中设置响应头后,在 API 网关中启用并部署 CORS 并得到相同的问题。

这是我的示例 Lambda 代码的 sn-p:

 let response = 
        statusCode: responseCode,
        headers: 
            "x-custom-header" : "my custom header value",
            "Access-Control-Allow-Origin": "*"
        ,
        body: JSON.stringify(responseBody)
    ;
    console.log("response: " + JSON.stringify(response))
    return response;

【讨论】:

以上是关于AWS API Gateway 不存在“Access-Control-Allow-Origin”标头的主要内容,如果未能解决你的问题,请参考以下文章

AWS API Gateway 集成响应

无服务器框架 AWS REST API Gateway - 403 CORS 错误

AWS API Gateway RestAPI CloudFormation 更新不更新部署资源

CloudFront 后面的 API Gateway 不支持 AWS_IAM 身份验证吗?

在 AWS API Gateway 中,我可以在不附加 API 密钥的情况下使用使用计划吗?

AWS API Gateway CORS 问题 - JS