August Williams
August Williams

Reputation: 929

Dynamodb.put works fine when running a lambda test configuration, but not when invoking the lambda through API gateway

I have an API gateway, which triggers a Lambda function. The Lambda function then writes an item to DynamoDb. The API gateway can reach and trigger the Lambda function fine, as I can see CloudWatch logs after sending a POST request.

The code for the Lambda function is below:

const AWS = require('aws-sdk');

const dynamodb = new AWS.DynamoDB.DocumentClient({region: 'eu-west-1'});

exports.handler = async (event) => {
    console.log("event.body contents", event.body);
    console.log("Inserting into DynamoDb...");
    await dynamodb.put(event.body).promise();
    return {
        statusCode: 200,
        body: JSON.stringify({message: 'Success'})
    };

};

I run a test configuration, with the following input which goes into event:

{
  "body": {
    "TableName": "TestTable",
    "Item": {
      "IngameName": "SomeName",
      "Timestamp": "Fri Oct 09 2020 12:26:12 GMT+0100 (British Summer Time)",
    }
  }
}

After running the test configuration, the item is written into DynamoDb as expected. I can also see in CloudWatch logs, that the following has been printed for event.body, which were the parameters for dynamodb.put:

{
    "TableName": "TestTable",
    "Item": {
        "IngameName": "SomeName",
        "Timestamp": "Fri Oct 09 2020 12:26:12 GMT+0100 (British Summer Time)",
    }
}

So, when running the Lambda function from a test configuration, everything works fine. However, when I invoke through API gateway, I get the following error (I shortened it a bit):

 "MultipleValidationErrors: There were 2 validation errors:",
        "* MissingRequiredParameter: Missing required key 'TableName' in params",
        "* MissingRequiredParameter: Missing required key 'Item' in params"

This is complaining that TableName and Item are missing. However, the print for event.body shows exactly the same output, as when the test configuration was carried out:

{
    "TableName": "TestTable",
    "Item": {
        "IngameName": "SomeName",
        "Timestamp": "Fri Oct 09 2020 12:26:12 GMT+0100 (British Summer Time)",
    }
}

Why does it complain that required keys are missing when invoking through API gateway, but works fine when running the test configuration, when the parameters for dynamodb.put are the same?

Upvotes: 0

Views: 485

Answers (1)

Seth Geoghegan
Seth Geoghegan

Reputation: 5747

While the content of event.body looks correct, it's a string, which is not what the put operation is expecting. The put operation requires a map. You could try something like this:

let requestBody = JSON.parse(event.body)
console.log(requestBody.TableName)

I don't know how you have your application set up, but be careful about passing the content of the request body directly to the put operation. If this function is exposed publicly, that could have bad consequences. For example, callers could decide to send the request to another table name, introduce new attributes to your table, etc. Instead, consider parsing arguments from the request body and passing them into the put operation manually.

const AWS = require('aws-sdk');

const dynamodb = new AWS.DynamoDB.DocumentClient({region: 'eu-west-1'});

exports.handler = async (event) => {
    let requestBody = JSON.parse(event.body)
    console.log("event.body contents", event.body);
    console.log("Inserting into DynamoDb...");
    await dynamodb.put(
        {
            "TableName": "TestTable",
            "Item": {
                "IngameName": requestBody.IngameName,
                "Timestamp": requestBody.Timestamp,
            }
        }
    ).promise();
    return {
        statusCode: 200,
        body: JSON.stringify({message: 'Success'})
    };

};

Upvotes: 3

Related Questions