Middleware used in a nested router is evaluated on unrelated routes.
See original GitHub issueDescriptions
The middleware used in a nested-router can be triggered if the regexp matches (matchedRoute) with the unrelated path. The behavior is something intuitive or not easily predictable.
I wrote one router like this, intending to run “checkAuth” middleware when the user accesses to /a/1
or any other subroutes written under /a
.
function createAjaxRouter() {
const router = createRouter('/a');
router.use(checkAuth);
router.get('/1', routeHandler(1))
return router.routes();
}
However, accessing /about
(defined elsewhere) can trigger “checkAuth”. This is because middleware is evaluated when the request-path matches /a(.*)
.
This issue can be avoided by defining the routes /about
before this nested router, but manually managing the order of nested routes is difficult.
I wonder if the library can guarantee that middleware used inside the nested-routes are used only in nested routes.
Environment
node.js version: v11.6.0 (Windows)
npm/yarn and version: 6.14.5
@koa/router
version: 9.0.1
koa
version: 2.12.0
Code sample:
const Koa = require('koa');
const Router = require('@koa/router');
function createRouter(prefix) {
return new Router({
prefix
});
}
function routeHandler(x) {
return async ctx => {
console.log(x);
ctx.body = `${x}`;
}
}
async function checkAuth(ctx, next) {
console.log('checkAuth');
// if (ctx.query['auth'] != "1") {
// throw new Error("not authed");
// }
await next();
}
function createAjaxRouter() {
// match for '/a(.*)'
const router = createRouter('/a');
router.use(checkAuth);
router.get('/1', routeHandler(1))
return router.routes();
}
function createIndexRouter() {
// match for '(.*)'
const router = createRouter();
router.get('/', routeHandler('index'));
router.get('/about', routeHandler('about'));
return router.routes();
}
function setRouter(app) {
// match for '(.*)'
const router = createRouter();
router.use(createAjaxRouter());
router.use(createIndexRouter());
// order of path in routes.router.stack =>
// ['/a(.*)', '/a/1', '/', '/about']
const routes = router.routes();
app.use(router.routes());
app.use(router.allowedMethods());
}
const app = new Koa();
setRouter(app);
app.listen(3010);
Expected Behavior:
Access to /about
should not run the middleware used for nested routes with prefix: /a
Actual Behavior:
Access to /about
can trigger the middleware defined in the nested routes.
Issue Analytics
- State:
- Created 3 years ago
- Comments:7
Looks interesting, thanks for the pointer !
I think #44 is orthogonal to this issue.
That issue is about the
Router.use
d middleware not executing when no paths are matched. In order to solve that one needs to userouter.(get|post|...|all)
instead.This issue is about
Router.use
d middleware on “inner router 1” executing on a match in “inner router 2”, which, I suspect, is because there is no “local scope” for the inner routers. (This is what I intended with Item 1, although it doesn’t seem very clear on second read)Still, thank you for your input.