|
module.exports = new Router(); |
|
|
|
/** |
|
* Router |
|
* @constructor |
|
*/ |
|
|
|
function Router() { |
|
|
|
var routes = {}; |
|
|
|
// Register a route handler |
|
this.add = function addRoute(route, fn) { |
|
|
|
// Parse "/a/:id" to ["a", ":id"] |
|
var segments = route.split('/').filter(function (item) { return item !== '' }); |
|
|
|
// Build the route tree of segments |
|
var currentRoute = routes, segment, routeSegment; |
|
while (segments.length) { |
|
|
|
// Selected & Register routeSegment |
|
segment = segments.shift(); |
|
routeSegment = /^:/.test(segment) ? ':' : segment; |
|
if (!currentRoute[routeSegment]) { |
|
currentRoute[routeSegment] = { handlers: [], subs: {} }; |
|
} |
|
|
|
// Next |
|
currentRoute = currentRoute[routeSegment]; |
|
segments.length && (currentRoute = currentRoute.subs); |
|
} |
|
|
|
// Register handler to final route |
|
currentRoute.handlers.push(fn); |
|
|
|
return new Route(route); |
|
|
|
}; |
|
|
|
// Dispatch route handlers |
|
this.dispatch = function dispatchRoutes(url) { |
|
|
|
// Parse "/a/123" to ["a", "123"] |
|
var segments = url.split('/').filter(function (item) { return item !== '' }); |
|
|
|
// Find a matched route |
|
var route = routes, seg, args = []; |
|
while (segments.length) { |
|
seg = segments.shift(); |
|
if (route[seg]) { |
|
route = route[seg]; |
|
} else if (route[':']) { |
|
route = route[':']; |
|
args.push(seg); |
|
} else { |
|
console.log('Unknown Request:', url); |
|
return; |
|
} |
|
|
|
// Next |
|
segments.length && (route = route.subs); |
|
} |
|
|
|
// Call handlers |
|
if (route.handlers.length) { |
|
route.handlers.forEach(function (fn) { |
|
fn.apply(this, args); |
|
}); |
|
} else { |
|
console.log('Unknown Request:', url); |
|
} |
|
|
|
}; |
|
|
|
this.debug = function () { |
|
return { routes: routes }; |
|
}; |
|
|
|
} |
|
|
|
/** |
|
* Route |
|
* @param route |
|
* @constructor |
|
*/ |
|
|
|
function Route(route) { |
|
this.route = route; |
|
} |
|
|
|
Route.prototype.generate = function generateUrlByRoute(args) { |
|
return this.route.replace(/:(\w+)/g, function (match, name) { |
|
return args[name] || match; |
|
}); |
|
}; |