如何使用 NodeJS 在本地测试 AWS Lambda 处理程序?

问题描述 投票:0回答:8

我按照这些说明创建一个在 Lambda 中执行的基本网络抓取工具。我有编写 selenium 代码的经验,但没有使用 Node JS 的经验。我在 Lambda 中运行了该项目,但是当我尝试在本地编辑该项目以执行我想要的 selenium 代码时,它不起作用。当我运行

exports.handler
时,
node index.js
中的任何内容都不会被执行。我将如何在本地执行这个项目?谢谢!

javascript node.js aws-lambda serverless-framework
8个回答
79
投票

这就是我所做的:

index.js

exports.handler = async (event) => {
    console.log('hello world');

    const response = {
        statusCode: 200,
        body: JSON.stringify('Hello from Lambda!')
    };

    return response;
};

package.json

// using require
"scripts": {
  "locally": "node -e \"console.log(require('./index').handler(require('./event.json')));\""
}

// or the following for ESM using import
"scripts": {
  "locally": "node --input-type=module -e \"import {handler} from './index.mjs'; console.log(await handler(JSON.parse(fs.readFileSync('./event.json'))));\""
}

事件.json

{
  "Records": [
    {
      "eventVersion": "2.0",
      "eventSource": "aws:s3",
      "awsRegion": "eu-central-1",
      "eventTime": "1970-01-01T00:00:00.000Z",
      "eventName": "ObjectCreated:Put",
      "userIdentity": {
        "principalId": "AIDAJDPLRKLG7UEXAMPLE"
      },
      "requestParameters": {
        "sourceIPAddress": "127.0.0.1"
      },
      "responseElements": {
        "x-amz-request-id": "C3D13FE58DE4C810",
        "x-amz-id-2": "FMyUVURIY8/IgAtTv8xRjskZQpcIZ9KG4V5Wp6S7S/JRWeUWerMUE5JgHvANOjpD"
      },
      "s3": {
        "s3SchemaVersion": "1.0",
        "configurationId": "testConfigRule",
        "bucket": {
          "name": "my-bucket",
          "ownerIdentity": {
            "principalId": "A3NL1KOZZKExample"
          },
          "arn": "arn:aws:s3:::my-bucket"
        },
        "object": {
          "key": "HelloWorld.jpg",
          "size": 1024,
          "eTag": "d41d8cd98f00b204e9800998ecf8427e",
          "versionId": "096fKKXTRTtl3on89fVO.nfljtsv6qko"
        }
      }
    }
  ]
}

外壳

npm run locally

输出

> node -e "console.log(require('./index').handler({}));"

hello world
Promise { { statusCode: 200, body: '"Hello from Lambda!"' } }

49
投票

您需要从另一个文件调用您的处理函数(例如

testHandler.js
)才能通过 NodeJs 运行。

这将像这样完成

//import your handler file or main file of Lambda
let handler = require('./handler');

//Call your exports function with required params
//In AWS lambda these are event, content, and callback
//event and content are JSON object and callback is a function
//In my example i'm using empty JSON
handler.handlerEvent( {}, //event
    {}, //content
    function(data,ss) {  //callback function with two arguments 
        console.log(data);
    });

现在您可以使用

node testHandler.js
来测试您的处理函数。

编辑:示例事件和内容数据按要求

活动:

