使用 AWS CDK 为 AWS API 网关启用 CORS
Posted
技术标签:
【中文标题】使用 AWS CDK 为 AWS API 网关启用 CORS【英文标题】:enabling CORS for AWS API gateway with the AWS CDK 【发布时间】:2019-03-16 01:43:53 【问题描述】:我正在尝试使用 AWS CDK 构建应用程序,如果我要使用 AWS 控制台手动构建应用程序,我通常会在 API 网关中启用 CORS。
即使我可以将 swagger 导出到 API Gateway 之外,并且找到了许多为 OPTIONS 方法生成 Mock 端点的选项,但我不知道如何使用 CDK 执行此操作。目前我正在尝试:
const apigw = require('@aws-cdk/aws-apigateway');
在哪里:
var api = new apigw.RestApi(this, 'testApi');
并定义 OPTIONS 方法,如:
const testResource = api.root.addResource('testresource');
var mock = new apigw.MockIntegration(
type: "Mock",
methodResponses: [
statusCode: "200",
responseParameters :
"Access-Control-Allow-Headers" : "string",
"Access-Control-Allow-Methods" : "string",
"Access-Control-Allow-Origin" : "string"
],
integrationResponses: [
statusCode: "200",
responseParameters:
"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" : "'GET,POST,OPTIONS'"
],
requestTemplates:
"application/json": "\"statusCode\": 200"
);
testResource.addMethod('OPTIONS', mock);
但这并没有部署。我在运行“cdk deploy”时从 cloudformation stack deploy 得到的错误消息是:
Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: Access-Control-Allow-Origin] (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException;
想法?
【问题讨论】:
【参考方案1】:recent change 使启用 CORS 变得更简单:
const restApi = new apigw.RestApi(this, `api`,
defaultCorsPreflightOptions:
allowOrigins: apigw.Cors.ALL_ORIGINS
);
【讨论】:
如果您启用了binaryMediaTypes
,这将不起作用。【参考方案2】:
我自己没有对此进行测试,但根据 this answer,您在定义 MOCK 集成时似乎需要使用一组稍微不同的键:
const api = new apigw.RestApi(this, 'api');
const method = api.root.addMethod('OPTIONS', new apigw.MockIntegration(
integrationResponses: [
statusCode: "200",
responseParameters:
"method.response.header.Access-Control-Allow-Headers": "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'",
"method.response.header.Access-Control-Allow-Methods": "'GET,POST,OPTIONS'",
"method.response.header.Access-Control-Allow-Origin": "'*'"
,
responseTemplates:
"application/json": ""
],
passthroughBehavior: apigw.PassthroughBehavior.Never,
requestTemplates:
"application/json": "\"statusCode\": 200"
,
));
// since "methodResponses" is not supported by apigw.Method (https://github.com/awslabs/aws-cdk/issues/905)
// we will need to use an escape hatch to override the property
const methodResource = method.findChild('Resource') as apigw.cloudformation.MethodResource;
methodResource.propertyOverrides.methodResponses = [
statusCode: '200',
responseModels:
'application/json': 'Empty'
,
responseParameters:
'method.response.header.Access-Control-Allow-Headers': true,
'method.response.header.Access-Control-Allow-Methods': true,
'method.response.header.Access-Control-Allow-Origin': true
]
如果能够使用更多 friendly API 启用 CORS,将会很有用。
【讨论】:
我同意一个更友好的 API 会非常有帮助,但这至少能让我前进并且它确实有效。谢谢!【参考方案3】:编辑:随着 CDK 的更新,不再需要使用逃生舱口。请查看其他答案,因为它们更干净。
原答案:
This version, originally created by Heitor Vital on github uses only native constructs.
export function addCorsOptions(apiResource: apigateway.IResource)
apiResource.addMethod('OPTIONS', new apigateway.MockIntegration(
integrationResponses: [
statusCode: '200',
responseParameters:
'method.response.header.Access-Control-Allow-Headers': "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Amz-User-Agent'",
'method.response.header.Access-Control-Allow-Origin': "'*'",
'method.response.header.Access-Control-Allow-Credentials': "'false'",
'method.response.header.Access-Control-Allow-Methods': "'OPTIONS,GET,PUT,POST,DELETE'",
,
],
passthroughBehavior: apigateway.PassthroughBehavior.NEVER,
requestTemplates:
"application/json": "\"statusCode\": 200"
,
),
methodResponses: [
statusCode: '200',
responseParameters:
'method.response.header.Access-Control-Allow-Headers': true,
'method.response.header.Access-Control-Allow-Methods': true,
'method.response.header.Access-Control-Allow-Credentials': true,
'method.response.header.Access-Control-Allow-Origin': true,
,
]
)
我还使用他的版本作为指导,将相同的代码移植到 python。
def add_cors_options(api_resource):
"""Add response to OPTIONS to enable CORS on an API resource."""
mock = apigateway.MockIntegration(
integration_responses=[
'statusCode': '200',
'responseParameters':
'method.response.header.Access-Control-Allow-Headers':
"'Content-Type,\
X-Amz-Date,\
Authorization,\
X-Api-Key,\
X-Amz-Security-Token,X-Amz-User-Agent'",
'method.response.header.Access-Control-Allow-Origin': "'*'",
'method.response.header.Access-Control-Allow-Credentials':
"'false'",
'method.response.header.Access-Control-Allow-Methods':
"'OPTIONS,\
GET,\
PUT,\
POST,\
DELETE'",
],
passthrough_behavior=apigateway.PassthroughBehavior.NEVER,
request_templates=
"application/json": "\"statusCode\": 200"
)
method_response = apigateway.MethodResponse(
status_code='200',
response_parameters=
'method.response.header.Access-Control-Allow-Headers': True,
'method.response.header.Access-Control-Allow-Methods': True,
'method.response.header.Access-Control-Allow-Credentials': True,
'method.response.header.Access-Control-Allow-Origin': True
)
api_resource.add_method(
'OPTIONS',
integration=mock,
method_responses=[method_response]
)
【讨论】:
【参考方案4】:背景
我在尝试在 Terraform 中实现 aws_api_gateway_integration_response
时遇到了这个答案,并且意外地遇到了解决方案。
问题
我收到此错误消息:
Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression specified: POST,GET,OPTIONS]
在aws_api_gateway_integration_response
资源中,我将response_parameter
键设为:
response_parameters =
"method.response.header.Access-Control-Allow-Headers" = "Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token"
"method.response.header.Access-Control-Allow-Origin" = "*"
"method.response.header.Access-Control-Allow-Methods" = "POST,GET,OPTIONS"
# "method.response.header.Access-Control-Allow-Credentials" = "false"
我认为一切都很好,因为我认为双引号就是 Terraform 所需要的。然而,事实并非如此。
解决方案
我必须在双引号内的值周围添加一个单引号。像这样:
response_parameters =
"method.response.header.Access-Control-Allow-Headers" = "'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token'"
"method.response.header.Access-Control-Allow-Origin" = "'*'"
"method.response.header.Access-Control-Allow-Methods" = "'POST,GET,OPTIONS'"
# "method.response.header.Access-Control-Allow-Credentials" = "false"
【讨论】:
以上是关于使用 AWS CDK 为 AWS API 网关启用 CORS的主要内容,如果未能解决你的问题,请参考以下文章
将自定义弹性 IP 与 NAT 网关与 AWS CDK 相关联
AWS CDK 将 API Gateway URL 传递到同一堆栈中的静态站点