ZijianHe / koa-router

Router middleware for koa.
MIT License
4.85k stars 406 forks source link

Conflicting routes when declared with prefix keyword #415

Open sujaykakkad opened 6 years ago

sujaykakkad commented 6 years ago

I have written this piece of code

const Koa = require("koa");
const Router = require('koa-router');
const app = new Koa();

const parentRouter = new Router()
const router = new Router({ prefix: '/countries'})

router.get('/', async(ctx) =>{
    console.log('countries called');
    ctx.body = {}
})

parentRouter.use(router.routes())

app.use(parentRouter.routes())

app.listen(3000);

console.log('Listening on port 3000')

When I call localhost:3000/countries then it prints countries called But it is conflicting with other routes also localhost:3000/some_route_1/countries prints countries called localhost:3000/some_route_1/some_route_2/countries prints countries called localhost:3000/some_route_1/some_route_2/some_route_3/countries prints countries called and so on

I guess it is adding it as suffix instead of prefix

DrFaraday commented 6 years ago

The problem is that, when nesting a router inside another one (via the router's .use() method), the child route is automatically prefixed with the regular expression (.*), which will match every string of characters. This basically means that any structure of the form:

const parentRouter = new KoaRouter();
const childRouter = new KoaRouter();
childRouter.get('/route');
childRouter.get('/much/nest/such/route');
parentRouter.use(childRouter.routes()) // child router is prefixed with (.*) here

Will always result in the first route being called when using parentRouter, as the regex means that as long as it ends with /route, it's a match.

I would really appreciate to have some context on this and understand why the route is prefixed with such a broad expression, as this makes some pieces of code potentially quite buggy.