如何使用 OpenAPI 为 AWS API Gateway 配置 CORS?
Posted
技术标签:
【中文标题】如何使用 OpenAPI 为 AWS API Gateway 配置 CORS?【英文标题】:How to configure CORS for AWS API Gateway using OpenAPI? 【发布时间】:2020-10-25 01:54:51 【问题描述】:我有一个通过 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"
当我尝试通过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);
);
API 可通过api.example.com
访问,我正在使用 Gatsby 在本地运行网站localhost:8000
。
AWS docs 似乎表明当我将 x-amazon-apigateway-cors
放在规范的根目录时启用了 CORS,但是当我尝试访问 API 时似乎没有启用(或工作)CORS。如何在无需在控制台中配置的情况下为我的 API 启用 CORS?
【问题讨论】:
【参考方案1】:Amazon API Gateway 提供两种类型的 API:REST API 和 HTTP API。 REST API 是最初随 Amazon API Gateway 引入的那种 API,而 HTTP APIs got announced at the end of 2019。
根据您的 OpenAPI 规范的描述,我假设您正在尝试部署 REST API。 x-amazon-apigateway-cors
OpenAPI 扩展仅适用于 HTTP API。
您现在有两个选择:要么切换到使用 HTTP API,要么手动配置 CORS。只要您不需要features only supported by REST APIs,我建议您改用 HTTP API,因为这是 Amazon API Gateway 提供的更现代的 API。
如果您想使用 REST API,启用 CORS 需要更多手动配置。 AWS 在Enabling CORS for a REST API resource 中记录了这一点。本质上,您必须确保您的集成返回正确的 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;
;
要使 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/'"
还请注意modern browsers don't support localhost as origin for CORS,因此您可能还需要解决这个问题。
【讨论】:
谢谢,这是一个非常有帮助的答案。你是对的,它是一个 REST API,因为 (a) 它是唯一通过 CDK 支持 OpenAPI 的 API,并且 (b) 我需要通过检查令牌来进行授权,因为它看起来不像 Cognito 授权方足够丰富我想要。根据您的回答,我已经设法通过从代理本身返回标头来使 CORS 工作,但前提是我禁用了自定义 lambda 授权程序。为了能够在这里使用 lambda 授权器,我还需要做些什么吗? 您的客户端请求是否成功通过了授权人?因为如果不是,授权方将生成响应,其中不包含必要的 CORS 标头。 有没有办法让授权方返回标头?文档建议抛出一个异常来指示 401,所以我猜这会导致标题不被传递。 原来在 *** 上有另一个问题:***.com/questions/36913196/… :-) 非常感谢以上是关于如何使用 OpenAPI 为 AWS API Gateway 配置 CORS?的主要内容,如果未能解决你的问题,请参考以下文章
terraform api 网关与 openapi 规范的集成
AWS SAM :: AWS::Serverless::Api“'Auth' 属性的值无效”
如何在 OpenAPI (Swagger) 中为相同的 HTTP 状态代码定义不同的响应?