Let’s learn about AWS Lamda local development, in this we are going to look into building, running, and testing a lambda in our own local machine.
Introduction
As the world is moving towards serverless computing, AWS Lambda is Amazon Web Services offering to the general masses, that provides an event-driven compute service that lets you run your code/ backend service without the hassle of managing servers. There are multiple framework offerings provided by different companies and cloud providers some include:
- AWS Amplify
- Zappa
- Architect
- Claudia.js
- AWS Lambda
Major benefits of using AWS lambda:
- More than 200 AWS services can trigger a lambda
- It can scale from 1 to 2 events per day to more than thousands of events per second
- It is cost-effective as you only pay for the computing time used by your code
- It runs concurrently
- It has low latency
Prerequisites
- Thorough understanding of JavaScript language
- Basic understanding of the NodeJS framework.
AWS Lamda local development
Serverless Application Model (SAM) Configuration
AWS SAM is an open-source framework for building serverless applications. It enables you to build and deploy serverless applications faster. SAM is an extension of AWS CloudFormation. SAM is built on top of the docker engine.
Configuring AWS and Making a SAM project
- Step one: Install the aws-cli
- Step two: Configure the aws-cli
- Step three: Install the sam-cli
step three
→
Scaffolding a Lambda Function using sam-cli
sam init
## for template source choose -> 1 - AWS Quick Start Templates
## for package type -> 1 - Zip (artifact is a zip uploaded to S3)
## for run time choose -> 1 - nodejs14.x (as the article is made for node)
## choose a name for your application
## for quick start application templates -> 1 - Hello World Example
After the creation of the project, let’s configure the app.js
file.
The file used for the scope of this article are:
hello-world/app.js
template.yaml
app.js
// app.js
let response;
exports.lambdaHandler = async (event, context) => {
try {
response = {
'statusCode': 200,
'body': JSON.stringify({
message: 'hello world',
})
}
} catch (err) {
console.log(err);
return err;
}
return response
};
The lambda handler runs right after the route runs. The lambda function has event and context parameters. Following is a brief overview of what values are present inside event and context parameters.
event
- event.body: Contains request body
- event.pathParameters: Contains path parameters → /hello/{id}/{name}
- event.queryStringParameters: Contains query parameters → /hello?name=lymn&id=10
Those are the mostly used ones.
context
functionName
– The name of the Lambda function.functionVersion
– The version of the function.memoryLimitInMB
– The Memory limit of the application
In the response, we send back statusCode, header, and body. The body contains data and messages.
template.yaml
## template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: simple lambda function
Globals: ##global variables for the lambdas
Function:
Timeout: 3 ## Max time this lamda can run for
Resources:
HelloWorldFunction:
Type: AWS::Serverless::Function ## Tells what kind of function it is
Properties:
CodeUri: hello-world/ ## File location where main function is present in
Handler: app.lambdaHandler ## Name of the main file and the runner function
Runtime: nodejs14.x ## Runtime of the application
Architectures:
- x86_64
Events:
HelloWorld:
Type: Api ## What kind of event is it
Properties:
Path: /hello ## Mount location of the function localhost:3000/app
Method: get ## what http method is it [get, post, put, delete, ...]
The template.yml
tells how the function should be built, and the location of the actual function. It builds the actual lambda function.
Now compile your first application
## compiling your first application
sam build
## running your first application
sam local start-api
## Running on http://127.0.0.1:3000/ should be present after starting
After application startup following route should be hit: http://localhost:3000/hello
Change made to app.js
will not be reflected during the time of running as it cannot hot reload. For making quick changes open the folder .aws-sam/build/functionName
this folder should have app.js. Changes made to the app.js is reflected in response but not in the app.js of hello-world/ app.js
.
After each change in application files open another terminal in the same directory then
sam build -p -c
The -p
-c
flag is used for:
-p
compiles multiple lambda functions in parallel-c
flag searches for cache and builds the applications changed part only
Working with environment variables
Make a file .env.json
inside the current working directory
.env.json
// .env.json
{
"Parameters": { // Keep environment variables inside Parameters
"CREATOR": "lymn",
"SITE": "http://hello.com"
}
}
After this, you need to add the environment variables inside the template.yml file under the global function if the scope of your environment variable is the global scope.
Globals:
Function:
Timeout: 3
Environment:
Variables:
CREATOR: !Ref CREATOR ## refers to the .env.json CREATOR key
SITE: !Ref SITE
!Ref gives reference to the parameters present inside the .env.json
file
For running applications that have system variable
sam local start-api --env-vars .env.json
--env-vars
.env.json
are:
--env-vars
notifies sam that there are environment variables in the application.env.json
has environment variables present inside them
Customizing the code
modified app.js
// app.js
exports.lambdaHandler = async (event, context) => {
let response;
try {
const site = process.env.SITE; // gets it through environment
const creator = process.env.CREATOR;
const body = JSON.parse(event.body); // response body
const pathParameters = event.pathParameters; // path parameters passed
const queryParameters = event.queryStringParameters; // query parameters
response = {
statusCode: 200, //status code to be sent
body: JSON.stringify({ // contains what data to be shown
data: { // put data inside data key
creator: creator,
site: site,
eventBody: body,
eventPath: pathParameters,
eventQuery: queryParameters,
},
message: "Operation success!", // message to be sent (vague)
}),
};
} catch (err) {
console.log(err);
return err;
}
return response; // returns the response back to the client
};
modified template.yaml
AWSTemplateFormatVersion: '2010-09-09'
Transform: AWS::Serverless-2016-10-31
Description: A Small Lambda Function
Globals: ##global variables for the lambdas
Function:
Timeout: 30 ## Max time this lamda can run for in seconds
MemorySize: 1024 ## Max memory size that this lambda can consume
Runtime: nodejs14.x ## Runtime of the application
Environment:
Variables:
CREATOR: !Ref CREATOR
SITE: !Ref SITE
Resources:
HelloWorldFunction: ## name of the function
Type: AWS::Serverless::Function ## Tells what kind of function it is
Properties:
CodeUri: hello-world/ ## File location where main function is present in
Handler: app.lambdaHandler ## Name of the main file and the runner function
Events:
HelloWorld:
Type: Api ## What kind of event is it
Properties:
Path: /hello/{id} ## id parameter is to be defined
Method: post ## what http method is it [get, post, put, delete, ...]
Build and run the function once again
sam build -p -c
sam local start-api --env-vars .env.json
Request POST
/hello/1?hello=helloworld&bye=byeworld
Response
The article showed the process of making a lambda function and invoking it. It showed briefly the things present inside of the event and context parameters of a function, working with query parameters and path parameters, working with environment variables, editing template files, the use of template files during the build of the application, and how to send a response back. As this works with user-sent inputs it should be validated for that look into How To Use Ajv In AWS Lambda Using SAM ? where Ajv is an amazing and light validation package for NodeJs.