2012-07-27 53 views
4

我已經定義了多個路由中間件,並希望跨多個路由/控制器共享它們。Expressjs:如何在路徑上共享路由中間件

這裏是我的設置:

app.js需要./routes/index.js:

// load fs module 
var fs = require('fs'); 

// import routing files 
module.exports = function(app){ 
    fs.readdirSync(__dirname).forEach(function(file) { 
     if (file == "index.js") return; 
     var name = file.substr(0, file.indexOf('.')); 
     require('./' + name)(app); 
    }); 
}; 

index.js全自動負載在目錄中的所有路線。一個可能的路徑文件可以看起來像:

module.exports = function(app) { 

    app.get('/contacts', function(req, res, next) { 
     // routing stuff 
    }); 

}; 

現在,我得到的路線中間件:

function isAuthenticated(req, res, next) { 
    if (!req.session.authenticated) return next(new Error('user not authenticated')); 
}; 

function loadUser(req, res, next) { 
    var query = User.findById(req.session.user_id); 
    query.populate('contacts'); 
    query.exec(function(err, user) { 
     if (err) return next(err); 
     req.user = user; 
     next(); 
    }); 
} 

,我想用這樣的:

var User = require('../models/user'); 

module.exports = function(app) { 

    app.get('/contacts', isAuthenticated, loadUser, function(req, res, next) { 
     res.json(req.user.contacts); 
    }); 

}; 

我也想避免要求他們橫跨所有路由文件。

一個可能的解決方案也將是:

// load fs module 
var fs = require('fs'); 

var routeMiddleware = { 
    loadUser: function(req, res, next) { // logic }, 
    isAuthenticated: function(req, res, next) { // logic }, 
}; 


// import routing files 
module.exports = function(app){ 
    fs.readdirSync(__dirname).forEach(function(file) { 
     if (file == "index.js") return; 
     var name = file.substr(0, file.indexOf('.')); 
     require('./' + name)(app, routeMiddleware); 
    }); 
}; 

,但我認爲不是最好的...

回答

13

我個人申報共享中間件在應用程序中,而不是在控制器,即:

路由/ home.js:

module.exports = function(req, res, next) { \\ Code } 

app.js:

app.get('/', thisMiddleware, thatMiddleware, require('./routes/home')) 

你也可以做一個堆棧(數組,而不是一個對象):

theseMiddlewares = [thisMiddleware, thatMiddleware] 
app.get('/', theseMiddlewares, require('./routes/home')) 

如果這些中間件對所有線路使用除少數,你可以做到以下幾點:

theseMiddlewares = function(req, res, next) { 
    if (req.url.match(some_regex_for_urls_to_skip)) next() 
    else { 
    \\ do stuff... 
    next() 
    } 
} 

現在你可以app.use(theseMiddlewares)中間件,或者如果它需要相對於其他中間件一定的順序發生,你可以使用app.all('*', theseMiddlewares)

+1

你好,interessting解決方案。還有一種方法可以在應用程序中保存中間件本身嗎?我想用他們manuelly沒有要求他們的壓力。 – bodokaiser 2012-07-28 07:23:47

+0

就像我說過的那樣,我會在應用中聲明路由和中間件,並使路由中的每個模塊都成爲中間件,而不是像你這樣的路由。這樣你只需要在你的應用中使用中間件,而不是每個路由模塊。 – 2012-07-28 09:16:47