Express.Router middleware is being called on all routes after routes are registered

express middleware list
express middleware for specific route
app.use() requires a middleware function
express middleware after response
express next function
node js middleware pattern
express get params
express middleware order

I have a simple app which has a login page and a section for authenticated users from where unauthenticated users are being redirected back to login. At the end of all my routes, I have app.all('*', ...) which returns 404 error page.

When I am authenticated, everything works fine, but if I log out and try to fetch unexisting route, I am redirected to the login page instead of getting 404 response.

I understand that this is because I added middleware which handles redirection but I would expect it to work only on routes specified in that one exact router - not in all routes (even the app-level ones) which are placed right after middleware.

The only solution I see at the moment is to use this authCheck middleware in every restricted route instead of registering it globally using router.use but I am still wondering if there is a better way?

const express = require('express')

module.exports = (app) => {
  const authRouter = express.Router()

  // ================================
  // ========= Public Routes ========
  // ================================
  app.get('/login', () => { /* ... login route */ })
  app.post('/login', () => { /* ... login route */ })

  // ====================================
  // ========= Restricted Routes ========
  // ====================================
  authRouter.use((req, res, next) => {
    req.isAuthenticated()
      ? next()
      : res.redirect('/login')
  })

  authRouter.get('/', () => { /* restricted route */ })

  // register restricted routes
  app.use(authRouter)

  // ========================================
  // ============ Other routes ==============
  // ========================================

  // error 404 route <--- this works only for authenticated users
  app.get('*', (req, res) => {

    res.status(404)
    res.render('error404')
  })
}

Thanks for any ideas..

try this, you can create an array of all URLs without auth and check inside middleware.

const authMiddleware = (req, res, next) => {
    /* Urls Without Auth */
    const withoutAuth = ['/login'];
    if (withoutAuth.includes(req.url) || req.isAuthenticated()) {
        next();
    } else {
        res.redirect('/login');
    }
};

app.use(authMiddleware);

Using Express middleware, Router-level middleware works in the same way as The following example code replicates the middleware for every request to the router router.use(​function (req, the next router if (req.params.id === '0') next('route') the router's middleware functions, call next('router')  Your argument is routes and you are using router to actually define the routes. router . get ( ' /controller/action ' , function () { Missing req and res arguments.

const express = require('express')
// Note: FWIW I think it's better to organize your middleware
// into separate files and store them into separate directory
// So you could use it like that:
// const verifyAuthMiddleware = require('./middleware/verifyAuthMiddleware);
const verifyAuthMiddleware = (req, res, next) => {
    req.isAuthenticated()
      ? next()
      : res.redirect('/login')
  };

module.exports = (app) => {    
  // ================================
  // ========= Public Routes ========
  // ================================
  app.get('/login', () => { /* ... login route */ })
  app.post('/login', () => { /* ... login route */ })

  // ====================================
  // ========= Restricted Routes ========
  // ====================================    
  // You can add the middleware like that
  app.get('/', [verifyAuthMiddleware], () => { /* restricted route */ });

  // Or you can add a middleware to a group of routes like that
  app.use('/user', [verifyAuthMiddleware]);
  // And then every route that starts with "/user" uses the middleware
  app.get('/user/settings', () => {});
  app.get('/user/wallet', () => {});
  app.get('/user', () => {});
  app.post('/user/wallet', () => {});
  // etc


  // ========================================
  // ============ Other routes ==============
  // ========================================

  // error 404 route <--- this works only for authenticated users
  app.get('*', (req, res) => {

    res.status(404)
    res.render('error404')
  })
}

Calling next('route') in middleware is ignored if a router is next in the , The following test : describe('when next("route") is called on a to application route', function(done){ var app = express(); var router Instead of jumping to the next registered '/foo/bar', it ends up calling the mounted '/bar' route anyway. I managed to forget about the reason why app.all is used entirely. Express is a routing and middleware web framework that has minimal functionality of its own: An Express application is essentially a series of middleware function calls. Middleware functions are functions that have access to the request object ( req ), the response object ( res ), and the next middleware function in the application’s request-response cycle.

thank you for your replies. In the end, I did it like this:

function authCheck (req, res, next) {
    return req.isAuthenticated()
        ? next()
        : res.redirect('/login')
}

// Product routes
const prodRouter = express.Router()
prodRouter.get('/', products.getlist)
prodRouter.get('/:uuid/:tab?', products.getbyId)
prodRouter.post('/:uuid/:tab?', products.update)

// Register product routes
app.use('/products', [authCheck, prodRouter])

// For all other routes return 404 error page
app.get('*', (req, res) => {
    res.status(404).render('error404')
})

With this approach, the authCheck middleware is being used only on /product routes so when I access /missing-page I get correctly the Error 404 page.

List All Routes in express app · Issue #3308 · expressjs/express , I've been fighting this for a bit, but I'm trying to gather a list of all of the endpoints I've tried 'express-list-router' and the code below, but none give the full Since paths are regular expression-based, there is no easy way in which routes registered directly on the app routes.push(middleware.route); } else  Use the express.Router class to create modular, mountable route handlers. A Router instance is a complete middleware and routing system; for this reason, it is often referred to as a “mini-app”. The following example creates a router as a module, loads a middleware function in it, defines some routes, and mounts the router module on a path in the main app.

A Better Way to Register Routes in Express, The first thing I'm going to do is create a file called app.js in our root It will be responsible for starting up the server, registering routes, Here's a quick example of how the Express Router works. will generate the following routes: registering middleware and registering all of the routes in the routes  Route handlers, being a middleware system, makes it possible to define multiple routes for a path. In the example below, two routes are defined for GET requests to /user/:id. The second router will not cause any problems, however it will never get called, because the first route ends the request-response cycle.

In What Order Does My Express.js Middleware Execute?, After some initial thoughts on the question, I found myself not 100% certain of The code I came up with is fairly straightforward, with a call to “.get” and This is true for all levels of your routing and middleware configuration. Module Contents¶ class routes.middleware.RoutesMiddleware (wsgi_app, mapper, use_method_override=True, path_info=True, singleton=True) ¶. Routing middleware that handles resolving the PATH_INFO in addition to optionally recognizing method overriding.

Express Middlewares, Demystified - Viral Shah, Express application: Middleware Layer Stack After that, any middlewares or routes registered on the adminRouter, will create a new Layer When we define the handle function of any Layer, it is actually called by another  The first thing in router_two is a middleware mounted at /, and since /testapi2 starts with /, the middleware is invoked. This logs to the console and calls next() telling Express to continue to match and invoke things. The next thing is the route GET /testapi2, which the request matches. This is invoked and res.json is called to write a response.

Comments
  • Without changing any code, you could change the flow of execution to get it to work properly.
  • I tried to move app.get('*') to the top but it started returning error 404 on all routes.. How would you change the order?
  • Honestly, I wouldn't recommend changing the order, as it would be confusing. There is most likely a better way.
  • @JanJůna Your code should not depend on the order of middleware, better go for the generic solution.
  • You might want to use app.use('*', ... rather than app.get('*', ....