触发 API 网关端点时 COR 配置错误

Posted

技术标签:

【中文标题】触发 API 网关端点时 COR 配置错误【英文标题】:CORs misconfigured while triggering API Gateway endpoint 【发布时间】:2020-01-05 03:21:48 【问题描述】:

我正在尝试使用 AJAX 从我的网站触发 AWS API Gateway 上的 API。我的 API Gateway 触发了 Lambda。我在 S3 上托管了我的网站。

我的 AJAX 代码如下所示:

$.ajax(
  type: "POST",
  url: api-gateway-api-endpoint-goes-here,
  data: str,
  dataType: 'json',
  contentType: 'application/json',
  crossDomain: true,
  headers: 
    'Access-Control-Allow-Origin': "*",
    'Access-Control-Allow-Credentials': 'true',
    'Access-Control-Allow-Methods': 'OPTIONS,POST',
    'Access-Control-Allow-Headers': 'access-control-allow-origin'
  ,
  success: function(msg) 
      // blah blah
  
);

lambda 处理程序看起来有点像这样:

def lambda_handler(event, context):
    # call SES send-email API
    aws_ses_response = ses_client.send_email(
        Source=blah,
        Destination=blah,
        Message=blah
    )

    return 
        'response': aws_ses_response
    

我已经在 API Gateway 上的 API 端点上“启用”了 CORS。我将access-control-allow-origin 添加为Integration ResponseAccess-Control-Allow-Headers 映射中的值之一。

触发此 AJAX 调用时,我仍然看到此错误:

Access to XMLHttpRequest at 'https://xxxxxxx.execute-api.xxxxx.amazonaws.com/dev/my-api' from origin 'http://www.my-website.com' has been blocked by CORS policy: Request header field access-control-allow-origin is not allowed by Access-Control-Allow-Headers in preflight response.

当我从终端从 cURL 触发 API 时,它工作正常。

我错过了什么?谢谢。

附:我在这里查看了一些类似的问题,但没有一个建议有效。所以,再次在这里发布。

--

更新:在遵循@hephalump 的建议后,我能够触发我的 API,只是 API 响应似乎没有传播回网站(托管在 S3 上)。我在发送 AJAX POST 请求后“检查”我的网站时看到此错误:

【问题讨论】:

您的 API 是否触发了 Lambda? @hephalump - 是的 你能发布你的 Lambda 代码吗? @hephalump - 我刚刚用 lambda 代码更新了我的问题。基本上我正在调用 AWS SES api 并从我的 lambda 返回来自该 API 的响应。 昨晚我从字面上回答了同样的问题,显然是同样的问题,而 OP 似乎已经删除了它。我会再写回复。 【参考方案1】:

查看错误信息:

请求头域 access-control-allow-origin 不允许

现在看看你的请求:

  headers: 
    'Access-Control-Allow-Origin': "*",
    'Access-Control-Allow-Credentials': 'true',
    'Access-Control-Allow-Methods': 'OPTIONS,POST',
    'Access-Control-Allow-Headers': 'access-control-allow-origin'
  ,

您正在尝试为您的请求设置权限。

如果您的 javascript 可以允许自己访问它喜欢的任何服务,那将是完全愚蠢的。这意味着这些标题是废话

由于它们是无稽之谈,它们不在跨域请求的可接受标头列表中,因此服务器需要明确授予您设置它们的权限……但它没有。

停止尝试设置它们。

Access-Control-* 标头需要由服务器设置。

请参阅Amazon's own documentation,其中明确涵盖了这一点。

【讨论】:

【参考方案2】:

当使用启用了 API 网关和 CORS 的 Lambda 代理集成时,您的浏览器会期望在响应中返回 CORS 标头。目前,您正在返回 ses_client.send_email 的结果,如果它只是原始 SES sendEmail 原始响应,它将类似于:


    "ResponseMetadata": 
      "RequestId": "99aaaaa9-a9aa-9999-aa99-744d6b6ede3c"
    ,
    "MessageId": "0100000aa0a00a0a-715e3e9e-e010-43c1-a91f-0492d75aa64c-000000"
  

正如我们所见,这不包括浏览器所需的 CORS 标头。要解决此问题,首先构建 aws_ses_response 的结果以包含 HTTP 状态代码和相应的标头,然后将完整的响应返回给调用者。修改您的代码如下,它应该可以工作:

    aws_ses_response = ses_client.send_email(
        Source=blah,
        Destination=blah,
        Message=blah
    )

    const result = 
        statusCode: 200,
        headers: 
            'Access-Control-Allow-Origin': '*',
            // other required headers
        ,
        body: aws_ses_response
    ;

    return result;

此外,尽管您的 API 网关的配置对我来说并不完全清楚,但对于您的请求,您可以删除标头和跨域属性(可能还有其他属性)。在新的 APIG 端点上对此进行测试时,我只是在没有这些的情况下向 API 发出请求,并且能够获得成功的响应(我的响应主体是我为原始 SES sendEmail 响应提供的示例)。

【讨论】:

现在我可以调用我的 lambda 函数并且可以发送电子邮件了。 (是的!)。但是,我无法回复我的网站(托管在 S3 上)。我在响应中看到此错误: 从源“MY-SITE”访问“MY-APIG-ENDPOINT”处的 XMLHttpRequest 已被 CORS 策略阻止:请求的资源上不存在“Access-Control-Allow-Origin”标头.跨域读取阻塞 (CORB) 阻止了 MIME 类型为 application/json 的跨域响应 My-APIG-ENDPOINT。有关详细信息,请参阅chromestatus.com/feature/5629709824032768。 刚刚贴在上面的回复里。 您是否从请求中删除了标头? 是的,我从 ajax 请求中删除了标头和“crossDomain”。API 调用得很好。只是我的网站无法得到响应。谢谢。

以上是关于触发 API 网关端点时 COR 配置错误的主要内容,如果未能解决你的问题,请参考以下文章

作为提供者的 502 错误网关错误

对 Kong api 网关端点的基本身份验证请求出现 CORS 错误并且未找到预检

我无法创建网关 API Google 错误:“无法转换为服务配置。”位置:“未知位置”

通过 API 网关为无服务器架构模型代理端点设置 CORS

在 Vercel 上部署的 Nextjs 中的 api 请求出现 504/502 错误

如何使用 cognito 验证我的 api 网关?