首页 > 解决方案 > 修复 AWS API 网关不存在的 CORS“对预检的响应 ...”标头并放大

问题描述

我一直在为下面的错误苦苦挣扎。我已经尝试了很多教程和 stackoverflow 答案,但没有一个解决方案可以解决我的问题。

从源“ http://localhost:3000 ”访问“ https://xxx ”的 XMLHttpRequest已被 CORS 策略阻止:对预检请求的响应未通过访问控制检查:没有“访问控制允许来源” ' 请求的资源上存在标头。

我正在使用 SAM 无服务器来创建我的 api。

模板.yaml:

Globals:
  Function:
    Timeout: 10
  Api:
    Cors:
      AllowMethods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
      AllowHeaders: "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
      AllowOrigin: "'*'"

我的 lambda 函数: 我的 GET 响应和 OPTIONS 响应都返回以下标头:

headers: {
  "Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
  "Access-Control-Allow-Origin": "'*'",
  "Access-Control-Allow-Methods": "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
}

我的 API 使用放大进入我的 ReactJs 应用程序:

API.get(apiName, path, {
   headers: {
      "Access-Control-Allow-Origin": "*",
      // "Access-Control-Allow-Headers": "Content-Type,X-Amz-Date,Authorization,X-Api-Key,x-requested-with",
      // "Access-Control-Allow-Methods": "OPTIONS,POST,GET,PUT,DELETE",
      // 'Content-Type': 'application/json'
   }
})

我已经在我的 template.yaml、我的 lambda 函数和我的 reactJs 项目中尝试了 Access-Control-Allow-Headers、Access-Control-Allow-Methods 的所有组合。

这是我在 API 端点上调用 postman 中的选项时的结果。因此,我确实得到了正确的标头,因此根据我的理解,我的 API 允许 CORS。 在此处输入图像描述

标签: javascriptamazon-cloudformationaws-api-gatewayaws-serverlesssam

解决方案


因此,在与@Jannes Botis 进行了非常有益的讨论后,我找到了解决方案。

在 template.yaml 中,我将值更改为:

Globals:
  Function:
    Timeout: 10
  Api:
    Cors:
      AllowMethods: "'DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT'"
      AllowHeaders: "'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'"
      AllowOrigin: "'*'"

  MyAPIFunction:
    Type: AWS::Serverless::Function
    Properties:
      CodeUri: myendpoint/
      Handler: app.lambdaHandler
      Runtime: nodejs12.x
      Events:
        GetMyData:
          Type: Api
          Properties:
            RestApiId: !Ref MyApi
            Path: /myendpoint
            Method: get
        Options:
          Type: Api
          Properties:
            RestApiId: !Ref MyApi
            Path: /myendpoint
            Method: options
            Auth:
              ApiKeyRequired: false

注意:您将收到错误消息“请求的资源上不存在‘xxx’标头。” 其中 xxx 是 Access-Control-Allow-Methods、Access-Control-Allow-Origin 和 Access-Control-Allow-Headers,因此您需要将它们添加到 AllowHeaders 中。另请注意,您必须使用 ApiKeyRequired: false 添加 Options 资源。

然后您的选项和获取请求的响应应该具有相同的标题:

headers: {
    "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": "DELETE,GET,HEAD,OPTIONS,PATCH,POST,PUT",
    "X-Requested-With": "*"
}

注意:“接受”必须存在,否则您将收到“对预检请求的响应未通过访问控制检查:它没有 HTTP ok 状态。”。

当您在邮递员中省略 x-api-key 时,您的预检必须能够通过 200 OK。


推荐阅读