首页 > 解决方案 > AWS CloudFormation。从 API Gateway v1 同步调用 Step Function

问题描述

我正在尝试通过 API Gateway 同步执行 AWS Step Function。问题是,对于 API Gateway V1,我必须使用 OpenAPI 语法(即 swagger)来指定integrationSubtype参数,但有些东西不起作用。这是我正在使用的 CloudFormation 模板:

{
    "AWSTemplateFormatVersion": "2010-09-09",
    "Parameters": {
        "restApiName": {
            "Type": "String",
            "Default": "stepApi"
        }
    },
    "Resources": {
        "MyStepFunction": {
            "Type": "AWS::StepFunctions::StateMachine",
            "Properties": {
                "StateMachineName": "HelloWorld-StateMachine",
                "StateMachineType": "EXPRESS",
                "DefinitionString": "{\"Comment\": \"A Hello World example of the Amazon States Language using Pass states\", \"StartAt\": \"Hello\", \"States\": {\"Hello\": { \"Type\": \"Pass\", \"Result\": \"Hello\", \"Next\": \"World\" }, \"World\": { \"Type\": \"Pass\", \"Result\": \"World\", \"End\": true } } }",
                "RoleArn": {
                    "Fn::GetAtt": [
                        "StepFunctionRole",
                        "Arn"
                    ]
                }
            }
        },
        "StepFuncGateway": {
            "Type": "AWS::ApiGateway::RestApi",
            "Properties": {
                "Name": {
                    "Ref": "restApiName"
                },
                "Body": {
                    "openapi": "3.0.1",
                    "info": {
                        "title": "processFormExample",
                        "version": "2020-11-06 15:32:29UTC"
                    },
                    "paths": {
                        "/step": {
                            "post": { 
                                "responses": {
                                    "200": {
                                      "description": "Pet updated.",
                                      "content": {
                                        "application/json": {},
                                        "application/xml": {}
                                      }
                                    },
                                    "405": {
                                        "description": "Method Not Allowed",
                                        "content": {
                                            "application/json": {},
                                            "application/xml": {}
                                        }
                                    }
                                },
                                "parameters": [
                                ],
                                "x-amazon-apigateway-integration": {
                                    "integrationSubtype": "StepFunctions-StartSyncExecution",
                                    "credentials": {
                                        "Fn::GetAtt": [
                                            "APIGatewayRole", 
                                            "Arn"
                                        ]
                                    },
                                    "RequestTemplates": {
                                        "application/json": {
                                            "Fn::Join": [
                                                "",
                                                [
                                                    "#set( $body = $util.escapeJavaScript($input.json('$')) ) \n\n{\"input\": \"$body\",\"name\": \"$context.requestId\",\"stateMachineArn\":\"",
                                                    {
                                                        "Ref": "MyStepFunction"
                                                    },
                                                    "\"}"
                                                ]
                                            ]
                                        }
                                    },
                                    "httpMethod": "POST",
                                    "payloadFormatVersion": "1.0",
                                    "passthroughBehavior": "NEVER",
                                    "type": "AWS_PROXY",
                                    "connectionType": "INTERNET"
                                }
                            }
                        }
                    },
                    "x-amazon-apigateway-cors": {
                        "allowMethods": [
                            "*"
                        ],
                        "maxAge": 0,
                        "allowCredentials": false,
                        "allowOrigins": [
                            "*"
                        ]
                    }
                }
            },
            "DependsOn": [
                "APIGatewayRole",
                "MyStepFunction"
            ]
        },
        "APIGatewayRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Effect": "Allow",
                            "Principal": {
                                "Service": [
                                    "apigateway.amazonaws.com"
                                ]
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "Path": "/",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AmazonAPIGatewayPushToCloudWatchLogs",
                    "arn:aws:iam::aws:policy/AWSStepFunctionsFullAccess"
                ]
            }
        },
        "StepFunctionRole": {
            "Type": "AWS::IAM::Role",
            "Properties": {
                "AssumeRolePolicyDocument": {
                    "Version": "2012-10-17",
                    "Statement": [
                        {
                            "Sid": "",
                            "Effect": "Allow",
                            "Principal": {
                                "Service": "states.amazonaws.com"
                            },
                            "Action": "sts:AssumeRole"
                        }
                    ]
                },
                "Path": "/",
                "ManagedPolicyArns": [
                    "arn:aws:iam::aws:policy/service-role/AWSLambdaRole"
                ]
            }
        }
    },
    "Outputs": {
        "HelloWorldApi": {
            "Description": "Sync WF API endpoint",
            "Value": {
                "Fn::Sub": "https://${StepFuncGateway}.execute-api.${AWS::Region}.amazonaws.com/step"
            }
        }
    }
}

我看到的错误如下:

导入期间发现错误:无法在路径“/step”处的资源的“POST”上进行集成:指定的集成 URI 无效(服务:AmazonApiGateway;状态代码:400;错误代码:BadRequestException;请求 ID:0c74acf9-147f-4561- 9f4f-e457096c5533;代理:空)

我没主意了。请帮我修复它。

更新:

我必须将以下代码添加到x-amazon-apigateway-integration部分并将类型更改为AWS

"uri": {
    "Fn::Join": [
        "",
        [
            "arn:aws:apigateway:",
            {
                "Ref": "AWS::Region"
            },
            ":states:action/StartSyncExecution"
        ]
    ]
},

我必须解决的另一件事是RequestTemplates,它应该以小写字母开头r。在提到更改之后,堆栈已正确部署,但现在我要解决节流问题。

标签: amazon-cloudformationaws-api-gatewayaws-step-functions

解决方案


x-amazon-apigateway-integration缺少uri财产。

Amazon Developer Guide中,URI 属性定义为:

后端的端点 URI。对于 aws 类型的集成,这是一个 ARN 值。对于 HTTP 集成,这是 HTTP 端点的 URL,包括 https 或 http 方案。

例如:

"x-amazon-apigateway-integration": {
    "type": "AWS_PROXY",
    "httpMethod": "POST",
    "uri": "http://petstore.execute-api.us-west-1.amazonaws.com/petstore/pets",
    "payloadFormatVersion": 1.0,
    "otherPropterties": "go here"
}

Amazon 在此处提供有关 URI 定义的其他信息。(复制方便)

对于 HTTP 或 HTTP_PROXY 集成,对于标准集成(其中 connectionType 不是 VPC_LINK)或私有集成(其中 connectionType 是 VPC_LINK),URI 必须是根据 RFC-3986 规范的完整编码的 HTTP(S) URL。对于私有 HTTP 集成,URI 不用于路由。

对于 AWS 或 AWS_PROXY 集成,URI 的格式为arn:aws:apigateway:{region}:{subdomain.service|service}:path|action/{service_api}. 这里,{Region}是 API 网关区域(例如,us-east-1);{service}是集成 AWS 服务的名称(例如 s3);并且{subdomain}是某些 AWS 服务支持的指定子域,用于快速查找主机名。action 可用于基于 AWS 服务操作的 API,使用Action={name}&{p1}={v1}&p2={v2}...查询字符串。随后{service_api}是指支持的操作{name}以及任何必需的输入参数。或者,路径可用于基于 AWS 服务路径的 API。随后service_api指的是 AWS 服务资源的路径,包括集成 AWS 服务的区域(如果适用)。例如,为了与 的 S3 API 集成GetObject,uri 可以是arn:aws:apigateway:us-west-2:s3:action/GetObject&Bucket={bucket}&Key={key}arn:aws:apigateway:us-west-2:s3:path/{bucket}/{key}


推荐阅读