A web router for NodeJS, compatible with Connect middlewares. The main goal is to provide a global function (req, res, next)
that can do different work regarding the req.method
and req.path
values.
Notice that it will also fill res.allowedmethods
with the list of methods implemented on the path, ie ['POST', 'GET']
.
In your project main directory, type npm install silence-router
var router = require('silence-builder')()
.createMW(badRequest, notAllowed);
function badRequest(req, res, next){
// URI doesn't exist in your router
}
function notAllowed(req, res, next){
// Method req.method is not allowed in your router
}
This will returns a function (req, res, next) than you will always proceed the badRequest method.
You can also see that res.allowedmethods
will always equals []
.
NodeJS doesn't set this value but it's very trivial to implements. Add this middleware before the router in your Express/Silence/whatever process.
function reqPath(req,res, next){
var path = require('url').parse(req.url).pathname;
req.path = path;
next();
}
function createUser(req, res, next){
//Create the user here and send the response you want
next();
}
function listUser(req, res, next){
//List users here and send the response you want
next();
}
var router = require('silence-builder')()
.path("user")
.post(createUser)
.get(listUser)
.createMW(badRequest, notAllowed);
Now you can handle POST /user
and GET /user
correctly with res.allowedmethods
equals to ['POST','GET']
You can of course specify it by yourself.
var router = require('silence-builder')()
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.createMW(badRequest, notAllowed);
But silence-router allows you to define a default OPTIONS handler that will be used on every defined uri, unless you override it.
function globalOptions(req, res, next){
//Your code here
next();
}
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.createMW(badRequest, notAllowed);
You can add a subpath with a name starting with :
that will be populated into req.params.
function userGet(req, res, next){
//Retrieve user via req.params.userId
}
function userDelete(req, res, next){
//Retrieve user via req.params.userId
}
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.path(":userId")
.get(userGet)
.delete(userDelete)
.createMW(badRequest, notAllowed);
Simply use ̀.parent()` to go up the path hierarchy.
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.path(":userId")
.get(userGet)
.parent()
.parent()
.path("other")
.get(somethingHere)
.createMW(badRequest, notAllowed);
Be aware that the router will always find the first matche, definition order is important. Look at the following example:
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.path(":userId")
.get(userGet)
.delete(userDelete)
.parent()
.path("me")
.get(whoAmi)
.createMW(badRequest, notAllowed);
The whoAmi
will never be called, just invert two blocks and you problem will be solved.
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.path("me")
.get(whoAmi)
.parent()
.path(":userId")
.get(userGet)
.delete(userDelete)
.parent()
.createMW(badRequest, notAllowed);
The path
method allows you to add as many function you want, that will be executed in the right order.
Than can be very usefull in some case, see the exemple below.
function loadUser(req, res, next){
User.findById(req.params.id, function(err, user){
if(err){
return next(err);
}
if(!user){
//Respond with 404
}
res.loaded = res.loaded || {};
res.loaded.user = user;
next();
});
}
function userGet(req, res, next){
//Simply use res.loaded.user
next();
}
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post(createUser)
.get(listUser)
.options(someFunction)
.path(":userId", loadUser, doALog)
.get(userGet)
.parent()
.parent()
.path("other")
.get(somethingHere)
.createMW(badRequest, notAllowed);
It could be very usefull for log to know which endpoint has been use without having to search for a http verb + a regular express on uri.
You can simply add a name for a handler as first optionnal parameter and silence-router will manage to set the variable req.name
.
var router = require('silence-builder')({optionsHandler:globalOptions})
.path("user")
.post("createUser", createUser)
.get("listUser", listUser)
.options(someFunction)
.path(":userId", loadUser, doALog)
.get("getUser", userGet)
.parent()
.parent()
.path("other")
.get("unamedMethod", somethingHere)
.createMW(badRequest, notAllowed);
{
optionsHandler : true | function(req,res,next) | (null/undefined/false)
}
If setted to true, the following method will be used:
function defaultOptionsHandler(req, res, next){
next();
}
Any falsy value is "do not use defaultOptionsHandler"
path (path, _fcts)
Arguments : * path * _fcts
parent : function()
Arguments : none
use (_fcts)
Arguments : * _fcts
method : function(verb, name, _fct)
Arguments : * verb * name * _fcts
options (name, _fct)
This function is just an helper on method, using "OPTIONS" for verb param.
head (name, _fct)
This function is just an helper on method, using "HEAD" for verb param.
This function is just an helper on method, using "GET" for verb param
Arguments : * name * _fcts
This function is just an helper on method, using "PUT" for verb param
Arguments : * name * _fcts
This function is just an helper on method, using "PATCH" for verb param
Arguments : * name * _fcts
This function is just an helper on method, using "DELETE" for verb param
Arguments : * name * _fcts