如何使用 OpenAPI 为 AWS API Gateway 配置 CORS?

Joh*_*ohn 0 amazon-web-services aws-cloudformation aws-lambda aws-api-gateway aws-cdk

我有一个用于通过 CDK 部署的 api 的 OpenAPI 规范。规范看起来像:

openapi: 3.0.1
info:
  title: My API
  description: My REST API with CORS enabled
  version: 0.1.0

x-amazon-apigateway-cors:
  allowOrigins:
    - "*"
  allowCredentials: true
  exposeHeaders:
    - "x-apigateway-header"
    - "x-amz-date"
    - "content-type"
  maxAge: 3600
  allowMethods:
    - "*"
  allowHeaders":
    - "x-apigateway-header"
    - "x-amz-date"
    - "content-type"
    - "Authorization"

components:
  securitySchemes:
    lambda:
      type: "apiKey"
      name: "Authorization"
      in: "header"
      x-amazon-apigateway-authtype: "custom"
      x-amazon-apigateway-authorizer:
        authorizerUri: "{{my-lambda-authorizer}}"
        authorizerResultTtlInSeconds: 300
        type: "token" 

paths:
  /user/{id}:
    get:
      summary: Get info of specified user.
      parameters:
        - in: path
          name: id
          required: true
          schema:
            type: string
      responses:
        '200':
          description: OK
          content:
            application/json:
              schema:
                $ref: '#/components/schemas/User'
      security:
        - lambda: []
      x-amazon-apigateway-integration:
        uri: "{{my-lambda}}"
        passthroughBehavior: "when_no_match"
        httpMethod: "POST"
        type: "aws_proxy"
Run Code Online (Sandbox Code Playgroud)

当我尝试通过 访问它时fetch(),出现错误Failed to load resource: Origin http://localhost:8000 is not allowed by Access-Control-Allow-Origin

fetch('https://api.example.com/user/1')
        .then(response => response.json())
        .then((user: User) => {
            // do something
        })
        .catch((err) => {
            console.log("Error: " + err);
        });
Run Code Online (Sandbox Code Playgroud)

API 可访问,api.example.com我正在使用 Gatsby 在本地运行网站localhost:8000

AWS文档似乎状态,当我把CORS启用x-amazon-apigateway-cors在规范的根源,但CORS似乎并没有被启用(或工作),当我尝试访问的API。如何在不需要在控制台中配置的情况下为我的 API 启用 CORS?

Dun*_*dan 5

Amazon API Gateway 提供两种类型的 API:REST API 和 HTTP API。REST API 是最初随 Amazon API Gateway 引入的那种 API,而HTTP API 于 2019 年底发布

根据您的 OpenAPI 规范的描述,我假设您正在尝试部署 REST API。x-amazon-apigateway-cors然而,OpenAPI 扩展仅适用于 HTTP API。

您现在有两种选择:切换到使用 HTTP API 或手动配置 CORS。只要您不需要仅由 REST API 支持的功能,我建议您改用 HTTP API,因为这是 Amazon API Gateway 提供的更现代的 API。

如果要使用 REST API,启用 CORS 需要更多的手动配置。AWS 在为 REST API 资源启用 CORS 中对此进行了记录。本质上,您必须确保您的集成返回正确的 CORS 标头。对于可能如下所示的 NodeJS AWS Lambda 函数:

exports.handler = async (event) => {
    const response = {
        statusCode: 200,
        headers: {
            "Access-Control-Allow-Headers" : "Content-Type",
            "Access-Control-Allow-Origin": "https://www.example.com",
            "Access-Control-Allow-Methods": "OPTIONS,POST,GET"
        },
        body: JSON.stringify('Hello from Lambda!'),
    };
    return response;
};
Run Code Online (Sandbox Code Playgroud)

对于 CORS 飞行前请求,您还必须确保 OPTIONS 请求也返回正确的标头。实现这一目标的最简单方法是将 OPTIONS 请求的模拟集成添加到您的 OpenAPI 规范中。那看起来像:

options:
  responses:
    '200':
      description: Default response
      headers:
        Access-Control-Allow-Headers:
          schema:
            type: string
        Access-Control-Allow-Methods:
          schema:
            type: string
        Access-Control-Allow-Origin:
          schema:
            type: string
  x-amazon-apigateway-integration:
    type: mock
    requestTemplates:
      application/json: |
        {"statusCode" : 200}
    responses:
      default:
        statusCode: 200
        responseParameters:
          method.response.header.Access-Control-Allow-Headers: "'*'"
          method.response.header.Access-Control-Allow-Methods: "'OPTIONS,POST'"
          method.response.header.Access-Control-Allow-Origin: "'https://example.com/'"
Run Code Online (Sandbox Code Playgroud)

还请注意,现代浏览器不支持 localhost 作为 CORS 的来源,因此您可能也需要解决这个问题。