Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to test AWS Lambda handler locally using NodeJS?

I am following these instructions to create a basic web scraper that executes in Lambda. I have experience writing selenium code, but not with Node JS. I got the project running in Lambda, but when I tried editing the project locally in order to execute the selenium code I want, It doesn't work. Anything in the exports.handler doesn't get executed when I run node index.js. How would I execute this project locally? Thanks!

like image 595
kroe761 Avatar asked Aug 25 '18 16:08

kroe761


People also ask

How do I run a Lambda function locally?

Step 1: Download SAM local Windows Install SAM CLI using an MSI in either the 64 bit or 32 bit versions. Step 2: Verify that the installation succeeded and version with the command below. Step 3: Write your lambda function or clone it from Github to run locally, making sure to add Template. yaml on the root level.


4 Answers

This is what I did:

index.js

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

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

    return response;
};

package.json

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

event.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"
        }
      }
    }
  ]
}

Shell

npm run locally

Output

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

hello world
Promise { { statusCode: 200, body: '"Hello from Lambda!"' } }
like image 110
jmk Avatar answered Oct 22 '22 03:10

jmk


You need to call your handler function from another file lets say testHandler.js in order to run via NodeJs.

This will be done like this

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

Now you can use node testHandler.js to test your handler function.

EDIT: Sample Event and content data as requested

Event:

{
    "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
}

Content:

{
    "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"
}
like image 45
NAVIN Avatar answered Oct 22 '22 04:10

NAVIN


In your index.js, just defined and exported a handler function, but no one calls it. In the Lambda environment, some AWS code will call this handler with message. In your local environment, you have to call your handler by yourself.

You could also have a look of this doc, it is a way to "simulate" Lambda in local environment.

like image 2
John Avatar answered Oct 22 '22 04:10

John


Perhaps the simplest way to get started, after some testing (with 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));
  }
);
like image 2
Jimmy_m Avatar answered Oct 22 '22 04:10

Jimmy_m