koa-router: Unable to reuse nested routers
I need to mount a shared router at different paths in my application. Something like this:
sharedRouter.get('/hello', (ctx) => {
ctx.body = 'Hello World!';
});
rootRouter.use(sharedRouter.routes());
rootRouter.use('/foo', sharedRouter.routes());
rootRouter.use('/bar', sharedRouter.routes());
app.use(rootRouter.routes());
Then, I expect the following routes to return the same thing:
GET /hello
GET /foo/hello
GET /bar/hello
However, with koa-router@7.0.1
, all of them throw 404 errors.
What is wrong with this?
Please, note that my real use case is a bit more complex: each mountpoint is supposed to receive its own middleware, which alters the behavior of the shared router.
About this issue
- Original URL
- State: open
- Created 8 years ago
- Reactions: 24
- Comments: 18
Commits related to this issue
- try to resolve #244 — committed to YanLobat/koa-router by deleted user 7 years ago
- Add test case from #244 — committed to YanLobat/koa-router by YanLobat 6 years ago
- [FIXED] Unable to reuse nested routers (#24) * [FIXED] Unable to reuse nested routers * [ADDED] tests about #18 #22 ZijianHe/koa-router#244 — committed to koajs/router by lichaozhy 5 years ago
I’m also waiting on a resolution of this issue
@tiant167 Thanks, but with this solution is only for using sharedRouter in one file. It is good to be able to nest router in a different part of application. For example, you have ‘/foo’ router in one file and ‘/bar’ in another.
@nadavoosh your solution throwing an error. But I slightly changed it and now this works for me:
const _ = require('lodash');
rootRouter.use('/foo', _.cloneDeep(sharedRouter).routes());
rootRouter.use('/bar', _.cloneDeep(sharedRouter).routes());
Maybe it depends on version?
After read the document of path-to-regexp, we are able to use RegExp-like string path to solve this problem.
For the nested router in the first comment, we can write router path as:
GET /hello
GET /foo/hello
GET /bar/hello
Thanks for the succinct example and for pointing this out. I was able to reproduce what you’re seeing.
It boils down to the fact that a router is mutated when it is mounted at a prefix. See this line
When
.routes()
is called onsharedRouter
, the returned layers are mutated in-place and the/foo
prefix is added to the existing/hello
-bound router. Further, when thesharedRouter
is mounted again, it is further prefixed. The resulting path would then be/bar/foo/hello
and if you request this path from your example you will get a200
.I started some work making the layer immutable, but it isn’t as easy as I’d like yet. I’ll have some test cases and a fix soon, but I’d recommend treating routers as mutable and unusable after they’re mounted at a prefix for now.
This affects all versions of koa-router.
Sorry for the inconvenience!
7.4.0 still not work.
I ran into this issue too, and I solved it by doing
which seems to work as intended.
@jbielick Okay! Thanks for your response. I will do it these days.