| 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 | | } |