【发布时间】:2020-08-30 11:48:19
【问题描述】:
我有一个手动构建的 API Gateway 资源,如下所示:
GET
/assets/{items} - (points to S3 bucket)
/{proxy+} - points to Lambda function
我想在 Cloudformation YAML 模板中模拟此设置,但不确定如何进行。这是我正在使用的当前模板(为简洁起见,部分缩小了):
AWSTemplateFormatVersion: 2010-09-09
Parameters:
apiGatewayStageName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Default: call
lambdaFunctionName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Default: my-function
s3BucketName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Resources:
apiGateway:
Type: 'AWS::ApiGateway::RestApi'
Properties:
Name: my-api
Description: My API
Metadata:
...
apiGatewayRootMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: POST
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- >-
arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
Metadata:
...
apiGatewayDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- apiGatewayRootMethod
- apiGatewayGETMethod
Properties:
RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
Metadata:
...
lambdaFunction:
Type: 'AWS::Lambda::Function'
Properties:
...
lambdaApiGatewayInvoke:
...
lambdaIAMRole:
...
lambdaLogGroup:
...
apiGatewayGETMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- >-
arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
Metadata:
'AWS::CloudFormation::Designer':
id: 1a329c4d-9d18-499e-b852-0e361af324f4
s3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Ref s3BucketName
Metadata:
...
Outputs:
apiGatewayInvokeURL:
Value: !Sub >-
https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
lambdaArn:
Value: !GetAtt lambdaFunction.Arn
这是经过大量调整的结果,除了查看官方文档之外,我之前没有任何 CloudFormation 知识。创建该模板背后的堆栈后,其 API Gateway 资源如下所示:
POST 操作是不必要的,只有反复试验。 GET 资源是唯一重要的资源,因为 Lambda 函数返回的应用程序尚未执行任何发布请求。
GET 必须从堆栈的这一部分创建:
apiGatewayGETMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- >-
arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
必须做些什么才能使 GET 资源具有指向 S3 存储桶的嵌套 /assets/{items} 路径和指向 Lambda 的 {proxy+} 路径?我是否需要为apiGatewayAssets 和apiGatewayLambdaProxy 等路径指定单独的同级资源,然后以某种方式将它们连接到apiGatewayGETMethod?
2020-05-17 更新
目前让我感到困惑的是这个资源:
apiGatewayAssetsItemsResourceMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
ResourceId: !Ref apiGatewayAssetsItemsResource
RestApiId: !Ref apiGateway
AuthorizationType: NONE
HttpMethod: GET
Integration:
Type: AWS
Credentials: arn:aws:iam::XXXXXX:role/AnExistingRole
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
RequestParameters:
integration.request.path.item: 'method.request.path.item'
method.request.path.item: true
Uri: !Sub >-
arn:aws:apigateway:${AWS::Region}:s3:path/${s3BucketName}/{item}
这会导致 CloudFormation 堆栈创建错误,状态原因为 Invalid mapping expression specified: Validation Result: warnings : [], errors : [Invalid mapping expression parameter specified: method.request.path.item] (Service: AmazonApiGateway; Status Code: 400; Error Code: BadRequestException; Request ID: XXXXXX)
但是,如果我尝试使用完全相同的资源减去 RequestParameters 条目来创建它,它就会成功创建。尽管在控制台中查看该 API Gateway GET 方法时,集成请求框中缺少 Paths: item 行。我目前正在使用的完整模板:
AWSTemplateFormatVersion: 2010-09-09
Parameters:
apiGatewayStageName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Default: call
lambdaFunctionName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Default: my-function
s3BucketName:
Type: String
AllowedPattern: '^[a-zA-Z0-9]+[a-zA-Z0-9-]+[a-zA-Z0-9]+$'
Resources:
apiGateway:
Type: 'AWS::ApiGateway::RestApi'
Properties:
Name: my-api
Description: My API
apiGatewayDeployment:
Type: 'AWS::ApiGateway::Deployment'
DependsOn:
- apiGatewayGETMethod
Properties:
RestApiId: !Ref apiGateway
StageName: !Ref apiGatewayStageName
lambdaFunction:
...
lambdaApiGatewayInvoke:
...
lambdaIAMRole:
...
lambdaLogGroup:
...
apiGatewayGETMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
HttpMethod: GET
Integration:
IntegrationHttpMethod: POST
Type: AWS_PROXY
Uri: !Sub
- >-
arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
ResourceId: !GetAtt apiGateway.RootResourceId
RestApiId: !Ref apiGateway
s3Bucket:
Type: 'AWS::S3::Bucket'
Properties:
BucketName: !Ref s3BucketName
BucketPolicy:
...
apiGatewayAssetsResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref apiGateway
ParentId: !GetAtt
- apiGateway
- RootResourceId
PathPart: assets
apiGatewayAssetsItemsResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref apiGateway
PathPart: '{item}'
ParentId: !Ref apiGatewayAssetsResource
apiGatewayAssetsItemsResourceMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
ResourceId: !Ref apiGatewayAssetsItemsResource
RestApiId: !Ref apiGateway
AuthorizationType: NONE
HttpMethod: GET
Integration:
Type: AWS
Credentials: arn:aws:iam::XXXXXX:role/AnExistingRole
IntegrationHttpMethod: GET
PassthroughBehavior: WHEN_NO_MATCH
Uri: !Sub >-
arn:aws:apigateway:${AWS::Region}:s3:path/${s3BucketName}/{item}
apiGatewayLambdaResource:
Type: 'AWS::ApiGateway::Resource'
Properties:
RestApiId: !Ref apiGateway
PathPart: '{proxy+}'
ParentId: !GetAtt
- apiGateway
- RootResourceId
apiGatewayLambdaResourceMethod:
Type: 'AWS::ApiGateway::Method'
Properties:
AuthorizationType: NONE
RestApiId: !Ref apiGateway
ResourceId: !Ref apiGatewayLambdaResource
HttpMethod: ANY
Integration:
Type: AWS_PROXY
IntegrationHttpMethod: GET
Uri: !Sub
- >-
arn:aws:apigateway:${AWS::Region}:lambda:path/2015-03-31/functions/${lambdaArn}/invocations
- lambdaArn: !GetAtt lambdaFunction.Arn
Outputs:
apiGatewayInvokeURL:
Value: !Sub >-
https://${apiGateway}.execute-api.${AWS::Region}.amazonaws.com/${apiGatewayStageName}
lambdaArn:
Value: !GetAtt lambdaFunction.Arn
【问题讨论】:
-
您使用不同的集成方法。在上图中,您使用 AWS,而在下图中,您使用 AWS_PROXY。所以很明显你不能开采它们。因此,要么创建为 AWS,要么创建为 AWS_PROXY。
-
请您将最终的工作模板分享给其他人,谢谢!
-
@pho_pho 你可以在这里找到它:gist.github.com/PatNeedham/5b3c4b68997b0375f27d402a056a6e1b
-
感谢您的快速回复和分享!
标签: amazon-web-services amazon-cloudformation aws-api-gateway