Format body mapping templates in API Gateway

Question:

Need your help! I have the below Lambda function that will take inputs from the API Gateway (using RestAPI Post method) and pass the same as Payload to a second Lambda function.

    def lambda_handler(event, context):
    
        customerName = event['Name']
        customerEmail = event['EmailAddress']
        
        input = {"Name": customerName, "EmailAddress": customerEmail}
        
        response = lambda_client.invoke(
        FunctionName='arn_of_the_lambda_to_be_invoked',
        InvocationType='Event',
        Payload=json.dumps(input))

Below will be my input to the API Gateway in JSON format –

    {
        "Name": "TestUser",
        "EmailAddress": "[email protected]"
    }

Have tried Lambda proxy integration and Generic Body Mapping templates (from here). In both occasions, API Gateway returns the below error –

Response Body:

{
  "errorMessage": "'Name'",
  "errorType": "KeyError",
  "stackTrace": [
    "  File "/var/task/lambda_function.py", line 7, in lambda_handlern    customerName = event['Name']n"
  ]
}

With the same JSON input when I directly invoke the Lambda from the Lambda console, it works. I know that API Gateway, along with the JSON body, pushes many other things. However, I’m unable to figure out.

How do I get this working?

Asked By: SupreetK

||

Answers:

In the lambda proxy integration, the event will be in the following format.

{
    "resource": "Resource path",
    "path": "Path parameter",
    "httpMethod": "Incoming request's method name"
    "headers": {String containing incoming request headers}
    "multiValueHeaders": {List of strings containing incoming request headers}
    "queryStringParameters": {query string parameters }
    "multiValueQueryStringParameters": {List of query string parameters}
    "pathParameters":  {path parameters}
    "stageVariables": {Applicable stage variables}
    "requestContext": {Request context, including authorizer-returned key-value pairs}
    "body": "A JSON string of the request payload."
    "isBase64Encoded": "A boolean flag to indicate if the applicable request payload is Base64-encode"
}

the values you posted will be inside body as a json string. you need to parse the json.

import json

def lambda_handler(event, context):

    fullBody = json.loads(event['body'])
    print('fullBody: ', fullBody)
    body = fullBody['body']
    customerName = body['Name']
    customerEmail = body['EmailAddress']
    
    input = {"Name": customerName, "EmailAddress": customerEmail}
    
    response = lambda_client.invoke(
    FunctionName='arn_of_the_lambda_to_be_invoked',
    InvocationType='Event',
    Payload=json.dumps(input))

Input format of a Lambda function for proxy integration

Please remember that the lambda is expected to return the output in the following format for Lambda Proxy integration.

{
    "isBase64Encoded": true|false,
    "statusCode": httpStatusCode,
    "headers": { "headerName": "headerValue", ... },
    "multiValueHeaders": { "headerName": ["headerValue", "headerValue2", ...], ... },
    "body": "..."
}
Answered By: Arun Kamalanathan

As best practice, you should NOT call a Lambda function from another Lambda function. Instead you should use AWS Step Function (SFN) to orchestrate your workflow. Amazon Managed Airflow is another solution.

SFN helps you with chaining Lambda output -> input, monitoring execution, debugging your chain of execution and visualizing the data flow through your workflow.

SFN can, not only call Lambda functions, but many other AWS Services APIs as well.

Answered By: koxon