Search code examples
amazon-web-servicesaws-api-gatewayaws-step-functions

How to change response from AWS StepFunction in API Gateway HTTP


I'm configuring API Gateway with HTTP -> Step Function -> Lambda, all work fine except I can't exclude some fields from the response getting from API Gateway or Step Function. Currently the response includes many unnecessary data.

{
  "billingDetails": {
    "billedDurationInMilliseconds": 100,
    "billedMemoryUsedInMB": 64
  },
  "executionArn": "arn:aws:states:us-west-2:***:express:ExpressStateMachine:********",
  "input": "{}",
  "inputDetails": {
    "__type": "com.amazonaws.swf.base.model#CloudWatchEventsExecutionDataDetails",
    "included": true
  },
  "name": "*********",
  "output": "{\"billedDurationInMilliseconds\":100,\"billedMemoryUsedInMB\":64}",
  "outputDetails": {
    "__type": "com.amazonaws.swf.base.model#CloudWatchEventsExecutionDataDetails",
    "included": true
  },
  "startDate": 1.667486785389E9,
  "stateMachineArn": "arn:aws:states:us-west-2:***:stateMachine:ExpressStateMachinePartnerMock",
  "status": "SUCCEEDED",
  "stopDate": 1.667486785466E9
}

I want in the body only the output as a JSON and specifically use HTTP not REST option in API Gateway, I was thinking as well using Lambda to StepFunction, but this is not acceptable since there are many stages in step function, I tried using response mapping in API Gateway but all I could do is put or rewrite data into header, it looks like I can map only header and response code. Is it possible to configure API Gateway so that body returned from StepFunction can be replaced.


Solution

  • What you are looking for is in Integration Response of your method: Mapping Templates. It allowes you to modify the body of the response.

    As you, I wanted to get ride of unwanted informations and have a better access to output data as JSON.

    Here is a template you can start with:

    #set($inputRoot = $input.path('$'))
    {
      "name" : "$inputRoot.name",
      "output" : $inputRoot.output,
      "startDate" : $inputRoot.startDate,
      "status" : "$inputRoot.status",
      "stopDate" : $inputRoot.stopDate
    }
    

    In the response, output will be in JSON and not stringifyed. Alternatively, you can have a look at $util.parseJson

    If you, or anyone, want to use it with CDK, pay attention to the ResponseModels. The response model for your statusCode have to be coherent with the template.

    exemple 1: for statusCode 200, response model is Model.EMPTY_MODEL so responseTemplate have to be "" (empty string)

    exemple 2: for statusCode 200, response model is myModel so responseTemplate cannot be "" (empty string)

    Here is the same template but declared in CDK TS:

    responseTemplates: {
        "application/json": "#set($inputRoot = $input.path(\"$\")) { \"name\": \"$inputRoot.name\", \"output\" : $inputRoot.output, \"startDate\" : $inputRoot.startDate, \"status\" : \"$inputRoot.status\", \"stopDate\" : $inputRoot.stopDate}"
    }
    

    Useful information can be found here in aws doc:

    https://docs.aws.amazon.com/apigateway/latest/developerguide/rest-api-data-transformations.html

    Also Cloud Guru have made a video on this subject:

    https://www.youtube.com/watch?v=4DGhYtR2S2k&ab_channel=CloudGuru