router.js
1.62 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
var create = require('./create'),
options = require('./options'),
parseUrl = require('./url').parse
module.exports = function(opts) {
opts = options(opts, { prefix:'/', default:'/' })
opts.prefix = new RegExp('^'+opts.prefix)
return create(router, {
routes:{},
errorHandlers:[],
opts:opts
})
}
var router = {
add:function(routeName, handler) {
var route = this.routes
var parts = routeName.split('/')
if (parts[0] != '') { throw new Error('Route much start with "/": '+ routeName) }
parts.shift()
for (var i=0; i<parts.length; i++) {
var name = parts[i]
var isVariable = (name[0] == ':')
var key = isVariable ? ':' : name
if (!route[key]) { route[key] = {} }
route = route[key]
if (i == parts.length - 1) {
route.handler = handler
}
if (isVariable) {
route.__paramName = name.substr(1)
}
}
return this
},
error:function(handler) {
this.errorHandlers.push(handler)
return this
},
route:function(url) {
url = parseUrl(url)
var path = url.pathname
if (this.opts.prefix) {
path = path.replace(this.opts.prefix, '')
}
var params = url.getSearchParams()
var route = this.routes
var parts = path.split('/')
parts.shift()
for (var i=0; i<parts.length; i++) {
var name = parts[i]
if (route[':']) {
route = route[':']
params[route.__paramName] = name
} else if (route[name]) {
route = route[name]
} else {
return this._onError(path)
}
}
if (typeof route.handler != 'function') {
this._onError(path)
} else {
route.handler(params)
}
},
_onError:function(url) {
this.errorHandlers.forEach(function(handler) { handler(url) })
}
}