8000 bug: Step Functions ApiGateway:Invoke integration not handling headers as expected. · Issue #11628 · localstack/localstack · GitHub
[go: up one dir, main page]

Skip to content
bug: Step Functions ApiGateway:Invoke integration not handling headers as expected. #11628
Closed
@Atomicman83

Description

@Atomicman83

Is there an existing issue for this?

  • I have searched the existing issues

Current Behavior

When executing a state machine with an ApiGateway:Invoke task, the entries in the header property seem to be required to be formatted as:

"headerKey": "headerValue"

using the format "headerKey": [ "headerValue1" ] returns an error
image

Expected Behavior

In Aws we serialize our headers for ApiGateway:Invoke with the "headerKey": [ "headerValue1" ] format with no issues, we would have expected this format to be fine per Aws own documentation:

image

How are you starting LocalStack?

Custom (please describe below)

Steps To Reproduce

How are you starting localstack (e.g., bin/localstack command, arguments, or docker-compose.yml)

docker desktop extension

Client commands (e.g., AWS SDK code snippet, or sequence of "awslocal" commands)

Using localstack and something like linqpad or a c# console app this snippet should create a working greedy proxy with http_proxy integration to an api running on the host machine at port 5000 (running api not necessary to prove defect).

               var apiName = "Test";
		var port = 5000;
		
		// localstack.net client
		var _localgwClient = SessionStandalone.Init().Create().CreateClientByImplementation<AmazonAPIGatewayClient>();
		
		// create rest api
		var api = _localgwClient.CreateRestApiAsync(new CreateRestApiRequest()
		{
			Name = apiName,
			EndpointConfiguration = new EndpointConfiguration()
			{
				
				Types = { "REGIONAL" }
			},
			ApiKeySource = "HEADER",
			Version = "1"
		}).Result;


		// get the default "/" resource
		var parentResource = _localgwClient.GetResourcesAsync(new GetResourcesRequest()
		{
			RestApiId = api.Id
		}).Result.Items.Single();


		// create the "/{proxy+}" resource
		var proxyResource = _localgwClient.CreateResourceAsync(new CreateResourceRequest()
		{
			ParentId = parentResource.Id,
			PathPart = "{proxy+}",
			RestApiId = api.Id
		}).Result;


		// add the ANY method for the proxy resource
		var method = _localgwClient.PutMethodAsync(new PutMethodRequest()
		{
			ApiKeyRequired = false,
			AuthorizationType = "None",
			HttpMethod = "ANY",
			RequestParameters = new Dictionary<string, bool> { { "resource.method.path.proxy", true } },
			ResourceId = proxyResource.Id,
			RestApiId = api.Id
		}).Result;

		// add the parameterized integration with Uri
		var integration = _localgwClient.PutIntegrationAsync(new PutIntegrationRequest()
		{
			ConnectionType = "INTERNET",
			IntegrationHttpMethod = "ANY",
			HttpMethod = "ANY",
			ResourceId = proxyResource.Id,
			RestApiId = api.Id,
			Uri = $"http://host.docker.internal:{port}/{{proxy}}",
			Type = "HTTP_PROXY",
			TlsConfig = new TlsConfig()
			{
				InsecureSkipVerification = true
			},
			RequestParameters = new Dictionary<string, string> { { "integration.request.path.proxy", "method.request.path.proxy" } }
		}).Result;

		// create a deployment to add the QA stage
		var deployment = _localgwClient.CreateDeploymentAsync(new CreateDeploymentRequest()
		{
			RestApiId = api.Id,
			StageName = "QA"
		}).Result;

Now also create an execution role for step functions (not pictured) and create a simple step function with ApiGateway:Invoke and the restApiId from above substituted in the ApiEndpoint parameter. The ApiEndpoint parameter has to be valid but the path doesn't, an invalid header will return an ApiGateway.InvalidHeader error during execution.

{
	"TimeoutSeconds": 36000,
	"Version": "1.0",
	"StartAt": "InvokeDefect",
	"States": {
		"InvokeDefect": {
			"Type": "Task",
			"Resource": "arn:aws:states:::apigateway:invoke",
			"Parameters": {
				"ApiEndpoint": "http://localhost:4566/restapis/<restApiId>",
				"Path": "test",
                                "Stage": "QA",
				"Method": "GET",
				"Headers.$": "$.Headers",
				"AuthType": "NONE"
			},
			"Next": "Finished"
		},
		"Finished": {
			"Type": "Succeed",
			"Comment": "Workflow complete"
		}
	}
}

Finally you can execute the state machine with the following input:

{
    "Headers" : {
        "ContentType" : [ "application/json" ]
    }
}

And the step should fail with the above error.

Provide this input instead and you'll likely just get a 404 or something:

{
    "Headers" : {
        "ContentType" : "application/json"
    }
}

Environment

- OS: Windows 11
- LocalStack:
  LocalStack version: 3.7.3.dev16
  LocalStack Docker image sha: sha256:3124606c2b96bac5dcc8eb953df16fe746f17e4cbf0d809a42d8165568fa8af5
  LocalStack build date: 2024-09-12
  LocalStack build git hash: 026c49c3d

Anything else?

No response

56EC

Metadata

Metadata

Assignees

Type

No type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions

    0