如何使用 OpenAPI 为 AWS API 网关配置 CORS?
How to configure CORS for AWS API Gateway using OpenAPI?
我有一个 api 的 OpenAPI 规范,我正在通过 CDK 进行部署。规格如下:
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
。
当我将 x-amazon-apigateway-cors
放在规范的根目录时,AWS docs 似乎表明 CORS 已启用,但当我尝试时,CORS 似乎未启用(或工作)访问 API。如何为我的 API 启用 CORS 而无需在控制台中进行配置?
Amazon API 网关提供两种类型的 APIs:REST APIs 和 HTTP APIs。 REST APIs 是 Amazon API Gateway 最初引入的那种 APIs,而 HTTP APIs got announced at the end of 2019.
根据您的 OpenAPI 规范的描述,我假设您正在尝试部署 REST API。然而,x-amazon-apigateway-cors
OpenAPI 扩展仅适用于 HTTP APIs。
您现在有两个选择:要么切换到使用 HTTP API,要么手动配置 CORS。只要您不需要 features only supported by REST APIs,我建议您改用 HTTP API,因为这是 API Amazon API 网关提供的更现代的类型。
如果您想使用 REST API,启用 CORS 需要更多的手动配置。 AWS 在 Enabling CORS for a REST API resource 中对此进行了记录。本质上,您必须确保您的集成 return 具有正确的 CORS headers。对于可能如下所示的 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 pre-flight 请求,您还必须确保 OPTIONS-requests 也 return 正确 headers。实现这一点的最简单方法是将 OPTIONS-request 的 mock-integration 添加到您的 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,因此您可能也需要解决这个问题。
我有一个 api 的 OpenAPI 规范,我正在通过 CDK 进行部署。规格如下:
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
。
当我将 x-amazon-apigateway-cors
放在规范的根目录时,AWS docs 似乎表明 CORS 已启用,但当我尝试时,CORS 似乎未启用(或工作)访问 API。如何为我的 API 启用 CORS 而无需在控制台中进行配置?
Amazon API 网关提供两种类型的 APIs:REST APIs 和 HTTP APIs。 REST APIs 是 Amazon API Gateway 最初引入的那种 APIs,而 HTTP APIs got announced at the end of 2019.
根据您的 OpenAPI 规范的描述,我假设您正在尝试部署 REST API。然而,x-amazon-apigateway-cors
OpenAPI 扩展仅适用于 HTTP APIs。
您现在有两个选择:要么切换到使用 HTTP API,要么手动配置 CORS。只要您不需要 features only supported by REST APIs,我建议您改用 HTTP API,因为这是 API Amazon API 网关提供的更现代的类型。
如果您想使用 REST API,启用 CORS 需要更多的手动配置。 AWS 在 Enabling CORS for a REST API resource 中对此进行了记录。本质上,您必须确保您的集成 return 具有正确的 CORS headers。对于可能如下所示的 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 pre-flight 请求,您还必须确保 OPTIONS-requests 也 return 正确 headers。实现这一点的最简单方法是将 OPTIONS-request 的 mock-integration 添加到您的 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,因此您可能也需要解决这个问题。