{
    "resource": "/API/PATH",
    "path": "/API/PATH",
    "httpMethod": "POST",
    "headers": {
        "Accept": "*/*",
        "Accept-Encoding": "gzip, deflate, br",
        "Accept-Language": "en-GB,en-US;q=0.9,en;q=0.8",
        "cache-control": "no-cache",
        "CloudFront-Forwarded-Proto": "https",
        "CloudFront-Is-Desktop-Viewer": "true",
        "CloudFront-Is-Mobile-Viewer": "false",
        "CloudFront-Is-SmartTV-Viewer": "false",
        "CloudFront-Is-Tablet-Viewer": "false",
        "CloudFront-Viewer-Country": "IN",
        "content-type": "application/json",
        "Host": "url.us-east-1.amazonaws.com",
        "origin": "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop",
        "User-Agent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
        "Via": "2.0 XXXXXXXXXXXXXX.cloudfront.net (CloudFront)",
        "X-Amz-Cf-Id": "XXXXXXXXXX51YYoOl75RKjAWEhCyna-fuQqEBjSL96TMkFX4H0xaZQ==",
        "X-Amzn-Trace-Id": "Root=1-XXX03c23-25XXXXXX948c8fba065caab5",
        "x-api-key": "SECUREKEY",
        "X-Forwarded-For": "XX.XX.XXX.XXX, XX.XXX.XX.XXX",
        "X-Forwarded-Port": "443",
        "X-Forwarded-Proto": "https"
    },
    "multiValueHeaders": {
        "Accept": [ "*/*" ],
        "Accept-Encoding": [ "gzip, deflate, br" ],
        "Accept-Language": [ "en-GB,en-US;q=0.9,en;q=0.8" ],
        "cache-control": [ "no-cache" ],
        "CloudFront-Forwarded-Proto": [ "https" ],
        "CloudFront-Is-Desktop-Viewer": [ "true" ],
        "CloudFront-Is-Mobile-Viewer": [ "false" ],
        "CloudFront-Is-SmartTV-Viewer": [ "false" ],
        "CloudFront-Is-Tablet-Viewer": [ "false" ],
        "CloudFront-Viewer-Country": [ "IN" ],
        "content-type": [ "application/json" ],
        "Host": [ "apiurl.us-east-1.amazonaws.com" ],
        "origin": [ "chrome-extension://fhbjgbiflinjbdggehcddcbncdddomop" ],
        "User-Agent": [ "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36" ],
        "Via": [ "2.0 XXXXXXXXXXXXXX.cloudfront.net (CloudFront)" ],
        "X-Amz-Cf-Id": [ "XXXXXXXXXhCyna-fuQqEBjSL96TMkFX4H0xaZQ==" ],
        "X-Amzn-Trace-Id": [ "Root=1-XXXXXXX67339948c8fba065caab5" ],
        "x-api-key": [ "SECUREAPIKEYPROVIDEDBYAWS" ],
        "X-Forwarded-For": [ "xx.xx.xx.xxx, xx.xxx.xx.xxx" ],
        "X-Forwarded-Port": [ "443" ],
        "X-Forwarded-Proto": [ "https" ]
    },
    "queryStringParameters": null,
    "multiValueQueryStringParameters": null,
    "pathParameters": null,
    "stageVariables": null,
    "requestContext": {
        "resourceId": "xxxxx",
        "resourcePath": "/api/endpoint",
        "httpMethod": "POST",
        "extendedRequestId": "xxXXxxXXw=",
        "requestTime": "29/Nov/2018:19:21:07 +0000",
        "path": "/env/api/endpoint",
        "accountId": "XXXXXX",
        "protocol": "HTTP/1.1",
        "stage": "env",
        "domainPrefix": "xxxxx",
        "requestTimeEpoch": 1543519267874,
        "requestId": "xxxxxxx-XXXX-xxxx-86a8-xxxxxa",
        "identity": {
            "cognitoIdentityPoolId": null,
            "cognitoIdentityId": null,
            "apiKey": "SECUREAPIKEYPROVIDEDBYAWS",
            "cognitoAuthenticationType": null,
            "userArn": null,
            "apiKeyId": "xxXXXXxxxxxx",
            "userAgent": "Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.106 Safari/537.36",
            "accountId": null,
            "caller": null,
            "sourceIp": "xx.xxx.xxx.xxx",
            "accessKey": null,
            "cognitoAuthenticationProvider": null,
            "user": null
        },
        "domainName": "url.us-east-1.amazonaws.com",
        "apiId": "xxxxx"
    },
    "body": "{\n    \"city\": \"Test 1 City\",\n    \"state\": \"NY\",\n    \"zipCode\": \"11549\"\n}",
    "isBase64Encoded": false
}

