|
|
|
var url = require('url');
|
|
|
|
var NotFoundError = require('./error').NotFound;
|
|
|
|
var RouteNode = require('./route-node');
|
|
|
|
var utils = require('./utils');
|
|
|
|
|
|
|
|
var assign = utils.assign;
|
|
|
|
var isArray = utils.isArray;
|
|
|
|
var isFunction = utils.isFunction;
|
|
|
|
var isString = utils.isString;
|
|
|
|
var noop = utils.noop;
|
|
|
|
|
|
|
|
function Router() {
|
|
|
|
this.routes = new RouteNode();
|
|
|
|
}
|
|
|
|
|
|
|
|
assign(Router.prototype, {
|
|
|
|
add: function add(path, handler) {
|
|
|
|
return this.routes.add(this._uriToParts(path), handler);
|
|
|
|
},
|
|
|
|
|
|
|
|
route: function route(path, options, done) {
|
|
|
|
if (done == null && isFunction(options)) {
|
|
|
|
done = options;
|
|
|
|
options = {};
|
|
|
|
}
|
|
|
|
options = options || {};
|
|
|
|
var routeArray = this._uriToParts(path);
|
|
|
|
done = done || noop;
|
|
|
|
|
|
|
|
function _routeCallback(err, func, context, args) {
|
|
|
|
if (err) {
|
|
|
|
return done(err);
|
|
|
|
} else {
|
|
|
|
if (isFunction(func)) {
|
|
|
|
return done(null, func.apply(context, args));
|
|
|
|
} else {
|
|
|
|
return done(new NotFoundError('not found', {location: path}));
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return this.routes.get(routeArray, (options.args || []), _routeCallback);
|
|
|
|
},
|
|
|
|
|
|
|
|
_uriToParts: function _uriToParts(uri) {
|
|
|
|
if (isString(uri)) {
|
|
|
|
return url.parse(uri)
|
|
|
|
.pathname
|
|
|
|
.split('/')
|
|
|
|
.filter(function (str) { return str !== ''; });
|
|
|
|
} else if (isArray(uri)) {
|
|
|
|
return uri.reduce(this._uriToPartsReducer.bind(this), []);
|
|
|
|
}
|
|
|
|
},
|
|
|
|
|
|
|
|
_uriToPartsReducer: function _uriToPartsReducer(memo, item) {
|
|
|
|
if (isArray(item)) {
|
|
|
|
return memo.concat(item);
|
|
|
|
} else if (isString(item)) {
|
|
|
|
return memo.concat(this._uriToParts(item));
|
|
|
|
} else {
|
|
|
|
return memo.concat(item);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
});
|
|
|
|
|
|
|
|
Router.isNotFound = function isNotFound(err) {
|
|
|
|
return err instanceof NotFoundError;
|
|
|
|
};
|
|
|
|
|
|
|
|
module.exports = Router;
|