ExpressJSのルーティングの自動化(Node.js)
肥大化とは別に、Expressのルーティングにもう一つ不満がある。
app.jsに以下の様に一々登録しないといけない事だ。
app.get('/', routes.index); app.get('/foo', routes.get_foo); app.get('/bar', routes.get_bar); app.post('/foo', routes.post_foo); app.post('/bar', routes.post_bar);
これでは新しいメソッドが追加されるたびに、記述を増やしていかなければならない。
という事で、昨日やった肥大化の解消を更に改良しつつ、ルーティングの自動化をしてみた。
app.js
var express = require('express') , http = require('http'); var app = express(); app.configure(function(){ app.set('port', process.env.PORT || 3000); app.set('views', __dirname + '/views'); app.set('view engine', 'hjs'); app.use(express.favicon()); app.use(express.logger('dev')); app.use(express.bodyParser()); app.use(express.methodOverride()); app.use(app.router); app.use(express.static(__dirname + '/public')); }); app.configure('development', function(){ app.use(express.errorHandler()); }); // ルーティング var routes = []; var fs = require('fs'); var files = fs.readdirSync('./routes'); for (i in files) { var ext = files[i].substr(files[i].lastIndexOf('.'), files[i].length); var name = files[i].substr(0, files[i].lastIndexOf('.')); if (ext === '.js') { routes[name] = require('./routes/' + name); for (j in routes[name]) { eval('var myfunc = routes[name].' + j); if (j.substr(0, 4) === 'get_') { var method = j.substr(4, j.length); app.get('/' + method, myfunc); } else if (j.substr(0, 5) === 'post_') { var method = j.substr(5, j.length); app.post('/' + method, myfunc); } else { app.get('/' + j, myfunc); } } } } app.get('/', routes['index'].index); http.createServer(app).listen(app.get('port'), function(){ console.log("Express server listening on port " + app.get('port')); });
上記でやっている事は、
- routesディレクトリ内の.jsファイルを取得し、
require
する - メソッド名が'get_ほにゃらら'ならば、'ほにゃらら'というリクエスト名でgetメソッドで登録
- メソッド名が'post_ほにゃらら'ならば、'ほにゃらら'というリクエスト名でpostメソッドで登録
- メソッド名がどちらでもなければ、そのままのリクエスト名でgetメソッドで登録
といった感じ。'/'にindexを割り当てるのは上記の条件に当てはまらないため。
readdirSync()
を使っているが、'/'の部分をindex判定させればreaddir()
でも書けるはず。
ただ、この処理は起動時だけだと思うので、どちらでも良いと思う。
/class/function/id/ /function/:num
な形にも対応させてみたいが、とりあえずここまで。