AWS Lambda:澄清从事件对象检索数据

Vic*_*tor 4 javascript amazon-web-services node.js aws-lambda aws-api-gateway

目前,我认为我对如何从lambda函数提取/传递数据有基本的误解,我正在寻求澄清

示例:假设我想将一些数据传递给lambda函数,即{"hello":"world"}通过在AWS API Gateway中创建REST端点将数据传递给该Lambda函数来实现

目前,我了解有三种提取数据的方法:

1)event.queryStringParameters(有意义)

例如 我们可以将查询参数附加到请求URL:https : //fakefakefake.execute-api.us-west-2.amazonaws.com/test/myapi?hello=world以及lambda函数中:

const data = event.queryStringParameters.hello; // 'world'
Run Code Online (Sandbox Code Playgroud)

2)event.body(很有意义,由于“ Lambda代理集成”,这是可能的)

例如 如果我们使用Lambda代理集成将数据附加到POST / PUT / etc请求的主体中(即转发所有数据),则可以event.body在lambda函数中通过&访问它(但请确保JSON.parse event.body)因为Lambda代理集成将通过字符串化JSON(无效/“真实” JSON)传递:

const parsedBody = JSON.parse(event.body); // should wrap in try/catch
const data = parsedBody.hello; // 'world'
Run Code Online (Sandbox Code Playgroud)

3)直接在事件对象上(不清楚)

例如 目前尚不清楚这种情况-通过API网关中的REST端点设置将数据传递给lambda函数,然后可以从事件对象直接访问它?

const data = event.hello; // 'world'
Run Code Online (Sandbox Code Playgroud)

例如在案例3中,如何在Lambda函数中的事件对象上“直接”传递数据的示例是什么?我认为这种情况要求我在设置API / Lambda时创建一个“映射模板”,但是我仍然不清楚。

对于简单的Node脚本,情况2似乎具有从字符串化JSON解析事件主体的“开销”,因此这是可以理解的缺点,但是除了如何做到这一点,为什么情况3或何时将是情况3?

Vic*_*tor 7

基于 Matus 的见解,我现在可以更好地回答上面的其余问题:

  • “什么是如何在 Lambda 函数中的事件对象上“直接”传递数据的示例,例如情况 #3?

使用 Lambda 设置 API Gateway 以发送特定数据时,您需要使用在 AWS API Gateway 中设置的映射模板。

该映射模板本身是用Apache Foundation的Velocity Template Language (VTL)编写的。Ex 用于附加“hello”数据,以便它可以作为 访问const data = event.hello; // world,例如:

    { 
      "hello": $input.params('$hello')
    }
Run Code Online (Sandbox Code Playgroud)

注意: VTL 非常强大,以上不是一个实际的使用示例,而是最小数量的 VTL 只是为了传达想法,请参阅此处此处了解更多详细信息

跳过界面来设置映射模板对于初学者示例来说有点考验,所以这里是图解步骤:

API 步骤

警告:请务必仔细检查编辑器中实际显示的内容,因为在更改下拉列表时,映射模板上可能偶尔会出现一些奇怪/意外的行为。有时您还会遇到涉及映射模板的无法恢复的问题,最好在开始时删除该方法并从 API 网关重新启动。

  • “对于一个简单的 Node 脚本,案例 2 似乎具有从字符串化 JSON 解析事件主体的“开销”,因此这是一个可以理解的缺点,但为什么或何时案例 3 是更理想的方法?

这完全取决于您的 Lambda 如何接收其数据。

Matus 的关键见解是,这最终都是一个实现细节。这个人为示例中的 Lambda(即通过 AWS 网关设置 REST API,向该 API 发送 GET/POST 并让 lambda 对数据执行某些操作)可以通过 3 种方式检索数据:

(1) 网址参数 const data = event.queryStringParameters.hello; // world

(2) 请求体const data = event.body.hello; // world(见下面的注释)

(3)直接在事件对象上 const data = event.hello; // world

注意 2:这需要选择 (a) Lambda Proxy Integration而不是使用映射模板,并且在您的代码中,您需要JSON.parse在访问数据之前使用事件正文,请参阅此答案以获取更多详细信息

所有这一切都取决于从 API Gateway 提供的内容。在这个特定示例中,我谈论的是执行 REST 请求以在 API 网关端点上传递数据,然后由 Lambda 处理该端点——但许多其他服务/触发器可以将数据发送到 Lambda 脚本进行分析。

其他有用的资源:

前任。一个玩具 Lambda 函数会回显 POST 的任何内容:

let client = null; // Data outside function handler (ex a DB connection or an incrementing value) can change within the handler code below and persist between Lamba invocations so long as the container is still "warm", see more for details: https://docs.aws.amazon.com/lambda/latest/dg/running-lambda-code.html

exports.handler = async (event, context) => {
    let data = {};

    // Lambda Proxy Integration
    if (event && event.body) {
        try {
            data = JSON.parse(event.body);
        } catch(e) { 
            return {
                statusCode: 400,
                body: JSON.stringify({message: 'There was an error parsing the JSON data posted to this endpoint', error:e})
            }
        }
    }

    try {

        // Echo back the data or perform transformations, pass on to another service, etc
        const response = {
            statusCode: 200,
            body: JSON.stringify({message: 'Data submitted', data})
        };

        return response;

    } catch(e) {
        // Report errors related with connection, auth, DB write, etc
        return {
          statusCode: 409,
          body: JSON.stringify({message: 'There was some type of catastrophic error', error:e})
      }
   }
};
Run Code Online (Sandbox Code Playgroud)


Mat*_*ava 6

Lambda是独立服务,不需要与API Gateway集成。queryStringParametersbodybody mapping templates,所有这一切都是具体的不LAMBDA,但LAMBDA - API网关集成。

如果您将Lambda与其他服务一起使用,则数据通常直接通过event对象传递,没有太多理由以其他方式传递数据。

例如,您可以将Lambda函数订阅到S3存储桶,并使用它以编程方式处理事件,例如文件上传到存储桶。在这种情况下,存储桶名称,对象密钥,对象数据,元数据等信息将直接通过event对象传递。

而且,当将Lambda与API Gateway结合使用时,为什么要使用body mapping templates直接通过event对象将数据传递给Lambda函数的功能?因为您可以更轻松地重用该功能用于其他目的(如果在您的方案中可行),因为您的Lambda函数将具有更简单的接口,而不是与API Gateway集成紧密相关的接口。

例如,您可以具有一个函数,该函数对传入的数字执行一些计算,这些数字既可以通过API网关调用,也可以直接从应用程序中调用。如果期望的话,使用这种功能会容易得多event.xevent.y而不是使用某些event.queryStringParameter.x可能在API网关之外没有意义的功能。