内容:

{
    "callbackWaitsForEmptyEventLoop": true,
    "logGroupName": "/aws/lambda/lambda-name",
    "logStreamName": "2018/11/29/[$LATEST]xxxxxxxxxxxb",
    "functionName": "lambda-name",
    "memoryLimitInMB": "1024",
    "functionVersion": "$LATEST",
    "invokeid": "xxxxx-xxx-11e8-xxx-xxxxxxxf9",
    "awsRequestId": "xxxxxx-xxxxx-11e8-xxxx-xxxxxxxxx",
    "invokedFunctionArn": "arn:aws:lambda:us-east-1:xxxxxxxx:function:lambda-name"
}

2
投票

在您的

index.js
中,刚刚定义并导出了一个处理函数,但没有人调用它。在 Lambda 环境中,某些 AWS 代码将使用消息调用此处理程序。在您本地的环境中,您必须自己调用您的处理程序。

您还可以看看这个文档,它是一种在本地环境中“模拟”Lambda 的方法。


2
投票

您可以查看lambda-local。它比上面接受的答案更奇特。例如,它支持传递环境变量并使用 JSON 文件作为负载。


2
投票

经过一些测试(使用 Node 14.17.3),这可能是最简单的入门方法

let handler = require('./index.js');

handler.handler ( 
  {}, // event
  {}, // content 
  (error, result) => { 
     if (error) console.error(JSON.stringify(error, null, 2));
     else console.log(JSON.stringify(result, null, 2));
  }
);

2
投票

这里我给出了同步调用一般情况的解决方案。

入口点中的函数签名

index.js

exports.handler = function(event, context, callback) {

  1. 创建一个调用者文件,例如
    testIndex.js
  2. 提供以下内容:
    /**
    This is a caller for ./index.js
    */
    const thatIndex = require('./index');

    const EVENT = {
      "somekey": {
        "somesubkey": "somevalue"
      }
    }

    thatIndex.handler (
        // event
        EVENT,
        // context
        {},
        // callback function with two arguments
        function(err, payload) {
            console.log(err);
            console.log(payload);
        }
    );
  1. 返回节点控制台(建议使用 Docker 容器)
  2. 如果你的index.js需要它们,你可以使用环境变量:用
    export MYVAR1=myvalue1
  3. 定义每个环境变量
  4. 运行您的呼叫者:
    node testIndex.js
  5. 控制台应该输出有效负载,前提是您的主文件(入口点)承诺调用与以下内容链接在一起:(示例)
    .then(() => callback(null, {
       statusCode: 301,
       headers: {'location': process.env.URL + '/' + somekey },
       body: '',
       })
    )
    .catch(err => callback(err))

提示:如果您发现调用的是之前的代码,则可能需要使用

node clean cache
清理缓存。

其他提示:在AWS环境中,您不需要压缩

node_modules/aws-sdk
文件夹,因为它将成为标准执行上下文的一部分。但在您的测试机器上您将需要这样做。所以,在开发模式下,简单运行
npm install
,而不是
npm install --omit=dev

因此,在压缩包含函数的文件夹之前,只需递归删除

node_modules
文件夹,并使用
npm install --ommit=dev

重建依赖项

压缩文件夹的示例:

zip -r ..\resizeImage.zip .

这就是您的

package.json
文件 可能 包含的内容:

  "dependencies": {
    "sharp": "^0.27.2"
  },
  "devDependencies": {
    "aws-sdk": "^2.1195.0"
  }

1
投票

0
投票

国际海事组织。测试 lambda 的最佳方法就是实际测试它!这意味着什么?只需使用一些测试库(例如

jest
)并简单地在
handler
函数上创建一个测试。模拟您需要的任何内容,并提供一些您期望进入 lambda 的数据(如果需要,可用于
event
context
)。就是这样。您已经编写了一些测试,并且同时有一种快速测试 lambda 的方法。

© www.soinside.com 2019 - 2024. All rights reserved.