Why aren't the HTTP headers passed from API Gateway to Step Functions?

0

I have an endpoint set up on API Gateway with integration to a step function - the integration is working well and my function is executed. However I have a need to access the headers on the initial request to the api gateway (as they need to be passed on to an API call made by one of the steps in the step function) I've added the http headers to the API Gateway Method Request and also done this in the HTTP Headers section of the Integration Request, then in the mapping template I have

#set($inputbody = $input.json('$'))
{
   "method": "$context.httpMethod",
   "input": "$util.escapeJavaScript($inputbody)",
   "stateMachineArn": "MyStateMachineARN",
   "headers": {
        #foreach($param in $input.params().header.keySet())
        "$param": "$util.escapeJavaScript($input.params().header.get($param))"
        #if($foreach.hasNext),#end
        #end
    }
}

When I test this I see the headers in the logs after the request body has been transformed - before it executes the step function

request body after transformations: {
   "method": "POST",
   "input": "{\"surname\":\"TESTSURNAME\"}",
   "stateMachineArn": "MyStateMachineARN",
   "headers": {
                "HeaderA": "ValueA"
        ,                "HeaderB": "ValueB"
                    }
}

But in the step functions I am struggling to see the headers - the input I can see at the start of the execution is only

{
   "surname::"TESTSURNAME"
}

I have inputPath set to $ and the same for the payload.

All the suggestions I've found online point to the mapping template but I can not get it to work - any ideas what I'm doing wrong?

  • The input to the Step Functions is only the string in the input property, so you will need to compose the input with both the body and the headers. At the core, API Gateway is calling StartExecution.

3 Answers
1

You should modify your mapping template to include the headers as part of the Input param as this is the only field which is passed to the Step Functions execution.

Something like this (did not actually try it so there may be some syntax mistakes):

#set($inputbody = $input.json('$'))
{
   "method": "$context.httpMethod",
   "input": { 
       "$util.escapeJavaScript($inputbody)",
       "headers": {
          #foreach($param in $input.params().header.keySet())
          "$param": "$util.escapeJavaScript($input.params().header.get($param))"
          #if($foreach.hasNext),#end
          #end
      }
   }
   "stateMachineArn": "MyStateMachineARN"
}
profile pictureAWS
EXPERT
Uri
answered 2 years ago
0

I've gotten this to work for single request headers, but this only works if you know the key of the header in advance. For example:

#set($body = $input.json('$'))
#set($token = $input.params().header.get('x-api-token'))
                    {
                        "input":"{\"token\":\"$util.escapeJavaScript($token).replaceAll("\\\\'", "'")\",\"body\":$util.escapeJavaScript($body).replaceAll("\\\\'", "'")}",
                        "stateMachineArn": "arn:aws:states:eu-central-1:xxxx:stateMachine:xxxx"
                    }

Here, 'x-api-token' is the key of the example HTTP header. We set the value of this header in the JSON input object that is passed into the state machine. The request body is set as well.

It doesn't match OP's question exactly, but might still be useful for someone searching on this topic.

Ejnar
answered 2 months ago
  • If you want to deploy this via CDK, you'll need to escape all backlashes correctly:

    #set($body = $input.json('$'))
    #set($x-api-token = $input.params().header.get('x-api-token'))
    {
    "input":"{\\\"x-api-token\\\":\\\"$util.escapeJavaScript($x-api-token).replaceAll.replaceAll("\\\\'", "'")\\\",\\\"body\\\":$util.escapeJavaScript($body).replaceAll("\\\\'", "'")}",
    "stateMachineArn": "${stateMachineArn}"
    }
    
0

This answer don't work anymore, it returns: Endpoint response body before transformations: {"__type":"com.amazon.coral.service#SerializationException"}

This is quite frustrating, to be honest. There should be a way to pass all parameters EASILY to the step functions without this much hassle.

answered 6 months ago

You are not logged in. Log in to post an answer.

A good answer clearly answers the question and provides constructive feedback and encourages professional growth in the question asker.

Guidelines for Answering Questions