AWS Lambda router for NodeJS

Overview

AWS Lambda Router for NodeJS

Build Status Coverage Status

A collection of tools to handle ApiGateway requests and direct function invocation calls on AWS Lambda. Use it as a stand-alone lib in a Lambda function or plugged-in to Apex or any other serverless framework on NodeJS. I'd recommend deploying and managing your Lambda functions with Apex and LambdaReq since they play nicely together.

Installation

npm install lambda-req --save

Deploy it with Apex

import LambdaReq from 'lambda-req'

const lambda = new LambdaReq()

// set APIGateway handlers
lambda.get('/lreqex_hello', (req, router)=> {
  const { params } = req
  return { message: 'hello world!', params }
})
lambda.post('/lreqex_hello', (req, router)=> {
  const { params } = req
  return { message: 'hello world!', params }
})

// set direct invocation handlers
lambda.proxy('hello', (req, router)=> {
  const { params } = req
  return { message: 'hello world!', params }
})

export default lambda.invoke

Use it stand-alone on Lambda

import LambdaReq from 'lambda-req'

// initialize Lambda with no params, pass them later from handler
const lambda = new LambdaReq()

// set handlers
lambda.get('/v1/test', (req, router)=> {})
lambda.proxy('migrate', (req, router)=> Promise.resolve({}))

// export the handler
// pass the event params on invocation time
export { handler: lambda.invoke }

Invoke other Lambdas

import LambdaReq, { LambdaProxy, LambdaReqError } from 'lambda-req'

const lambda = new LambdaReq()

// set APIGateway handlers
lambda.get('/lreqex_proxy', (req, router)=> {
  const { params } = req
  
  const proxy = new LambdaProxy()
  
  // Invoke another Lambda in the same AWS VPC
  return proxy.invoke('lreqex_hello', 'hello', params)
  .then((response)=> {
    return { message: 'Proxy response from lreqex_hello', response }
  })
  .catch((err)=> {
    console.error(err)
    throw new LambdaReqError({
      message: {
        error: {
          code: 'lambdaInvocationError',
          message: 'lreqex_hello Lambda is unresponsive.'
        }
      }
    })
  })
})

export default lambda.invoke

See more examples.

API

LambdaReq

This is the Lambda router object. It binds routes and proxies events for a Lambda handler.

.constructor([event = Object], [context = Object], [callback = function])

Pass in the lambda handler event, context and callback on object initialization. However, this is optional since they can be sent diectly on hanlder invocation.

Node 4.3:

const LambdaReq = require('lambda-req').default

function handler (event, context, callback) {
  const lambda = new LambdaReq(event, context, callback)
  lambda.invoke()
}

module.exports = { handler }

With Babel:

import LambdaReq from 'lambda-req'

function handler (event, context, callback) {
  const lambda = new LambdaReq(event, context, callback)
  lambda.invoke()
}

export { handler }

.get|.post|.put|.delete|.options(path = String, handler = function)

Shorthand methods for binding APIGateway route handlers. ALL APIGateway params (path, query, body) are passed through the params key on the req argument. A router instance is passed as the second handler arg. router._event and router._context are mapped to the original handler params.

const lambda = new LambdaReq(event, context, callback)

lambda.get('/test', handler)
lambda.post('/test', handler)
lambda.put('/test', handler)
lambda.delete('/test', handler)

lambda.invoke()

async function handler (req, router) {
  const { params, headers } = req
  return {}
}

A request to https://api-gateway-id.execute-api.eu-west-1.amazonaws.com/prod/test will fire up the GET handler on the /test route.

.proxy(name = String, handler = function)

Shorthand method for binding Lambda direct invocation handlers. Used for maintenance tasks (i.e. db migrations, cronjobs) and internal Lambda calls. Each proxy handler has a unique name, passed as a command key on the Lambda event. A direct call, proxies all the event data to the handler.

const lambda = new LambdaReq(event, context, callback)

lambda.proxy('db_migrate', handler)

lambda.invoke()

async function handler (req, router) {
  const { params } = req
  return {}
}

Invoke this functions from command line with aws-cli:

#!/usr/bin/env bash

PAYLOAD='{"command":"db_migrate","params":{"name":"users"}}'

aws lambda invoke \
  --function-name myFunction \
  --payload $PAYLOAD \
  out.log

or through aws-sdk:

import AWS from 'aws-sdk'

const config = {
  FunctionName: 'myFunction',
  Payload: JSON.stringify({ command: 'db_migrate', params: { name: 'users' } })
}
const lambda = new AWS.Lambda()
lambda.invoke(config).promise().then(response => JSON.parse(response.Payload))

