【问题标题】:Dynamodb.put works fine when running a lambda test configuration, but not when invoking the lambda through API gatewayDynamodb.put 在运行 lambda 测试配置时工作正常,但在通过 API 网关调用 lambda 时却不行
【发布时间】:2020-10-10 00:08:54
【问题描述】:

我有一个触发 Lambda 函数的 API 网关。然后 Lambda 函数将一个项目写入 DynamoDb。 API 网关可以正常访问并触发 Lambda 函数,因为我可以在发送 POST 请求后看到 CloudWatch 日志。

Lambda 函数的代码如下:

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'})
    };

};

我运行一个测试配置,下面的输入进入event

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

运行测试配置后,项目按预期写入 DynamoDb。我还可以在 CloudWatch 日志中看到,为 event.body 打印了以下内容,这是 dynamodb.put 的参数:

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

因此,当从测试配置运行 Lambda 函数时,一切正常。但是,当我通过 API 网关调用时,出现以下错误(我将其缩短了一点):

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

这是在抱怨缺少 TableNameItem。但是,event.body 的打印显示与执行测试配置时完全相同的输出:

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

为什么在通过API网关调用时提示缺少所需的密钥,但在运行测试配置时却可以正常工作,而dynamodb.put的参数相同?

【问题讨论】:

  • 在测试配置调用和通过api网关调用的时候可以放控制台日志吗?
  • 我在下面提供的答案对您有帮助吗?

标签: node.js amazon-web-services aws-lambda amazon-dynamodb


【解决方案1】:

虽然event.body 的内容看起来正确,但它是一个字符串,这不是put 操作所期望的。 put 操作需要映射。你可以试试这样的:

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

我不知道您是如何设置应用程序的,但请注意将请求正文的内容直接传递给put 操作。如果此功能公开,可能会产生不良后果。例如,调用者可以决定将请求发送到另一个表名,向您的表引入新属性等。相反,请考虑从请求正文中解析参数并将它们手动传递到put 操作。

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'})
    };

};

【讨论】:

  • +1 获取关于此处安全性的评论。永远不要让客户端指定要写入的表或正在执行的操作。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多