A light weight Express like Request and Response handler for serverless lambda functions
Install it via npm:
npm install serverless-req-res --saveAnd include in your project:
var ReqRes = require('serverless-req-res');Get the Res and Req handlers:
//file: handler.js
//serverlessEndpoint.com/getExample?userName="fooBar"
var reqRes = new ReqRes((req,res)=>{
res.json({
hello: req.params.userName
})
})
module.exports = {get:reqRes.run}add the function to serverless.yaml
functions:
getExample:
handler: src/handler.get
description: an example of useing ReqRes
events:
- http:
method: GET
path: getExamplePlugins will run globally on all resReq Objects when .run is called.
Alternatively, you can use .before() to extend a single function
include the plugins module
var ReqRes = require('serverless-req-res');create two plugins that vaildates user and sends back a 404 with a custom message
//varify user based off token
ReqRes('plugin', (res,req, ServerlessEvent)=>{
return new Promise((fullfill, reject)=>{
getUser(req.headers.token).then((user)=>{
req.user = user
fulfill()
}).catch(reject)
})
})
//create a custom response for a "specal usecase"
ReqRes('plugin', (res,req, ServerlessEvent)=>{
res.notFound = (message)=>{
if(!message) message = "404 - Not Found."
ServerlessEvent.callback(null, {
statusCode: 404,
headers:{},
body: message,
})
}
})
let reqRes = new ReqRes((req,res)=>{
//use first pugin to get req.user
res.send("hello! "+req.user.firstName + " it's now "+req.now )
})
//set req.now for only this function
.before((req, res, ServerlessEvent)=>{
req.now = new Date.now()
})
//catch a plugin rejectcion
.catch((errors ,req,res, ServerlessEvent)=>{
//use second plugin to catch an error (first plugin rejected it's promise)
res.notFound("User Not Found")
})NOTE: All plugins and before()s are synchronously called
var handler = new ReqRes((req, res)=>{
req.stack.push("Finally")
//use our plugin
res.json({
message:"the stack is",
stack:req.stack
});
})
//Pass Object to add to req, or res
.before({
req:{
stack:[]
}})
//Passing a function that returns a Proimise will wait unfil it is resolved before running any other "before"
.before((req,res,lambda)=>{
return new Promise((fulfill,reject)=>{
setTimeout(()=>{
req.stack.push("First")
fulfill()
},1000)
})
})
.before((req,res,lambda)=>{
req.stack.push("Second")
})
.catch((errors, req,res, lambda)=>{
res.error(errors)
})Returns
{
"message": "stack is",
"stack": [
"First",
"Second",
"Finally"
]
}In examples shown with 'ServerlessEvent' (constructor, before(), plugins) The object is the raw Serverless Event as an Object
{
event:Object
context:Object
callback:Function
}
console.log(req.headers)res.headers({"foo":"bar"})
console.log(res.headers())res.json({
works:true;
})Returns a 400 json response with error message and stack trace
try{
var1.anUndefinedVar = aNotherUndefinedVar;
}catch(e){
res.error(e)
}ReqRes(Callback) Your main function to get access to res and req obejcts
ReqRes("plugin", Callback) Register a plugin that will run on all serverless requests
reqRes.before(Callback|Object) runs a callback before main function
reqRes.catch(Callback) catch plugin or .before errors along with your main constructor function
reqRes.context(Object) set raw serverless contex
reqRes.event(Object) set raw serverless event
reqRes.run(rawServerlessEvent, rawServerlessContex, rawServerlessCallback) handle raw serverless function call
var reqRes = new ReqRes(
//the constructor
(req,res,ServerlessEvent)=>{
//send the request object to browser
res.json(req)
}
); On serverless request, this 'constructor callback' will run after all .before() and plugins have ran.
Req Stores lambad request (headers, query parameters, url parameters...)
Res Handle a response (json,jsonp,text,redritcs...)
//fake auth plugin
//first param is string "plugin",
//seond pram is the callback to run apon a serverless request
ReqRes('plugin', (res,req, ServerlessEvent)=>{
return new Promise((fullfill, reject)=>{
getUser(req.headers.token).then((user)=>{
req.user = user
fulfill()
}).catch((e){
req.user = null,
req.userError = e.message
fulfill()
})
})
})
//note .before() will be undefined
//.before()when the first parameter of ReqRes is a string "plugin" the callback will run before every request made Note: Plugins are not chanable and return undefined. You cannot use .before or any of the fallowing functions
reqRes.before((req,res,ServerlessEvent)=>{
req.userId = 123
})Chainable Functions to run (synchronously) before main function
Type: Function
Param 'Callback': Function to run before your main function (usefull for exdending the req or res objects)
Returns: resReq
Example:
//set req.server
reqRes.before({req:{
"server":process.env.serverName
}})
//The Callback Supports Promises
.before((req,res)=>{
return new Promise((fulfill, reject)=>{
getUser(req.path.userId).then((user)=>{
req.user = user
fulfill()
}).catch(reject)
})
})
//this will wait until the proimse from .before (above) has resolved, then
//add a custom response
.before((req,res)=>{
res.jsonUpdated = (data)=>{
data.accessedAt = new Date.now();
data.accessedBy = req.user.id;
res.json(data)
}
})reqRes.before((req,res)=>{
undefinedVar.value = 12345;
})
.catch((errors, req, res)=>{
//return the array of errors
res.error(errors)
})returns
[
{
"message": "undefinedVar is not defined",
"stack": "ReferenceError: undefinedVar is not defined at ReqRes.before.req.stack ({above}}.js:2:4)
at checkFulfill ({{node_modules}}/index.js:187:21)"
}
]Catch all .before() and plugin errors and then your constructor function
Type: Function
Param 'Callback': Function that runs (after all befores have ran) and one or more befores threw a Promse reject
Returns: resReq Example
reqRes.context({callbackWaitsForEmptyEventLoop: false})
console.log(reqRes.context())set defulats for the serverless context befure .run
Type: Function
Param 'contex': If set, it will update the context
Returns: contex (if parameters are empty) or undefined
reqRes.event({headers: {}})
console.log(reqRes.event())set defulats for the serverless event befure .run
Type: Function
Param 'event': If set, it will update the context
Returns: event (if parameters are empty) or undefined
var standerdHandler = (event, contex, callback)=>{
rewReq.run(event, contex, callback)
}Handles the raw serverless request
Type: Function
Param 'event': serverless's request event
Param 'contex': serverless's contex
Param 'callback': the serverless function to output
Returns: undefined
Type: Object
Returns: a key value pairs of query parameters
Type: String | Object
Returns: HTTP request body. If body is a JSON string, the string will be parese to Object
Type: Object
Returns: a key value pairs of url parameters
Type: Object
Returns: a key value pairs of url path parameters
Type: Object
Returns: a key value pairs of request headers
Get and Set the headers
Type: Function
Param 'headers': A key/val object to set response headers.
Returns: currently set header object
Waits for proimsie to resolve before fullfilling the response (res.json) or displaying error (res.error)
Type: Function
Param 'Promise': A JS Promise
Pram 'Headers' (Optinal): key/value object of headers to set
Returns: serverless callback parameters
fulfill the lamba function with a Json object
Type: Function
Param 'Body': Return this Object to serverless
Prams 'statusCode' (Optinal): Set the http response code, Defualts to 200
Returns: serverless callback parameters
NOTE: If queryparam "cb" or "callback" is set, jsonp will be returned
fulfill the lamba function with a string (such as html)
Type: Function
Prams 'statusCode' (Optinal): Set the http response code, Defualts to 200
Param 'Body': Return this string to serverless
Prams 'statusCode' (Optinal): Set the http response code, Defualts to 200
fulfill the lamba function with an JS Thrown Error or Object;
if Thrown Error is past serverless will be called back with json body
{stack:"String of Stack trace", message:"error message"} If an object is past it will return your custom error object as jason body
Type: Function
Returns: serverless callback parameters
Returns: serverless callback parameters
MIT