.invoke([event = Object], [context = Object], [callback = function])

Invokes the handlers that match the current Lambda route from APIGateway or by a direct invocation call. Optionally, Lambda handler params will be passed along. It's recommended to export this method as a Lambda handler.

import LambdaReq from 'lambda-req'

const lambda = new LambdaReq()

lambda.get('/test', ()=> {})
lambda.proxy('db_migrate', ()=> {})

export { handler: lambda.invoke }

or with Apex and WebPack

import LambdaReq from 'lambda-req'

const lambda = new LambdaReq()

lambda.get('/test', ()=> {})
lambda.proxy('db_migrate', ()=> {})

export default lambda.invoke

.isApiGateway Bool

It returns true if the request was an APIGateway invocation. Internally, checks if an HTTP method is set on the Lambda event.

const lambda = new LambdaReq(event, context, callback)

if (lambda.isApiGateway) {
  // it's a HTTP call
}

.isProxy Bool

It return true if the request was a direct Lambda invocation. Internally, checks if a property command is set on the Lambda event.

const lambda = new LambdaReq(event, context, callback)

if (lambda.isProxy) {
  // it's a direct invocation
}

.params Object

Has all the params coming from event.queryStringParameters, event.pathParameters and event.body for an APIGateway call. Stores all the params coming from event.params for a direct invocation. Referenced through req.params on a handler.

const lambda = new LambdaReq(event, context, callback)

lambda.get('/test', (req)=> {
  const { params } = req
  // process APIGateway data
})
lambda.proxy('db_migrate', (req)=> {
  const { params } = req
  // process direct invocation data
})

if (lambda.params) {
  // process data
}

.headers Object

Stores the HTTP headers from an APIGateway call.

const lambda = new LambdaReq(event, context, callback)

lambda.get('/test', (req)=> {
  const { headers } = req
  if (headers['x-auth']) {
    // process user authentication
  }
})

.currentRoute String

Returns the current invocation route.

LambdaProxy

A wrapper for direct Lambda invocation calls. Sets the command and parameters on internal calls.

.constructor([client = Object = AWS.Lambda])

.invoke(functionName = String, command = String, [params = Object])

Call a Lambda internally, pass in the command and params.

import { LambdaProxy } from 'lambda-req'

const proxy = new LambdaProxy()
proxy.invoke('myFunction', 'db_migrate', { name: 'users' })
.then((response)=> {
  return { message: 'Proxy response from myFunction', response }
})
.catch((err)=> {
  console.error('myFunction Lambda is unresponsive', err)
})

LambdaReqError

A tiny wrapper for Lambda request errors.

.constructor({ message, status })

The error has a message and a status that will be passed along to the APIGateway.

lambda.get('/users', (req, router)=> {
  const { params } = req
  if (!params.id) {
    throw new LambdaReqError({
      message: {
        error: {
          code: 'userNotFound',
          message: 'User not found.'
        }
      },
      status: 404
    })
  } else {
    const user = await dbConnection.findUser(params.id)
    return { user }
  }
})

See more examples.

You might also like...

A serverless AWS expense tracker API. AWS Lambda functions, API gateway, and Dynamodb are among the ingredients.

AWS-Serverless-API A serverless AWS expense tracker API. AWS Lambda functions API gateway Dynamodb Endpoints Create a new expense: Method: POST Body f

Jul 16, 2022

Everynode allows you to run any version of Node.js in AWS Lambda, in any commercial AWS region

Everynode allows you to run any version of Node.js in AWS Lambda, in any commercial AWS region

Run Any Node.js Version in AWS Lambda Everynode allows you to run any version of Node.js in AWS Lambda, in any commercial AWS region. We add support f

Dec 15, 2022

A monorepo that uses the AWS Cloud Development Kit to deploy and configure nanomdm on AWS lambda.

NanoMDM on AWS This repo builds and configures a nanomdm server to run on AWS lambda. It uses the Cloud Development Kit and tries to follow best pract

May 26, 2022

Lumos is an AWS Lambda visualizer and open source alternative to AWS CloudWatch.

Lumos is an AWS Lambda visualizer and open source alternative to AWS CloudWatch.

Lumos Lambda Metrics Visualizer Table of Contents About Lumos Techologies Used Getting Started Key Lambda Metrics How to Contribute License Contributo

Nov 5, 2022

Learn Web 2.0 and Web 3.0 Development using Next.js, Typescript, AWS CDK, AWS Serverless, Ethereum and AWS Aurora Serverless

