Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Expressjs: How to share route middleware accross routes

I have defined multiple route middleware and want to share them across multiple routes/controllers.

Here is my setup:

app.js requires ./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 loads all routes automaticly in the dir. A possible routes file can look like:

module.exports = function(app) {

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

};

Now I got route middleware:

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();
    });
}

which I want to use like:

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

module.exports = function(app) {

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

};

I also would like to avoid requiring them accross all routing files.

A possible solution would also be:

// 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);
    });
};

but I think not the best...

like image 257
bodokaiser Avatar asked Jul 27 '12 15:07

bodokaiser


People also ask

How many middleware can be on a single route?

We can use more than one middleware on an Express app instance, which means that we can use more than one middleware inside app.

How do Middlewares work in Express?

Middleware functions are functions that have access to the request object ( req ), the response object ( res ), and the next function in the application's request-response cycle. The next function is a function in the Express router which, when invoked, executes the middleware succeeding the current middleware.

Are routes middleware?

Note: Router functions are Express middleware, which means that they must either complete (respond to) the request or call the next function in the chain.

How many parameters you should pass in the middleware function?

Error-handling middleware always takes four arguments. You must provide four arguments to identify it as an error-handling middleware function.


1 Answers

Personally I would declare shared middleware in the app, not in the controllers, i.e.:

routes/home.js:

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

app.js:

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

You can also make a stack (array, not an object):

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

And if these middlewares are used on all routes except a few, you can do the following:

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

Now you can app.use(theseMiddlewares) that middleware, or if it needs to happen in a certain order relative to other middleware, you can use app.all('*', theseMiddlewares)

like image 184
Jonathan Ong Avatar answered Oct 06 '22 21:10

Jonathan Ong