Lambdify is a set of tools that makes building and consuming AWS Lambda functions easier.
Basic HTTP Lambda Function - JSON Response
const lambdify = require('lambdify');
const helloWorld = (request, response) => {
response.json({ message: `Hello User, I see that you are coming from IP: ${request.getIp()}` });
return response;
};
exports.handler = lambdify(helloWorld);
Basic HTTP Lambda Function - HTML Response
const lambdify = require('lambdify');
const helloWorld = (request, response) => {
response.html(`Hello User, I see that you are coming from IP: ${request.getIp()}`);
return response;
};
exports.handler = lambdify(helloWorld);
Basic S3 Trigger
const lambdify = require('lambdify');
const AWS = require('aws-sdk');
const s3 = new AWS.S3({ apiVersion: '2006-03-01' });
const run = async (request) => {
const { bucket, key } = request.getS3();
const file = await s3.getObject({ Bucket: bucket, Key: key }).promise();
if (file && file.Body) {
// Do something with the file
}
};
exports.handler = lambdify(run);
npm i lambdify
or
yarn add lambdify
Lambdify accepts a function and an array of middleware
const lambdify = require('lambdify');
const errorMiddleware = require('errorMiddleware');
const run = (request, response) => {
response.json({ foo: 'bar' });
return response;
};
exports.handler = lamdify(run, [errorMiddleware]);
This is the request object that is built from the lambda event
request.get(name)
- Get a value ofname
from a basic key value storerequest.getAuthToken()
- Get the authorization token from the requestrequest.getBody()
- Get the body of the event and parse into an object if JSONrequest.getContext()
- Get the lambda contextrequest.getCookie(name)
- Get value of cookiename
from API Gateway Requestrequest.getCookies()
- Get all cookies from API Gateway Requestrequest.getEvent()
- Get lambda eventrequest.getHeader(name)
- Get value of headername
from API Gateway Requestrequest.getHeaders()
- Get all headers from API Gateway Requestrequest.getIp()
- Get remote ip (handles X-Forwarded-For)request.getMethod()
- Get HTTP request method from API Gateway Requestrequest.getPath()
- Get URL path from API Gateway Requestrequest.getPathParams()
- Get path paramaters from API Gateway Requestrequest.getQueryParam(name)
- Get value of query parametername
from API Gateway Requestrequest.getQueryParams()
- Get query parameters from API Gateway Requestrequest.getS3()
- Get bucket and key from S3 Triggerrequest.getSns()
- Get record from SNS Triggerrequest.getSqs()
- Get records from SQS Triggerrequest.getUa()
- Get UserAgent from API Gateway Requestrequest.set(name, value)
- Set avalue
ofname
into a basic key value store
This is the response object that must be returned from your lambda function (or middleware)
Methods binary
, html
, json
, redirect
, xml
can be returned directly
response.binary(base64 | buffer, contentType)
- Build a binary responseresponse.enableCors()
- Enable CORS for an API Gateway responseresponse.getBody()
- Get the body of the responseresponse.getHeader(name)
- Get the value of headername
response.getHeaders()
- Get all headersresponse.getResponse()
- Get the lambda response objectresponse.getStatusCode()
- Get the status code of the responseresponse.html(body)
- Build an html responseresponse.json(body)
- Build a json responseresponse.file(filePath, contentType)
- Sends fileresponse.redirect(url, statusCode = 302)
- Build a redirect responseresponse.setBinaryResponse(value)
- Set the response as a binary response for API Gatewayresponse.setBody(body)
- Set the body of the responseresponse.setHeader(name, value)
- Setvalue
of headername
response.setStatusCode(value)
- Set the status code of the responseresponse.xml(body)
- Build an xml response
Middleware allows you to wrap your function with another function in such a way that you can execute code before or after your function runs. This is useful for instantiating database connections or error handling
const middleware = async (req, res, next) => {
const response = await next(req, res);
response.setHeader('Cookie', 'test=this');
return response;
};
module.exports = middleware;
Usage:
const lambdify = require('lambdify');
const middleware = require('./middleware');
const run = (request, response) => {
response.json({ foo: 'bar' });
return response;
};
exports.handler = lamdify(run, [middleware]);
const errorMiddleware = async (req, res, next) => {
try {
const response = await next(req, res);
return response;
} catch (error) {
// Fire off log to error system like raygun / sentry
res.setStatusCode(500);
return res.json({
message: error.message,
stack: error.stack,
status: 'error',
});
}
};
module.exports = errorMiddleware;
Usage:
const lambdify = require('lambdify');
const errorMiddleware = require('./errorMiddleware');
const run = (request, response) => {
response.json({ foo: 'bar' });
return response;
};
exports.handler = lamdify(run, [errorMiddleware]);
const knex = (config) => async (req, res, next) => {
const knex = require('knex')(config);
req.set('knex', knex);
try {
const response = await next(req, res);
await knex.destroy();
return response;
} catch (error) {
await knex.destroy();
throw error;
}
};
module.exports = knex;
Usage:
const lambdify = require('lambdify');
const knexMiddleware = require('./knexMiddleware');
const run = (request, response) => {
const knex = request.get('knex');
const user = knex('user').where({ id: request.getPathParam('userId') });
response.json({ user });
return response;
};
exports.handler = lamdify(run, [knexMiddleware(dbConfig)]);
Lambdify provides a router to enable your to attach a lambda to an ALB endpoint or a proxy+ api gateway path
const lambdify = require('lambdify');
const router = require('lambdify/router')(); # Mind the double parentheses here
const index = (req, res) => res.json({ foo: 'bar' });
router.path('get', '/', index);
exports.handlers = lambdify(router.serve);
This will match the method and path. The path can be a valid url path defined here
If key, value, fn are provided, it will match on the matching key / value inside the sqs request payload (single SQS message only). If just fn is provided, it will execute the fn when there is an SQS event
This is the fn that lambdify accepts
Lambdify provides a couple of helpers to help consume other local lambda functions and build / extend events.
Invoke is used to invoke other local lambda code correctly irregardless if the function uses callback, context or a standard response.
event
is the event payload that your lambda accepts. Seeevent
below for event creationfn
is the function handler
Example
const lambdify = require('lambdify');
const { event, invoke } = require('lambdify/helpers');
const run = (req, res) => {
const newEvent = event(req.getEvent(), { foo: 'bar' });
const fn = require('./otherProjectLambdaFunction/turnBarToBaz').handler;
const response = await invoke(newEvent, fn);
return res.json((JSON.parse(response.body));
// => { foo: 'baz' }
};
exports.handler = lambdify(run);
The goal of event is to ensure a consistent event payload to be sent to other lambda functions in a clean and consistent structure
originalEvent
is the original event object you wish to extendbody
is the new body payload being sent that is automaticallyJSON.stringify
'edoverrides
is an object that will override anything else in the original event
Run a webserver on your lambda instance! Express, Koa, etc should now run without a hitch.
This is very similar to aws-serverless-express. The main point being, it's a little more clean and simple to understand
Your Lambda Handler (usually index.js
)
const lambdaServer = require('lambdify/server');
const app = require('./app');
exports.handler = lambdaServer(app);
app.js
const express = require('express');
const app = express();
app.get('/', (req, res) => res.send('Hello World!'));
module.export = app;
And for testing locally (I like to name it server.js
)
const app = require('./app.js');
app.listen(3000, () => console.log('Now Listening'));
This focuses on simplicity and standard use cases. It also doesn't worry about legacy implementations of lambda callback / context use and is focused on Node 10 / 12 support only with an emphasis on async / await code
This was originally developed to handle next.js SSR on AWS Lambda. Officially there is no support and although packages like serverless-nextjs-plugin exist, they require more packages and the serverless deployment system.