Learn Web 2.0 Cloud and Web 3.0 Development in Baby Steps In this course repo we will learn Web 2.0 cloud development using the latest state of the ar

Jan 3, 2023

Micro client-side router inspired by the Express router

Tiny Express-inspired client-side router. page('/', index) page('/user/:user', show) page('/user/:user/edit', edit) page('/user/:user/album', album) p

Dec 28, 2022

A chainable router designed for Next.js api. inspired and regex based from itty-router

Next.js Api Router A chainable router designed for Next.js api. inspired and regex based from itty-router Features Tiny (~8xx bytes compressed) with z

Jan 21, 2022

Router JS 💽 Simple Router building in JavaScript

Router JS 💽 Simple Router building in JavaScript

Feb 12, 2022

Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

May 18, 2022

Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

May 3, 2022

Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

Jan 3, 2023

Serverless raster and vector map tile generation using Mapnik and AWS Lambda

tilegarden 🗺️ 🌻 Contents About Usage Deployment to AWS Additional Configuration Options Required AWS Permissions Features Configuration Selection an

Dec 22, 2022

A serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gateway, Lambda)

A serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gateway, Lambda)

---- Sorry, this project is not maintained anymore. ---- dawson is a serverless web framework for Node.js on AWS (CloudFormation, CloudFront, API Gate

Dec 30, 2022

Implementing hexagonal architecture on AWS Lambda with Node.js

Implementing hexagonal architecture on AWS Lambda with Node.js

Developing evolutionary architecture with AWS Lambda Context Agility enables you to evolve a workload quickly, adding new features, or introducing new

Dec 20, 2022

AWS Lambda and API Gateway, simplified for Javascript

AWS Lambda and API Gateway, simplified for Javascript

alanajs AWS Lambda and API Gateway, simplified for JavaScript About alanajs Make setting up Lambda microservices easier than ever. alanajs is a free,

Aug 1, 2022

Alexa Skill & Google Action code that works on AWS Lambda

Alexa Skill & Google Action code that works on AWS Lambda

Jovo v4 Sample: Alexa Skill & Google Action on AWS Lambda Website - Docs - Marketplace - Template This Jovo v4 sample app showcases the following feat

Nov 22, 2022

A quickstart AWS Lambda function code generator. Downloads a template function code file, test harness file, sample SAM deffiniation and appropriate file structure.

Welcome to function-stencil 👋 A quickstart AWS Lambda function code generator. Downloads a template function code file, test harness file, sample SAM

Jun 20, 2022

A simple example repo that demonstrates the dynamic ephemeral storage solution for AWS Lambda outlined in the corresponding Storyboard Dev Blog post.

AWS Lambda Dynamic Ephemeral Storage Example A simple example repo that demonstrates the dynamic ephemeral storage solution for AWS Lambda outlined in

Jun 14, 2022

Sample code for resizing Images with Lambda@Edge using the Custom Origin. You can deploy using AWS CDK.

Sample code for resizing Images with Lambda@Edge using the Custom Origin. You can deploy using AWS CDK.

Resizing Images with Lambda@Edge using the Custom Origin You can resize the images and convert the image format by query parameters. This Lambda@Edge

Dec 11, 2022
Comments
  • Support for x-www-form-urlencoded / Multipart

    Support for x-www-form-urlencoded / Multipart

    If the content-type header is set to x-www-form-urlencoded it tries to parse the data as a string such as one=val&two=someothervalue and returns the object:

    { 
      one: 'val',
      two: 'someothervalue'
    }
    

    Previously this broke because it always tried to parse as json.

    Secondly if the content type is multipart im using busboy and returning the .on method on the req variable ((req, router) => {}). You would then use a promise to access to the for data as such:

      const lambda = new LambdaReq(event, context, callback);
      lambda.post('/message',  (req, router) => {
            const fields = {};
            return new Promise((resolve, reject) => {
                req.on('field', (fieldname, val, fieldnameTruncated, valTruncated, encoding, mimetype) => {
                    console.log('test');
                    console.log('Field [' + fieldname + ']: value: ' + inspect(val));
                    fields[fieldname] = val;
                });
    
        
            req.on('file', function(fieldname, file, filename, encoding, mimetype) {
                console.log('File [' + fieldname + ']: filename: ' + filename + ', encoding: ' + encoding + ', mimetype: ' + mimetype);
                file.on('data', function(data) {
                    console.log('File [' + fieldname + '] got ' + data.length + ' bytes');
                });
                req.on('end', function() {
                    console.log('File [' + fieldname + '] Finished');
                });
            })
    
    
            req.on('error', (err) => {
                console.log(err);
            })
    
            req.on('finish', () =>{
                console.log("finished");
                //inspect(fields);
                resolve({test: 'some value'});
            });
            }).catch(e => {
                console.log(e)
            });
    
        });
    opened by jamescharlesworth 2
  • application/x-www-form-urlencoded not supported?

    application/x-www-form-urlencoded not supported?

    Looks like form uploads are not supported, is that correct. Meaning the library only supports post json/querystring parameters. Or, am i using the library incorrectly? If i try to parse a application/x-www-form-urlencoded body, the code does not look at a content-type header and parse accordingly, right? It throws an error when you do this.

    opened by jamescharlesworth 2
  • Sets a default statusCode of 200 for all API Gateway requests

    Sets a default statusCode of 200 for all API Gateway requests

    Problem

    For all API Gateway requests, a statusCode is currently only sent if it's an error. This is because the only thing developers have access to when handling a route is the response body (which is stringified and placed on the response here).

    Proposed Solution

    Given that any error sets the statusCode accordingly, it should be safe to assume a default statusCode of 200.

    This PR does the following

    • Sets a default value for the statusCode of 200 when handling API Gateway requests
    • Updates the corresponding unit tests to ensure that the response also includes the statusCode
    opened by mattbeattie 2
  • adds support for application/x-www-form-urlencoded and multipart

    adds support for application/x-www-form-urlencoded and multipart

    will parse application/x-www-form-urlencoded properly and not attempt to parse multipart with JSON.parse. the req object now contains the raw body and the consuming application can choose how to process multipart requests.

    opened by jamescharlesworth 1
Owner
Dumitru Glavan
Backend developer building highly scalable platforms for more than 15 years. NodeJS, Go, AWS.
Dumitru Glavan
🍔 A Node.js Serverless Framework for front-end/full-stack developers. Build the application for next decade. Works on AWS, Alibaba Cloud, Tencent Cloud and traditional VM/Container. Super easy integrate with React and Vue. 🌈

Midway - 一个面向未来的云端一体 Node.js 框架 English | 简体中文 ?? 欢迎观看 Midway Serverless 2.0 发布会回放: https://www.bilibili.com/video/BV17A411T7Md 《Midway Serverless 发布

Midway.js 6.3k Jan 8, 2023
Actionhero is a realtime multi-transport nodejs API Server with integrated cluster capabilities and delayed tasks

Actionhero The reusable, scalable, and quick node.js API server for stateless and stateful applications NPM | Web Site | Latest Docs | GitHub | Slack

Actionhero 2.3k Jan 4, 2023
Framework for setting up RESTful JSON APIs with NodeJS.

Restberry works with both Express and Restify! Framework for setting up RESTful JSON APIs with NodeJS. Define your models and setup CRUD API calls wit

Restberry 117 Jul 5, 2021
Zeronode - minimal building block for NodeJS microservices

Zeronode - minimal building block for NodeJS microservices Why Zeronode? Installation Basics Benchmark API Examples Basic Examples Basic Examples [Adv

Steadfast 120 Oct 21, 2022
Component based MVC web framework for nodejs targeting good code structures & modularity.

Component based MVC web framework for nodejs targeting good code structures & modularity. Why fortjs Based on Fort architecture. MVC Framework and fol

Ujjwal Gupta 47 Sep 27, 2022
MerLoc is a live AWS Lambda function development and debugging tool. MerLoc allows you to run AWS Lambda functions on your local while they are still part of a flow in the AWS cloud remote.

MerLoc MerLoc is a live AWS Lambda function development and debugging tool. MerLoc allows you to run AWS Lambda functions on your local while they are

Thundra 165 Dec 21, 2022
AWS Lambda & Serverless - Developer Guide with Hands-on Labs. Develop thousands line of aws lambda functions interact to aws serverless services with real-world hands-on labs

AWS Lambda & Serverless - Developer Guide with Hands-on Labs UDEMY COURSE WITH DISCOUNTED - Step by Step Development of this Repository -> https://www

awsrun 35 Dec 17, 2022
AWS Lambda router for NodeJS

AWS Lambda Router for NodeJS A collection of tools to handle ApiGateway requests and direct function invocation calls on AWS Lambda. Use it as a stand

Dumitru Glavan 11 Apr 22, 2019
Under the Sea is an official AWS workshop delivered by AWS SAs and AWS Partners to help customers and partners to learn about AIOps with serverless architectures on AWS.

Under the Sea - AIOps with Serverless Workshop Under the Sea is an exciting MMORPG developed by the famous entrepreneur behind Wild Rydes, the most po

AWS Samples 4 Nov 16, 2022