Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Express Router bypass

In an express server, I am using user to display different things depending on permissions.

app.use("/user", ensureAdmin, ...myAdminFunc);
app.use("/user", ...myFunc);

Now, in my real code I have broken it into its own Express.Router object. And done app.use(adminRoutes);

All simple stuff currently. I found that the next("route") function doesn't work the way I expected. I have since read that I would STILL need to use the ensureAdmin middleware function on each route within the router.

I currently have below.

function ensureAdmin(req, res, next) {
    /*if not admin*/ next("route");
}
admin.get("/user", ensureAdmin, ...myAdminFunc);
admin.get("/other", ensureAdmin, ...myOtherAdminFunc);

I was hoping I could do a single middleware and bypass the whole router if needed. Something such as

function ensureAdmin(req, res, next) {
    /*if not admin*/ next("skip everything in this router");
}
admin = new Express.Router();
admin.use(ensureAdmin);
admin.get("/user", ...myAdminFunc);
admin.get("/other", ...myOtherAdminFunc);

but when I call next("route") within ensureAdmin it still goes on to the admin.get("/user", ...myAdminFunc); part.

I have read that this IS the expected behaviour for the next("route")

But wondering if there was a way that I have not been able to find yet to have it bypass everything within this admin Router collection? Maybe a next("router") or something?

I know the router itself doesn't count as a "route" but a route collection, which now makes sense why next("route") doesn't work.

  • Colin
like image 520
WORMSS Avatar asked Nov 09 '22 07:11

WORMSS


1 Answers

This feature was implemented in 2017 under THIS commit, see Line 121 of route.js

Usage is as follows

const express = require('express')
const app = express()

function myAwesomeCheck() {
    // randomly pick a router to go with
    return (Math.random() > 0.5) 
}

const router1 = express.Router()

router1.use((req, res, next) => {
    // using next('router') will skip this entire router and pass to router2
    if(myAwesomeCheck() === true) next('router')
    // using next() will just pass to the middleware
    else next()
})

router1.get('/', (req, res) => {
    res.send("I'm router 1, this means myAwesomeCheck was FALSE")
})

const router2 = express.Router()

router2.get('/', (req, res) => {
    res.send("I'm router 2, this means myAwesomeCheck was TRUE")
})

app.use(router1, router2)
app.listen(3000)

This allows you to completely skip a router if conditions are not met, in the examples case, it will randomly skip router1 50% of the time

like image 129
Jack Avatar answered Nov 15 '22 07:11

Jack