1 | 1 | var fs = require('fs'); |
2 | 1 | var path = require('path'); |
3 | 1 | var urlparse = require('url').parse; |
4 | | |
5 | 1 | function pageNotFound(req, res) { |
6 | 8 | res.statusCode = 404; |
7 | 8 | res.end(req.method !== 'HEAD' && req.method + ' ' + req.url + ' Not Found '); |
8 | | } |
9 | | |
10 | 1 | module.exports = function router(options) { |
11 | | //default options |
12 | 1 | options = options || {}; |
13 | 1 | options.path = options.path || './controllers'; |
14 | 1 | options.deepth = options.deepth || 1; |
15 | 1 | options.index = options.index || 'index'; |
16 | 1 | options.rewrite = options.rewrite || {}; |
17 | 1 | options.root = options.root || '/'; |
18 | 1 | var controllers = {}; |
19 | | |
20 | | //load all the controllers |
21 | 1 | var realPath = path.resolve(options.path); |
22 | 1 | var innerDirs = []; |
23 | 1 | do { |
24 | 3 | var inner = innerDirs.shift() || ''; |
25 | 3 | var dirName = realPath + (inner ? '/' + inner : ''); |
26 | 3 | fs.readdirSync(dirName).forEach(function(filename) { |
27 | 9 | var totalName = dirName + '/' + filename; |
28 | 9 | var innerName = inner ? inner + '/' + filename : filename; |
29 | 9 | if (fs.statSync(totalName).isDirectory() && innerName.split('/').length < options.deepth) { |
30 | 2 | innerDirs.push(innerName); |
31 | | } |
32 | 7 | else if (/\.js$/.test(filename) && !controllers.hasOwnProperty(innerName.slice(0, -3))) { |
33 | 6 | var controller = require(totalName); |
34 | 6 | for (var key in controller) { |
35 | 18 | var temp = controller[key]; |
36 | 18 | delete controller[key]; |
37 | 18 | controller[key.toUpperCase()] = temp; |
38 | | } |
39 | 6 | controllers[innerName.slice(0, -3).toUpperCase()] = controller; |
40 | | } |
41 | | }); |
42 | | } while(innerDirs.length); |
43 | 1 | function getActionParam() { |
44 | 30 | var ctlName = ''; |
45 | 30 | var controller; |
46 | 30 | var funcNum; |
47 | 30 | var deepth = arguments.length < options.deepth ? arguments.length : options.deepth; |
48 | 30 | for (var i = 0; i < deepth; ++i) { |
49 | 44 | ctlName += arguments[i]; |
50 | 44 | controller = controllers[(ctlName || options.index).toUpperCase()]; |
51 | 44 | funcNum = i+1; |
52 | 44 | if (controller) { |
53 | 24 | break; |
54 | | } |
55 | 20 | ctlName += '/'; |
56 | | } |
57 | 30 | if (controller) { |
58 | 24 | var func = controller[(arguments[funcNum] || options.index).toUpperCase()]; |
59 | 24 | if (typeof func === 'function') { |
60 | 22 | return { |
61 | | action: func, |
62 | | param: Array.prototype.splice.call(arguments, funcNum + 1) |
63 | | } |
64 | | } |
65 | | } |
66 | 8 | return { |
67 | | action: pageNotFound |
68 | | }; |
69 | | } |
70 | 1 | return function lookup(req, res, next) { |
71 | 30 | var pathname = urlparse(req.url).pathname; |
72 | 30 | pathname = !pathname || pathname === '/' ? options.root : pathname; |
73 | 30 | var rewrite = options.rewrite; |
74 | 30 | var rewritePath = ''; |
75 | 30 | for(var key in rewrite) { |
76 | 58 | var reg = new RegExp('^' + key); |
77 | 58 | rewritePath = pathname.replace(reg, rewrite[key]); |
78 | 58 | if (rewritePath !== pathname) { |
79 | 4 | pathname = rewritePath; |
80 | 4 | break; |
81 | | } |
82 | | } |
83 | 30 | var segments = pathname.slice(1).split('/'); |
84 | 30 | var actionInfo = getActionParam.apply(null, segments); |
85 | 30 | req.param = actionInfo.param; |
86 | 30 | actionInfo.action.apply(null, arguments); |
87 | | } |
88 | | } |