I'm attempting to build a CF stack that essentially does what an AWS guide can do through the console: https://docs.aws.amazon.com/step-functions/latest/dg/tutorial-api-gateway.html
I'm able to create it manually through the console, and it works. Now I'd like to use ApiGatewayV2, because it hs the AutoDeploy
feature, whereas the RestApi does not. My template.yml
is (only the relevant bits):
GatewayV2:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: !Sub ${AWS::StackName}-GatewayV2
Description: API Gateway for integrations
ProtocolType: HTTP
CredentialsArn: !GetAtt SubmitOrderResourceRole.Arn
RouteKey: $default
StageV2:
Type: AWS::ApiGatewayV2::Stage
Properties:
ApiId: !Ref GatewayV2
DeploymentId: !Ref DeploymentV2
StageName: $default
AutoDeploy: true
DeploymentV2:
Type: AWS::ApiGatewayV2::Deployment
DependsOn:
- RouteV2
Properties:
ApiId: !Ref GatewayV2
Description: Deployment for the API Gateway
RouteV2:
Type: AWS::ApiGatewayV2::Route
Properties:
ApiId: !Ref GatewayV2
RouteKey: POST /orders
Target: !Join
- /
- - integrations
- !Ref IntegrationV2
IntegrationV2:
Type: AWS::ApiGatewayV2::Integration
Properties:
ApiId: !Ref GatewayV2
IntegrationType: AWS_PROXY
CredentialsArn: !GetAtt SubmitOrderResourceRole.Arn
IntegrationMethod: POST
IntegrationUri: !Sub arn:aws:apigateway:${AWS::Region}:states:action/StartSyncExecution
PassthroughBehavior: NEVER
RequestTemplates:
application/json: !Sub |
{
"input": "$util.escapeJavaScript($input.json('$'))",
"stateMachineArn": "${SubmitOrderStateMachine}"
}
ResponseParameters:
- StatusCode: 200
ResponseTemplates:
application/json: |
if(!$input.json('$.status').toString().equals('"SUCCEEDED"'))
set($context.responseOverride.status = 500)
end
However, when I attempt to deploy this, I get an error back:
Resource handler returned message: "Target is a required property in this context
If I try to use the Target
property of the ApiGatewayV2
and set it to the ARN of my step function:
GatewayV2:
Type: AWS::ApiGatewayV2::Api
Properties:
Name: !Sub ${AWS::StackName}-GatewayV2
Description: API Gateway for integrations
ProtocolType: HTTP
CredentialsArn: !GetAtt SubmitOrderResourceRole.Arn
RouteKey: $default
Target: !Sub integrations/${SubmitOrderStateMachine}
I instead get this error:
Resource handler returned message: "Target only supports HTTP Proxy or Lambda Proxy
Does anyone know why the Target
property is required "in this context", and how I can bypass it? Its docs say it's only for the quick-create features, which I don't need to do here. I'm happy to define the specific deployments, stages, routes, and integrations to make it work.
AWS::ApiGatewayV2::Api only supports two kinds of APIs: WebSockets and HTTPS via quick create.
The older V1 API Gateway allows much more control over the process, and does not use quick create. You can use a Method rather than an Integration to link it to the state machine; it's complicated but possible.
I suggest creating the Gateway using the V1 definition instead (along with any deployments/stages/routes):
Gateway:
Type: AWS::ApiGateway::RestApi
Properties:
Name: !Sub ${AWS::StackName}-Gateway
EndpointConfiguration:
Types:
- REGIONAL
With the gateway created, you can now add a Method to link the Gateway to the Step Function:
GatewayMethod:
Type: AWS::ApiGateway::Method
Properties:
ResourceId:
Ref: GatewayResource
RestApiId:
Ref: Gateway
ApiKeyRequired: true
AuthorizationType: NONE
HttpMethod: POST
Integration:
Type: AWS
IntegrationHttpMethod: POST
Uri: arn:aws:apigateway:us-east-1:states:action/StartSyncExecution
Credentials:
...
RequestTemplates:
...
IntegrationResponses:
...
MethodResponses:
- StatusCode: 200
The above was taken from https://github.com/antstackio/api-gateway-to-synchronous-step-function which is a more in-depth explanation. The article explains more but this should be enough to get you started.
This approach should allow you to create a gateway without using quick create. Note there's also a difference between V1 HTTPS and REST APIs, but both should work with a step function.