0

I am making a new clean structure of nodejs (express) application.

I have a models folder with mongoose schemas, a routes folder for routing, a controllers folder (with all the logic) and main file server.js with following:

require('./models/notifications');
require('./models/articles');

const
    notificationRouter = require('./routes/notifications'),
    articleRouter = require('./routes/articles');

app.use('/notifications', notificationRouter);
app.use('/articles', articleRouter);

File routes/notifications.js

const
    router = require('express').Router(),
    controller = require('../controllers/notifications');

router.route('/')
      .get(controller.getAll)
      .post(controller.create);

router.route('/:id')
      .put(controller.seen);

module.exports = router;

File routes/articles.js

const
    router = require('express').Router(),
    controller = require('../controllers/articles');

router.route('/:articleId/comments')
      .post(controller.insertComment);

module.exports = router;

I also have a middleware function that ensures access only for people logged in. My question is, where should I put the middleware to make it as clean as possible? My concerns are:

  • The middleware is needed in different places
    • Notification routes are all for just logged in users, so it could be in server.js in app.use() function
    • But article routes have more variety, e.g. everybody can see article, but just logged in users can comment it. So I have to have the middleware inside routing file.
  • Is this good place to use global function (for the middleware)?
  • Do I really need same require function (of just one middleware) in many routing files?

Thanks for all and any advices or criticism of my clean solution.

Majkeee
  • 960
  • 1
  • 8
  • 28

1 Answers1

0

I also have a middleware function that ensures access only for people logged in. My question is, where should I put the middleware to make it as clean as possible?

The simplest scheme is to define the few routes that do not require authentication, then after that, you would do an app.use() for your auth middleware as it will then apply to all routes you define after that.

But article routes have more variety, e.g. everybody can see article, but just logged in users can comment it. So I have to have the middleware inside routing file.

If you have routers that require auth on some routes and not on others in that router, then you've created a design that does not allow for the simplest way to check authentication. To make that work, you will have to add an auth check with router.use() to ever router that has routes that need authentication. Again, you define the routes that don't need auth first, then do a router.use() with your auth middleware, then define the routes that do require auth.

Do I really need same require function (of just one middleware) in many routing files?

That depends upon your design. If your design requires you to add auth middleware to every single router, then you will need to require in that middleware for every single router file. But, if you design your routers so that routers aren't a mix of auth and non-auth routes, then you can probably handle the auth middleware at a higher level by defining the non-auth routers first, then add your auth middleware with an app.use() then define your routers that require auth. The complexity of handling the auth depends entirely upon how you organize the routes that require auth. If you mix them with routes that don't require auth, then the code is definitely more verbose to define the autn appropriately. If you separate the auth, from non-auth routes, you can probably add in the auth middleware at a higher level and perhaps only once.

Is this good place to use global function (for the middleware)?

No. It's no big deal to add one require() statement to the top of a module to get your middleware when you need and then you can avoid the use of globals.


The general question about avoiding using a require() at the top of a lot of your modules has been discussed before. Here are some of those references:

Node.js global require

How to properly require files into another file

NodeJS require all modules in one file, good practice?

How to make module (such as bcrypt) available globally in Express?

jfriend00
  • 683,504
  • 96
  • 985
  • 979
  • Alright, you said exactly what I knew. Of course, I cannot use app.use(), otherwise this question wouldn't exist. My question was more like "is require really needed in every routing module and is it okay?" I guess you kinda answered it, so if no better answer comes, I accept it. – Majkeee May 12 '18 at 19:08
  • @Majkeee - Well, my main advice is to change the design of your routers to make specifying auth simpler so you don't mix auth and non-auth routes in every router.. – jfriend00 May 12 '18 at 19:09
  • @Majkeee - I added some references about the question of using the same `require()` in lots of node.js modules into my answer. That question arises regularly. In a nutshell, one point of modules is to make them as self describing and as independent as possible and this leads to a little repetition of `require()` that one wouldn't normally use in a different programming style. That's OK. It's in service of the node module design and the goals of that modular architecture. Rather than assuming some global environment is present, the module simply defines what it depends upon. This is good. – jfriend00 May 12 '18 at 19:20
  • Ok, those references cleared it for me. As for your main advice: I noticed it first time, but I ignored it as it goes against clean syntax and maybe even against intuitive way of modularizing. – Majkeee May 12 '18 at 20:04