I am currently trying to set up the invocation of a Step Function via an API Gateway endpoint in LocalStack. I have both the Step Function and the API Gateway creating successfully however when I try to cUrl the API endpoint I get an error:
{"Type": "User", "message": "Error invoking integration for API Gateway ID '5zpknu8ld7': Expecting value: line 1 column 1 (char 0)", "__type": "InvalidRequest"}
The following is the series of commands in my init script which can be used to recreate this issue (hopefully):
#!/bin/bash
set -x
apt-get install jq -y
source ~/.bashrc
export STEP_FUNCTION_DEFINITION=$(</etc/localstack/init/functions/step-func-def.json)
awslocal lambda create-function \
--function-name lambda-function \
--runtime python3.10 \
--zip-file fileb:///etc/localstack/init/functions/function.zip \
--handler handler.lambda_handler \
--role arn:aws:iam::000000000000:role/lambda-role
awslocal stepfunctions create-state-machine \
--name step-function \
--definition "$STEP_FUNCTION_DEFINITION" \
--role-arn arn:aws:iam::000000000000:role/step-function-role
export gateway_repsonse=$(awslocal apigateway create-rest-api --name api-gateway)
export gateway_id=$(echo $gateway_repsonse | jq -r '.id')
export root_resources_response=$(awslocal apigateway get-resources --rest-api-id $gateway_id)
export root_resource_id=$(echo $root_resources_response | jq -r '.items[0].id')
export session_resource_response=$(awslocal apigateway create-resource \
--rest-api-id $gateway_id \
--parent-id $root_resource_id \
--path-part "{sessionId}")
export session_resource_id=$(echo $session_resource_response | jq -r '.id')
awslocal apigateway put-method \
--rest-api-id $gateway_id \
--resource-id $session_resource_id \
--http-method POST \
--request-parameters "method.request.path.sessionId=true" \
--authorization-type "NONE"
awslocal apigateway put-integration \
--rest-api-id $gateway_id \
--resource-id $session_resource_id \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri arn:aws:apigateway:us-east-1:states:action/StartExecution \
--request-parameters '{"input": "{}","name": "MyExecution","stateMachineArn": "arn:aws:states:us-east-1:000000000000:stateMachine:step-function"}' \
--passthrough-behavior WHEN_NO_MATCH
awslocal apigateway create-deployment \
--rest-api-id $gateway_id \
--stage-name test
set +x
The step function definition is as follows:
{
"StartAt": "QueryBMM",
"States": {
"QueryBMM": {
"Type": "Task",
"Resource": "arn:aws:states:::lambda:invoke",
"Parameters": {
"Payload.$": "$",
"FunctionName": "arn:aws:lambda:us-east-1:000000000000:function:step-function-handler"
},
"Retry": [
{
"ErrorEquals": [
"Lambda.ServiceException",
"Lambda.AWSLambdaException",
"Lambda.SdkClientException",
"Lambda.TooManyRequestsException"
],
"IntervalSeconds": 2,
"MaxAttempts": 6,
"BackoffRate": 2
}
],
"End": true
}
}
}
I tried running:
curl -X POST http://localhost:4566/restapis/<gateway_id>/test/_user_request_/test
and expected that the step function and thus the lambda would be invoked. Instead I get the error listed earlier. Is anybody able to see any issues with this setup?
When you are stuck with issues like this one, I strongly suggest you to look at the tests that Localstack certifies as working. For example, in this case, you could search in the StartExecution tests, there is the test_apigateway_with_step_function_integration
test. Then search the test name in the Github repository and you will find its code.
I had a similar problem in the past, so I have translated that Python test as shell code. Maybe you are missing the --request-templates
parameter (?):
REQUEST_TEMPLATE="$(echo "
{
\"application/json\": \"{
\\\"input\\\": \\\"\$util.escapeJavaScript(\$input.json('$'))\\\",
\\\"stateMachineArn\\\": \\\"$STATE_MACHINE_ARN\\\"
}\"
}" | sed -z 's/\n//g' )"
awslocal apigateway put-integration \
--rest-api-id "$REST_API_ID" \
--resource-id "$RESOURCE_ID" \
--http-method POST \
--type AWS \
--integration-http-method POST \
--uri "$INTEGRATION_URI" \
--passthrough-behavior WHEN_NO_MATCH \
--request-templates "$REQUEST_TEMPLATE"