leads v1.0.1
leads.js
leads.js is a client-side routing library that is very similar to express.js.
var app = leads();
app.get('/', function(req, res, next) {
res.send('Hello world');
});
app.dispatch('/', 'get'); // or app.get('/');
Example
Define handlers.
var app = leads();
app.all('/', indexHandler);
app.all('/user/:id', load, show);
app.all('/user/:id/profile', getProfile);
Define handlers using various path.
app.all('/foo/bar', handler);
app.all('/foo/:bar', handler);
app.all('/foo/:bar/:baz?', handler);
app.all('/ab(c)?d', handler);
app.all('/a(bc)+d', handler);
app.all('/abc/*', handler);
app.all(/\/foo\/bar/, handler);
app.all(['/abc/def', '/user/:id', /\/foo\/bar/], handler);
Define handlers using various METHOD.(See app.METHOD()).
app.all('/', handler);
app.get('/', handler);
app.post('/', handler);
app.put('/', handler);
app.delete('/', handler);
Define middleware.(See app.use())
app.use('/', middleware, errorHandler);
app.use('/admin', authenticate, router);
app.use('/blog', blogApp);
Dispatch!!
app.dispatch('/', 'all'); // or app.all('/');
app.dispatch('/user/123', 'get'); // or app.get('/user/123');
app.dispatch('/comments/post', 'post'); // or app.post('/comments/post');
Installation
$ npm install leads # for browserify
$ git clone https://github.com/webkatu/leads.js
<script src="leads.js"></script>
API
This API is referring the 4.x API of Express.
leads()
This is a main function that creates an application.
var app = leads();
leads([options])
It creates an instance of Application.
var app = leads({
caseSensitive: false,
mergeParams: false,
strict: false,
});
The optional options parameter specifies the behavior of the router in app.
Property | Type | Description | Default |
---|---|---|---|
caseSensitive | Boolean | Enable case sensitivity. | false, treating '/Foo' and '/foo' as the same. |
mergeParams | Boolean | Preserve the req.params values from the parent router. If the parent and the child have conflicting param names, the child’s value take precedence. | false |
strict | Boolean | Enable strict routing. | false, '/foo' and '/foo/' are treated the same by the router. |
addHistory | Boolean | app.dispatch() option | true |
changePath | Boolean | app.dispatch() option | true |
transition | Boolean | app.dispatch() option | true |
leads.Router([options])
It creates an instance of Router
.
The options
is the same as options of leads([options])
.
Application
This object is subclass of Router.
app.defaults
This property is an object that has properties, caseSensitive
, mergeParams
, strict
, addHistory
, changePath
, transition
.
var app = leads({caseSensitive: true});
console.log(app.defaults.caseSensitive); // true
app.defaults.caseSensitive = false;
console.log(app.defaults.caseSensitive); // false
app.all(path, callback[, callback ...])
It registers route handler(s).
It defines a route mapping path to the given callback(s). Each callback is given three arguments, request
, response
, next
.
This method is one of the app.METHOD()
methods.
app.all('/', index);
app.all('*', all);
app.all('/user/:id', authenticate, show);
The leads.js is using internally path-to-regexp to match the path.
app.all(path[, options])
app.all(path, options)
is same as app.dispatch(path, 'all', options)
.
app.dispatch(path[, method][, options])
app.dispatch()
invokes middleware and matching route handlers(callbacks).
And, it changes the url path by History API.
app.dispatch(path)
is same as app.dispatch(path, 'all')
and app.all(path)
.
The second param is specified HTTP method. However, leads.js doesn't do actually HTTP request beacuse leads.js is client-side router. This is one of the mere conditions when matching routes.
app.post('/greet', function(req, res, next) {
console.log('Hello');
next();
});
app.get('/greet', function(req, res, next) {
console.log('Hi');
});
app.dispatch('/greet'); // same as app.all('/greet')
/* console
Hello
Hi
*/
app.dispatch('/greet', 'get'); // same as app.get('/greet')
/* console
Hi
*/
The third param is dispatch options.
Property | Type | Description | Default |
---|---|---|---|
addHistory | Boolean | If false, the history doesn't add. | true |
changePath | Boolean | If false, the url path doesn't change. | true |
data | multiple | This property is given directly to req.data | undefined |
transition | boolean | It transition page if you specify other origin url to path. If false, it doesn't transition. | true |
About addHistory
and changePath
.
app.get('/greet', function(req, res, next) {
console.log('Hi');
});
app.dispatch('/greet', 'get', {
addHistory: false,
changePath: false,
}); // URL and History don't change
About data
.
app.post('/signup', function(req, res, next) {
console.log(req.data);
});
app.dispatch('/signup', 'post', {
data: new FormData(),
});
/* console
FormData {}
*/
About transition
.
app.dispatch('http://www.google.com', null, {
transition: false
}); // not occur anything.
app.dispatch('http://www.google.com'); // transition to the google.
app.METHOD(path, callback[, callback ...])
This register route handler(s).
As with app.all()
, it defines a route mapping path to the given callback(s).
Specify HTTP method name in the METHOD.
app.get('/image', load, show);
app.post('/user/:id', authenticate);
app.put('/edit', send, show);
The HTTP method name is given to req.method
.
Supported methods
- get
- post
- head
- put
- delete
- options
app.METHOD(path[, options])
This is same as app.dispatch(path, METHOD, options)
.
app.param(name, callback)
This registers a route parameter handler.
When it matches the route of path that contains the parameters, callback defined by app.param()
is called first.
The callback is given four arguments, request
, response
, next
and paramValue
.
app.get('/user/:id', function(req, res, next) {
console.log('Hi user');
});
app.param('id', function(req, res, next, value) {
console.log('ID is ' + value);
next();
});
app.dispatch('/user/123');
/* console
ID is 123
Hi user
*/
Same param callback is not called in succession.
app.param('id', function(req, res, next, value) {
console.log('ID is ' + value);
next();
});
app.get('/user/:id', function(req, res, next) {
console.log('This matches');
next();
});
app.get('/user/:id', function(req, res, next) {
console.log('This matches too');
});
app.dispatch('/user/456');
/* console
ID is 456
This matches
This matches too
*/
It is also possible to give an array to name
such as app.param(['class', 'id'], callback)
Please refer to path-to-regexp about path that contains the parameters.
app.route(path)
app.route()
returns a route object mapping the path.
The route object has method of app.METHOD(), and it defines callback by method chain.
Use app.route() to avoid duplicate route names.
app.route('/blog/article')
.all(function(req, res, next) {
console.log('Hi');
next();
})
.get(function(req, res) {
console.log('Get article');
})
.post(function(req, res) {
console.log('Post article');
})
.delete(function(req, res) {
console.log('Delete article');
});
app.use([path, ]function[, function ...])
It mounts the middleware function(s).
Each middleware function is given three arguments, request
, response
, next
.
If the first param is path, middleware is called when it matches path prefix.
For example, app.use('/blog',middleware)
will match /blog
, /blog/articles
, /apple/articles/123
, and so on.
If path is not specified, it defaults to '/'.
app.use(function(req, res, next) { // same as app.use('/', ...)
console.log('This is called every time');
});
app.use()
is also possible to mount router and sub-app as well as function.
var router = leads.Router();
router.get('/', function(req, res, next) {
console.log('Hi');
});
router.get('/Hello', function(req, res, next) {
console.log('Hello');
});
app.use('/greet', router);
var subApp = leads();
app.use('/blog', subApp);
In addition, app.use()
can mount error handler. The error handler function is given four arguments, error
, request
, response
, next
.
The error handler will be called when given a value other than undefined to next()
.
app.use(function(err, req, res, next) {
console.log(err);
});
app.get('/', function(req, res, next) {
next('Error Occurred');
});
app.get('/', function(req, res, next) {
console.log("I won't be called.");
});
app.dispatch('/');
/* console
Error Occurred
*/
You can specify various types of path, a path string, a path pattern, a named parameter, a regular expression, an array of combinations thereof.
From Express4.x table
app.use()
can mount plural middleware. However, it does not support to give array parameter like express app.use()
.
var subApp = leads();
var r1 = leads.Router();
var r2 = leads.Router();
var f = function(req, res, next) { next(); }
app.use(subApp, r1, r2, f); // possible;
app.use(subApp, [r1, r2], f) // impossible;
next()
This is a function given to a route handler and a middleware function for calling the next route handler.
The error handler will be called if you give a value other than undefined to next()
.
However, if specifying next('route')
, it will skip to next route.
app.get('/', function(req, res, next) {
next('route');
}, function(req, res, next) {
console.log(1);
next();
}, function(req, res, next) {
console.log(2);
next();
});
app.get('/', function(req, res, next) {
console.log(3);
});
app.dispatch('/');
/* console
3
*/
When calling the next('route')
in parameter handler, it will skip only subsequent parameter handlers.
app.param('id', function(req, res, next, value) {
next('route');
});
app.param('id', function(req, res, next, value) {
console.log(1);
next();
});
app.param('id', function(req, res, next, value) {
console.log(2);
next();
});
app.get('/:id', function(req, res, next) {
console.log(3);
});
app.dispatch('/123');
/* console
3
*/
Request
This instance is given to a route handler and a middleware function.
When dispatching, it is created and contain context.
req.app
req.app
can access an app object or a router object from the inside of middleware that has been mounted by them.
var subApp = leads();
subApp.get('/', function(req, res, next) {
console.log(req.app === subApp); // true
next();
});
var r = leads.Router();
r.get('/', function(req, res, next) {
console.log(req.app === r); // true
});
app.use(subApp, r);
req.baseUrl
req.baseUrl
is path of middleware that mounted by app.use()
.
var r = leads.Router();
r.use('/123', function(req, res, next) {
console.log(req.baseUrl); // /user/123
next();
});
r.get('/123', function(req, res, next) {
console.log(req.baseUrl); // /user
});
app.use('/user', r);
app.dispatch('/user/123');
/* console
/user/123
/user
*/
In other words, the req.baseUrl
returns matched string.
app.use([/\/\d+/, '/a(bc)+d'], function(req, res, next) {
console.log(req.baseUrl);
});
app.dispatch('/1111/2222'); // 1111;
app.dispatch('/1234/5678/9'); // 1234;
app.dispatch('/abcbcd/ef'); // abcdcd;
req.cookies
It returns cookie object.
// cookie => name=Bob
req.cookies.name // => Bob;
It is dynamic and read-only.
res.cookie('name', 'Bob');
req.cookies.name; => Bob
res.cookie('name', 'John');
req.cookies.name; => John
req.data
When dispatched, req.data
is given data by the dispatch options.
app.all('/', function(req, res, next) {
console.log(req.data);
});
app.dispatch('/', null, { data: 'foo' });
/* console
foo
*/
req.dispatcher
req.dispatcher
is app object or router object that executed the dispatch method.
var r = leads.Router();
r.all('/', function(req, res, next) {
console.log(req.dispatcher === app); // true;
});
app.use(r);
app.dispatch('/');
req.hash
// app.dispatch('http://example.com/foo?page=12#bar');
req.hash // => #bar
req.host
// app.dispatch('http://example.com/foo?page=12#bar');
req.host // => example.com
req.hostname
// app.dispatch('http://example.com/foo?page=12#bar');
req.hostname // => example.com
req.href
// When origin is 'http://example.com'
// app.dispatch('/foo?page=12#bar');
req.href // => http://example.com/foo?page=12#bar
req.method
req.method
is http method name specified in app.dispatch()
;
// app.dispatch('/');
req.method // => all
// app.dispatch('/', 'get');
req.method // => get
// app.post('/');
req.method // => post
req.origin
// app.dispatch('http://example.com/foo?page=12#bar');
req.origin // => http://example.com
req.originalUrl
req.originalUrl
is path specified in app.dispatch();
// app.dispatch('/foo/bar');
req.originalUrl // => /foo/bar
//app.dispatch('http://example.com/foo?page=12#bar');
req.originalUrl // => http://example.com/foo?page=12#bar
req.params
This property is an object containing properties mapped to the named route parameters.
app.use('/:foo/:bar', function(req, res, next) {
console.log(req.params);
});
app.dispatch('/blog/articles');
/* console
{ foo: 'blog', bar: 'articles' }
*/
When you use an unnamed parameters such as a path pattern or a regular expression using brackets, it will be numerically indexed.
app.use('/fo(o)+/b(ar)?/(.*)', function(req, res, next) {
console.log(req.params);
next();
});
app.use(/\/(foo)\/(bar)/, function(req, res, next) {
console.log(req.params);
});
app.dispatch('/foo/bar/baz/123');
/* console
{ 0: "o", 1: "ar", 2: "baz/123" }
{ 0: "foo", 1: "bar" }
*/
Refer to path-to-regexp.
req.path
// app.dispatch('http://example.com/foo?page=12#bar');
req.path // => /foo?page=12
req.pathname
// app.dispatch('http://example.com/foo?page=12#bar');
req.pathname // => /foo
req.port
It returns ''
if port is number 80.
req.protocol
// app.dispatch('http://example.com/foo?page=12#bar');
req.protocol // => http:
req.query
This property is query object of querystring.parse();
// app.dispatch('http://example.com/foo?page=12#bar');
req.query.page // 12
req.search
// app.dispatch('http://example.com/foo?page=12#bar');
req.search // => ?page=12:
req.secure
If protocol is https:, req.secure
returns true.
Response
This instance is given to a route handler and a middleware function.
This object has various and useful methods. However, they might be not necessarily required. If you want using minimum function, use leads-router.
res.defaults
This property is an object to set the default options.
Property | Type | Description | Default |
---|---|---|---|
baseElement | Element | An element to show HTML and text, and so on. | document.body |
filename | String | The default filename when downloading the file. | 'file' |
url | Boolean | To distinguish url and string when sending file. res.download() and res.sendFile() option. | true |
transition | Boolean | res.sendFile() option. | false |
cookieExpires | String | res.cookie() option. | '' |
cookiePath | String | res.cookie() and res.clearCookie() option. | '/' |
cookieDomain | String | res.cookie() and res.clearCookie() option | '' |
cookieSecure | Boolean | res.cookie() and res.clearCookie() option. | false |
Example of setting way.
app.use(function(req, res, next) {
res.defaults = {
filename: 'filename.txt',
transition: true,
cookieExpires: 7,
cookiePath: ''
};
});
res.cookie(name, value[, options])
res.cookie()
create a cookie.
res.cookie('name', 'value', { expires: 7, path: '' });
This method is internally using js-cookie. res.cookie(name, value, options)
is the same as Cookies.set(name, value, options)
of js-cookie. Please refer to it.
The following are properties of options
.
- expires
- path
- domain
- secure
res.clearCookie(name[, options])
res.clearCookie()
delete a cookie.
This method is the same as Cookies.remove(name, options)
of js-cookie.
The following are properties of options
.
- path
- domain
- secure
"IMPORTANT! when deleting a cookie, you must pass the exact same path, domain and secure attributes that were used to set the cookie, unless you're relying on the default attributes."
res.download(file[, options])
This method downloads a file.
res.download('/img/cat.png')
In addition to the path, it can specify various types to the file. See the following table.
The following table is about res.download()
options.
res.send(data[, options])
It shows the data on document.
res.send('send text');
res.send('<p>send HTML</p>');
res.send(Element);
res.send(document);
res.send({ foo: 'bar' });
res.send(new ArrayBuffer());
res.send(blob);
The following table is about the data.
The following table is about res.send()
options.
res.sendFile(file[, options])
(Experimental method)
It shows the file using <object></object>
.
res.sendFile('/image/cat.png');
/*
<body>
<object data="/image/cat.png"></object>
</body>
*/
It can specify the following types to the file like res.download().
- ArrayBuffer
- Blob
- Object
- URL
- String
If the file isn't URL, res.sendFile()
creates blob URL from the file. However IE doesn't create blob URL. Therefore IE directly downloads blob.
The following table is about res.sendFile()
options.
res.sendStatus(status[, options])
It sends HTTP status and the status message.
res.sendStatus(403) // <body>403 Forbidden</body>
res.sendStatus(404) // <body>404 Not Found</body>
res.sendStatus(500) // <body>500 Internal Server Error</body>
Please refer to httpStatusTable about status message.
If you specify non-existent status, it returns the status number.
res.sendStatus(1234) // <body>1234</body>
You can specify any message.
res.sendStatus(404, { message: 'ERROR 404' }) // <body>ERROR 404</body>
The following table is about res.sendStatus()
options.
res.redirect(path)
It redirects to path.
res.redirect('./');
res.redirect('../');
res.redirect('http://www.google.com');
If you specify res.redirect('back')
, history back.
Router
Router is a core object of leads.js.
var router = leads.Router();
router.get('/', function(req, res, next) {
/* code */
});
app.use('/user', router);
It is inherited to Application.
router.defaults
See app.defaults.
router.all(path, callback[, callback ...])
See app.all().
router.all(path[, options])
See app.all().
router.dispatch(path[, method][, options])
See app.dispatch().
router.METHOD(path, callback[, callback ...])
See app.METHOD().
router.METHOD(path[, options])
See app.METHOD().
router.param(name, callback)
See app.param().
router.route(path)
See app.route().
router.use([path, ]function[, function ...])
See app.use().
Support
Tested on IE11, Chrome, Firefox.
If you want to support IE10+, use leads-router.
Author
- Twitter @vinyufi
- Blog webkatu.com