我想使用AWS CDK来定义一个API网关和一个APIG将代理到的lambda。
OpenAPI规范支持Swagger规范的x-amazon-apigateway-integration
自定义扩展(详细的here),为此需要lambda的调用URL。如果lambda与API定义在同一个堆栈中,我不知道如何在OpenAPI规范中提供这一点。我能想到的最好的方法是定义一个堆栈,其中包含lambda,然后从中获取输出,并运行sed
在OpenAPI规范中执行查找和替换操作以插入URI,然后使用此修改后的OpenAPI规范创建第二个堆栈。
示例:
/items:
post:
x-amazon-apigateway-integration:
uri: "arn:aws:apigateway:eu-west-2:lambda:path/2015-03-31/functions/arn:aws:lambda:eu-west-2:123456789012:function:MyStack-SingletonLambda4677ac3018fa48679f6-B1OYQ50UIVWJ/invocations"
passthroughBehavior: "when_no_match"
httpMethod: "POST"
type: "aws_proxy"
这似乎是一个先有鸡还是先有蛋的问题,以上是唯一的方法吗?
我尝试使用SpecRestApi CDK构造的defaultIntegration
属性。文档声明:
除非指定了集成,否则用作此API中创建的所有方法的默认值的集成。
这看起来像是a应该能够使用CDK规范中定义的lambda来定义一个默认的集成,从而让所有的方法都使用这个集成,而不需要事先知道lambda的uri。
因此我试着这样做:
SingletonFunction myLambda = ...
SpecRestApi openapiRestApi = SpecRestApi.Builder.create(this, "MyApi")
.restApiName("MyApi")
.apiDefinition(ApiDefinition.fromAsset("openapi.yaml"))
.defaultIntegration(LambdaIntegration.Builder.create(myLambda)
.proxy(false)
.build())
.deploy(true)
.build();
在openapi.yaml
中定义的OpenAPI规范不包括x-amazon-apigateway-integration
节;它只有一个在标准OpenApi3规范中定义的GET方法。
但是,当我尝试部署它时,我得到一个错误:
No integration defined for method (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: 56113150-1460-4ed2-93b9-a12618864582)
这似乎是一个bug,所以我提交了一个here。
Q2.如何使用CDK定义API网关和Lambda,并通过OpenAPI规范将两者连接在一起?
4条答案
按热度按时间vi4fp9gy1#
有一个现有的解决方法。方法如下:
您的OpenAPI文件必须如下所示:
如您所见,这个OpenAPI模板引用了ApiStage、AWS::Region和MySuperLambda.Arn。
关联的cdk文件包含以下内容:
这里的ApiStage是用在props中的。它允许我在CI期间用一个环境变量将其传递给cdk应用程序。
在这里,和前面一样,我强制CDK覆盖逻辑id,以便在部署之前知道id,否则,cdk会给逻辑id添加一个后缀。
这允许我将OpenAPI文件直接上传到cdk存储桶中(无需创建新的存储桶,这太棒了)。
这是云形成魔法的一部分。这是Fn::Sub和Fn::GetAtt被解释的地方。我无法让它和!Ref函数一起工作。
从以前读取的文件创建API定义。
最后,创建SpecRestApi. Run and magic,这是有效的.你可能仍然会遇到400个错误,可能是因为你的OpenAPI文件格式不正确(不要使用!Ref).
我会推荐这个吗?嗯。这几乎是一个变通方案。如果你想在你的CI中使用OpenAPI格式的动态变量,它真的很有用。不需要太多的努力,你可以在dev和prod中部署,只需要切换一个环境变量。
然而,这感觉真的很笨拙,似乎不符合CDK的理念。这是我目前用于部署的,但将来可能会改变。我相信一个真正的模板解决方案可能会更适合这里,但现在,我真的没有考虑过它。
g6ll5ycj2#
我提出了一个解决方案,它比这里的其他答案简单一些,因为它不需要阶段变量或多个部署。
首先,将
x-amazon-apigateway-integration
的uri
设置为类似${API_LAMBDA_ARN}
的变量,并使用与此示例中相同的type
和httpMethod
:然后,您可以使用此构造(或等效的TypeScript实现)在构建时替换变量,并基于OpenAPI文档创建API Gateway Http API:
Python用户可能也会对我发布的openapigateway结构感兴趣,它支持JSON和YAML,使这个过程更加简单。
fivyi3re3#
看起来我所追求的是由this CDK issue跟踪的。同时,我在这里对这个问题的评论的指导下提出了一个解决方案。
我使用https://github.com/spullara/mustache.java来解析我的OpenAPI规范文件,并替换其中引用API网关的调用ARN(API网关本身引用Lambda ARN)的模板值。
注意,
props
是引用Stack
prop 的变量,myLambda
是对SingletonFunction
的引用。我的OpenAPI规范如下所示(删除了标题和模型部分):
还请注意,当我授予API Gateway权限以调用lambda时,如下所示:
我仍然收到一个500错误,并且在日志中看到一个“Invalid permissions on Lambda function”错误消息。如果我向Lambda添加权限,如下所示:
那么我现在需要在权限生效之前重新部署API。我仍在努力避免这种情况。
2izufjch4#
我最近仅使用Python和CDK实现了相同的功能,如下所示
在我的swagger.json文件里我已经
注意:要明确的是,LAMBDA_ARN是一个占位符,它将被CloudFormation而不是Python所取代! Python对Lambda ARN一无所知...
希望这有帮助!