|
|
|
'use strict'
|
|
|
|
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(options) {
|
|
|
|
options = options || {}
|
|
|
|
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
|