2013-08-24 43 views
0

我開始使用node.js並表達一些寧靜的API。我把我的邏輯分解成控制器。每個控制器都有一些對應於我的API的方法。我不想每次使用新控制器向現有控制器或現有控制器添加新功能或全新功能時更新我的​​路線。爲此,我試圖通過一組簡單的路由來定義我的restful api,並且足夠聰明地根據現有的控制器和方法進行處理。爲此,我有這個...在node.js中顯示「自動」路由

"use strict"; 

module.exports = function (app) { 
    var routes = [ 
     { 
      'get'  : true, 
      'put'  : false, 
      'post'  : false, 
      'update'  : false, 
      'delete'  : false, 
      'controller' : '', 
      'action'  : 'search', 
      'url'  : '/:controller/search/:query/:page?' 
     }, 
     { 
      'get'  : true, 
      'put'  : false, 
      'post'  : false, 
      'update'  : false, 
      'delete'  : false, 
      'controller' : '', 
      'action'  : '', 
      'url'  : '/:controller/' 
     }, 
     { 
      'get'  : true, 
      'put'  : false, 
      'post'  : true, 
      'update'  : true, 
      'delete'  : true, 
      'controller' : '', 
      'action'  : '', 
      'url'  : '/:controller/:id' 
     }, 
     { 
      'get'  : true, 
      'put'  : false, 
      'post'  : true, 
      'update'  : false, 
      'delete'  : false, 
      'controller' : '', 
      'action'  : '', 
      'url'  : '/:controller/:id/:action' 
     } 
    ]; 

    function setupRoute(method, item) { 
     if (method in item && item[method]) { 
      console.log('Init route: ' + method.toUpperCase() + ' ' + item.url); 
      app[method](item.url, function(req, res) { 
       var c = ''; 
       if ('controller' in item) { 
        c = item.controller; 
       } 
       var a = ''; 
       if ('action' in item) { 
        c = item.action; 
       } 

       if ('controller' in req.params) { 
        c = req.params.controller; 
       } 
       if ('action' in req.params) { 
        a = req.params.action; 
       } 
       if (c == '') { 
        c = 'default'; 
       } 
       if (a != '') { 
        a += '_'; 
       } 
       a += req.method.toLowerCase(); 

       c = c.toLowerCase(); 
       a = a.toLowerCase(); 

       if (c in app.controllers) { 
        if (a in app.controllers[c]) { 
         app.controllers[c][a](req, res); 
        } else { 
         console.log('Unknown action on controller ' + a); 
         res.status(400).send('Bad Request'); 
        } 
       } else { 
        console.log('Unknown Controller ' + c); 
        res.status(404).send('Not found'); 
       } 
      }); 
     } else { 
      app[method](item.url, function(req, res) { 
       res.status(405).send('Method Not Allowed'); 
      } 
     } 
    } 

    routes.forEach(function(item) {  
     setupRoute('get', item); 
     setupRoute('put', item); 
     setupRoute('post', item); 
     setupRoute('update', item); 
     setupRoute('delete', item); 
    }); 
} 

這樣設置的東西有任何問題嗎?

有沒有更好的方式去做這件事?

回答

0

它看起來像我喜歡有一個配置文件與所有的路線,而不是按照通常的方式來構建應用程序的快遞。如果是這種情況,我建議切換到Hapi。 Hapi是一個以配置爲中心的框架,可讓您從配置對象輕鬆構建API。這聽起來正是你想要做的。

+0

或類似於Rails的機車(http://locomotivejs.org/)(Express更像Sinatra)。 – tandrewnichols

2

我已經嘗試了許多不同的方法來分解node.js中的路由。如果你正在做一個小應用,把它們放在app.js中是有道理的,但如果你開始有很多不同的路由被很多不同的控制器處理,它可能會很快變得混亂。如果你試圖做的工作(我建議進行廣泛的測試),那麼我認爲這樣做很好,但請記住,只是工作的複雜「魔術」可能很慢,很難維護並且難以調試。我曾嘗試過一段時間來做類似的事情,但最終選擇通過向每個控制器添加「register_routes」方法來簡化它。因此,像這樣:

module.exports = { 
    register_routes: function(app, callback) { 
     app.get('/something', function(req, res){ 
      // Do stuff 
     }); 
     callback(); 
    } 
} 

然後在路線/ index.js

module.exports = [ 
    require('./something'), 
    require('./something_else') // etc... 
]; 

然後在app.js

var controllers = require('routes'); 
async.eachSeries(controllers, function(controller, cb){ 
    controller.register_routes(app, cb); 
}, function(err){ 
    // done 
}); 

注意,使用內部register_routes回調,建議等等該路線以正確的順序註冊。

有可能的方式來構建路線的快遞是壞的,但一般來說,如果它的工作,應該沒事的(特別是如果它是你的項目)。

但是,像danielepolencic建議的那樣,您可能會喜歡其他處理路由更自然的框架。