In progress
The code source is fully documented, see:
- /src/index.js
- /src/Router.js
- /src/Route.js
- Also, examples directory.
A route controller receive 2 arguments, req
and next
(optional).
req
is an object containing the current request.next
is an optional function used only in the route middleware. Whennext()
is executed, the controller of the next route that matches is called.next()
can receive only one argument, it's an error. If an argument is passed to thenext(error)
function, it considered as an error.
var router = new routux.Router();
router.use('/my-route', function(req, next) {
console.log('my route');
// your logic here...
});
router.use('/', function(req) {
// "/"
console.log(req.current);
});
router.use('/another/route', function(req) {
// "/another/route"
console.log(req.current);
});
// listen
router.run();
var router = new routux.Router();
router.use('home', '/', function(req) {
// "/"
console.log(req.current);
// "#/"
console.log(router.getUrl('home'));
// "http://your-domain.ltd#/"
console.log(router.getFullUrl('home'));
});
router.use('another', '/another/route', function(req) {
// "/another/route"
console.log(req.current);
// "#/another/route"
console.log(router.getUrl('another'));
// "http://your-domain.ltd#/another/route"
console.log(router.getFullUrl('another'));
});
// listen
router.run();
router.use({
name: 'home',
pattern: '/',
middlewares: [
function(req, next) {
console.log('Route middleware called before');
next();
},
function(req, next) {
console.log('Route controller');
}
]
});
It's equivalent of:
router.use('home', '/',
function(req, next) {
console.log('Route middleware called before');
next();
},
function(req, next) {
console.log('Route controller');
}
);
Or more readable:
function myMiddleware(req, next) {
console.log('Route middleware called before');
next();
}
router.use('home', '/', myMiddleware, function(req, next) {
console.log('Route controller');
});
Considers the URL http://your-domain.ltd#/user/42
:
router.use('user.edit', '/user/:id', function(req) {
// 42
console.log(req.params.id);
// "#/user/10"
console.log(router.getUrl('user.edit', { id: 10}));
// "http://your-domain.ltd#/user/10"
console.log(router.getFullUrl('user.edit', { id: 10}));
});
Considers the URL http://your-domain.ltd?sort=desc#/user/42
:
router.use('user.edit', '/user/:id', function(req) {
// desc
console.log(req.query.sort);
// 42
console.log(req.params.id);
// "#/user/10"
console.log(router.getUrl('user.edit', { id: 10}));
// "http://your-domain.ltd?sort=desc#/user/10"
console.log(router.getFullUrl('user.edit', { id: 10}));
});
An object of context (req.ctx
) is passed with the request.
req.ctx
is an empty object, it is intended to store what you want
(e.g: for your controller or for other routes or for what you want).
router.use('home', '/', function(req) {
req.ctx.date = new Date();
req.ctx.anyValue = 'Any value !';
// your logic here...
});
A Route
instance can be acceded from the scope (this
) of a route controller:
router.use('home', '/', function(req) {
// true
console.log(this instanceof routux.Route);
// true
console.log(this.router === router);
// "home"
console.log(this.name);
// "/"
console.log(this.pattern);
// uniq identifier of the route
console.log(this._uid);
// multiple data can be getted from a Route instance
console.log(this.params);
console.log(this.query);
console.log(this.middlewares);
console.log(this.baseUrl);
// ...
});
Also, a Route
instance can be getted with the router:
var route = router.getRoute('home');
// true
console.log(route instanceof routux.Route);
// true
console.log(route.router === router);
// "home"
console.log(route.name);
// "/"
console.log(route.pattern);
// uniq identifier of the route
console.log(route._uid);
// multiple data can be getted from a Route instance
console.log(route.params);
console.log(route.query);
console.log(route.middlewares);
console.log(route.baseUrl);
// ...
Like the router of Express.js, Routux support the middlewares ✌️
A middleware can be defined in several ways (as needed).
Executed for all routes:
// This middleware adds the date in the context
router.use(function(req, next) {
req.ctx.date = new Date();
next();
});
router.use('home', '/', function(req, next) {
// print the date
console.log(req.ctx.date);
});
router.use('/', function(req, next) {
req.ctx.date = new Date();
next();
});
router.use('home', '/', function(req, next) {
// print the date
console.log(req.ctx.date);
});
router.use('other', '/other', function(req, next) {
// print `undefined`
console.log(req.ctx.date);
});
It is often convenient to use the same middleware in several routes
Example, considers 2 middlewares:
// this middleware log the current request
function logRequest(req, next) {
console.log(req);
next();
}
// this middleware ensures that the user is authentified
function requireAuth(req, next) {
if(req.ctx.user) {
next();
} else {
next(new Error('This route require authentification.'))
}
}
Now we can use in our routes:
router.use('home', '/', logRequest, function(req, next) {
// the request (req) is printed in the console
// Add your logic here...
});
router.use('account', '/acount', requireAuth, function(req, next) {
// The authentification is checked by the middleware,
// we have the guarantee that the user is authenticated.
// Otherwise this route is not executed
// Add your logic here...
});
In a route, we can use multiple middlewares:
router.use('account', '/acount', logRequest, requireAuth, function(req, next) {
// The request (req) is printed in the console
// The authentification is checked by the middleware,
// we have the guarantee that the user is authenticated.
// Otherwise this route is not executed
// Add your logic here...
});
An error handler is a special middleware that is able to handle errors. It works like a conventional middleware, the only difference is when an error is declared, Routux skips all routes until it finds an error handler.
For creating an error handler, simply add the error argument:
router.use(function(error, req, next) {
// print the error encountered in the standard output
console.log(error);
});
As conventional middlewares, it is possible to chain the error handler:
router.use(function(error, req, next) {
if(error.code === 404) {
// example, load your custom 404 error page (not found)
myFramework.render('pageNotFound');
} else {
// if not an error 404, let for the next error handler
next(error);
}
});
router.use(function(error, req, next) {
// print the error encountered
console.error(error);
});
Error handler in real world, considers for the examples an Ajax lib named http
that call a server.
router.use('user.edit', '/user/:id', function(req, next) {
http
.get(apiUrl + '/user/' + this.params.id)
.onSuccess(function(user) {
req.ctx.user = user;
next();
})
.onError(function(error) {
next(error);
})
;
});
router.use('user.edit', '/user/:id', function(req, next) {
// the user object
console.log(req.ctx.user);
});
// Your custom error handler, executed if an error was encountered
// ( remember the next(error) function called in onError() function)
router.use(function(err, req, next) {
// print the error
console.log(err);
});
The router uses location
object to determine the current state of the application and update it when needed.
By default the HashLocation adapter is used.
You can also supply the router with your own location
implementation by creating your own adapter.
For examples below, considers the full URL http://domain.ltd/page.html?show=stats#/user/42
.
Note: some properties below can be getted from the router (shortcut).
Current base URL (absolute).
// print: "http://domain.ltd/page.html"
console.log(router.location.baseUrl);
Shortcut:
// print: "http://domain.ltd/page.html"
console.log(router.baseUrl);
Current location (without URL prefix).
// print: "user"
console.log(router.location.current);
Shortcut:
// print: "user"
console.log(router.current);
The URL (relative).
// print: "#/user"
console.log(router.location.url);
Shortcut:
// print: "#/user"
console.log(router.url);
The full URL (absolute).
// print: "http://domain.ltd/page.html?show=stats#/user/42"
console.log(router.location.fullUrl);
Shortcut:
// print: "http://domain.ltd/page.html?show=stats#/user/42"
console.log(router.fullUrl);
The query string.
// print: "show=stats"
console.log(router.location.queryString);
The query string object.
See qs package.
console.log(router.location.qs);
2 features are added: qs.current
and qs.currentWith()
.
Current query string parsed.
Parse current query string with the given options.
The path prefix.
// print: "#"
console.log(router.location.pathPrefix);
The URL prefix.
By default is the same value of pathPrefix
but can be changed from the router options.
// print: "#"
console.log(router.location.urlPrefix);
If you need your own location
implementation, you can create your own location
adapter.
See HashLocation for a good example.