Pat*_*ham 6 amazon-web-services aws-cloudformation aws-api-gateway
我有一个手动构建的 API 网关资源,如下所示:
GET
/assets/{items} - (points to S3 bucket)
/{proxy+} - points to Lambda function
Run Code Online (Sandbox Code Playgroud)
我想在 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
Run Code Online (Sandbox Code Playgroud)
这是大量调整的结果,而且除了阅读官方文档之外,我之前没有任何 CloudFormation 知识。创建该模板背后的堆栈后,其 API 网关资源如下所示:

POST 操作是不必要的,只能通过反复试验才能实现。GET 资源是唯一重要的资源,因为 Lambda 函数返回的应用程序尚未执行任何 post 请求。
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
Run Code Online (Sandbox Code Playgroud)
必须做什么才能使 GET 资源具有/assets/{items}指向 S3 存储桶的嵌套路径和{proxy+}指向 Lambda 的路径?我是否需要为这些路径指定单独的同级资源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}
Run Code Online (Sandbox Code Playgroud)
这会导致 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
Run Code Online (Sandbox Code Playgroud)
因此,您需要执行以下操作:
assets,这将使用来自 Rest API 的 RootResourceId attr 的 ParentId{item},这将使用上面资源资源的 ParentId。HTTP_PROXY并将 Uri 设置为 S3 存储桶路径,确保{{ item }}在路径中包含该变量。{proxy+},这将使用来自 Rest API 的 RootResourceId attr 的 ParentIdAWS_PROXY并设置 uri 来引用 Lambda 函数。希望这可以帮助
| 归档时间: |
|
| 查看次数: |
4376 次 |
| 最近记录: |