尽管已设置标头,但调用 API 网关仍返回 CORS 错误

MSO*_*ACC 1 amazon-web-services cors aws-lambda aws-api-gateway

我有一个与 Lambda 函数集成的 API 网关(HTTP 类型)。我试图从本地主机调用该函数,如下所示:

const jwt = getAuthToken();
const formBody = new FormData();
formBody.set('user', 'test');

const res = await fetch('https://example.execute-api.eu-west-1.amazonaws.com/default/GetShareValue', {
method: 'POST',
body: formBody,
headers: {
   'Authorization': jwt
   }
});
Run Code Online (Sandbox Code Playgroud)

但是,我收到此错误消息:

从源“http://localhost:3000”获取“https://example.execute-api.eu-west-1.amazonaws.com/default/GetShareValue”的访问已被 CORS 策略阻止:对预检的响应请求未通过访问控制检查:请求的资源上不存在“Access-Control-Allow-Origin”标头。如果不透明响应满足您的需求,请将请求模式设置为“no-cors”以在禁用 CORS 的情况下获取资源。

我了解不正确的 CORS 设置将阻止浏览器显示 Lambda 函数返回的内容。但是,我的 API 网关指定了 CORS 设置:

在此输入图像描述

根据此线程,在 Lambda 函数的响应中设置标头非常重要。我已将它们设置为相同。这是我的 Lambda 函数:

exports.handler = async (event, context) => {
    let body;
    let statusCode = '200';
    const headers = {
        'Content-Type': 'application/json',
        "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,X-Amz-Security-Token,Authorization,X-Api-Key,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers",
        "Access-Control-Allow-Origin": "*",
        "Access-Control-Allow-Methods": "*",
        "X-Requested-With": "*"
    };

try {
    body = "Success!!";
} catch (err) {
    statusCode = '400';
    body = err.message;
} finally {
    body = JSON.stringify(body);
}

return {
    statusCode,
    body,
    headers,
};
Run Code Online (Sandbox Code Playgroud)

};

我可以在 Postman 中调用这个端点- 它不关心 CORS - 所以我知道它正在工作。我开始认为这是 AWS 本身的一个错误。

MSO*_*ACC 6

为了@peter n 的利益回答我自己的问题。

最终我放弃了HTTP API Gateway。我相信 AWS 中存在一个错误,因为当我通过 REST API 触发它时,完全相同的 Lambda 函数起作用。这就是我所做的。

  1. 创建新的 API 网关
  2. 选择API网关的类型为REST API。我之前选择的是 HTTP。REST API 给了我们更多的控制权;HTTP API 很简单(而且便宜 70%)
  3. 在资源页面上,单击操作 > 创建资源
  4. 创建资源;如果您看到任何提及 CORS 的复选框,请选中它。我不记得这个阶段是否发生过这种情况。
  5. 然后单击操作 > 创建方法
  6. 选择除“任何”之外的任何方法(如 POST、GET 等)。这很重要 - 如果您选择“任何”,则会出现 CORS 的进一步问题。为什么?谁知道,AWS是一个用户不友好的平台。
  7. 一旦您配置了该方法并让它在您的 Lambda 函数(或您正在集成的任何函数)上触发,就可以使用 Postman 之类的东西来测试它,它不关心 CORS。
  8. 最后,要使 CORS 正常工作,请单击“操作”>“启用 CORS”

我输入了以下设置:

方法:邮寄

访问控制允许方法:选项、POST

访问控制允许标头:'内容类型、X-Amz-日期、X-Amz-安全令牌、授权、X-Api-Key、X-请求方式、接受、访问控制允许方法,访问控制允许来源,访问控制允许标头'

访问控制允许来源:'*'

然后单击“启用 CORS 并替换现有的 CORS 标头”。

你还没有完成。如果您的目标是 Lambda 函数,这仍然无法解决问题。您需要将 CORS 标头添加到 Lambda 的实际响应中。

这是我的 Lambda 的完整代码:

exports.handler = async (event, context) => {
   let body = JSON.stringify('Success!');
   let statusCode = '200';
   const headers = {
      'Content-Type': 'application/json',
      "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,X-Amz-Security-Token,Authorization,X-Api-Key,X-Requested-With,Accept,Access-Control-Allow-Methods,Access-Control-Allow-Origin,Access-Control-Allow-Headers",
      "Access-Control-Allow-Origin": "*",
      "Access-Control-Allow-Methods": "*",
      "X-Requested-With": "*"
   };
    
   return {
      statusCode,
      body,
      headers,
   };
};
Run Code Online (Sandbox Code Playgroud)

我不确定您在 Lambda 中返回的 CORS 设置与您在 AWS 控制台中应用的 CORS 设置是否相同是否重要。

这真是令人头疼,除非我做错了什么,AWS 在这方面的实现非常糟糕。

更新:在遇到进一步的问题后,我想我应该更新我的答案,指出您提出的请求似乎也会对 CORS 产生影响。我正在更改 API,CORS 错误又开始发生;最终,唯一的解决方案是删除我发送到 AWS 的请求中的一些标头。

这导致了 CORS 错误:

const res = await fetch('https://123.execute-api.eu-west-1.amazonaws.com/test', {
   method: 'POST',
   headers: {
      'Authorization': jwt,
      "Access-Control-Allow-Origin": "*" // This had to be removed to fix the CORS error
   }
});
Run Code Online (Sandbox Code Playgroud)

如您所见,我Access-Control-Allow-Origin在 API 的出站请求中进行了指定。这始终存在并且从未引起问题,但似乎现在我可以在请求中注释和取消注释该行并获取/不获取 CORS 错误。

更新 #2:进一步更新,以拯救那些可能为此而苦恼的人。在向现有 API 网关添加新的源和方法后,请务必单击,Actions > Deploy API以便您的更改真正生效。

AWS 确实需要清理 API Gateway 和 Lambda 的整个 UI。根本不清楚您是否有未发布的更改,或者是否需要发布;用户界面使任何更改看起来都立即生效。