steambap / koa-tree-router

high performance router for Koa
MIT License
138 stars 11 forks source link

Getting matched route #14

Open rightaway opened 5 years ago

rightaway commented 5 years ago

Is there a way to get the matched route pattern as opposed to the actual url (ctx.request.url)?

Also this middleware appears near the end of all my middleware (after the ones that need to go before it like logging and permissions). But I'd like to be able to log the matched route pattern in the earlier middleware. Something like a router.getMatchedPattern function we could call at the beginning of our middleware to resolve the matched pattern which we can use throughout the other middleware. What do you think of such feature?

app.use(addToLogger(router.getMatchedPattern())
// lots of other middleware go here
app.use(othermiddleware)
app.use(router.routes())
steambap commented 5 years ago

I see no easy way to get the matched route pattern without hurting performance. However, PRs are welcome if you can fix it.

Since Koa middleware run in the order that they declared, if a middleware want to do something in the upstream middleware, it will require a lot of hack. I think a good middleware should be self-contained and has no black magic that can manipulate upstream middleware. Therefore, this feature should be in your Koa application, not in a module.

rightaway commented 5 years ago

koa-tree-router is already taking ctx.request.url and looking through all routes to determine which one matches. If you could expose that function so we could call it ourselves, koa-tree-router middleware will remain self-contained with no black magic.

We can just call that exposed function in another middleware (only if we'd like to log the matched route pattern early in the middleware stack). No routing happens until koa-tree-router is reached, just as before. So no change for people who don't need this functionality.

The only downside would be that if I log the matched route pattern, the route resolution happens twice. But since this is already up to 11 times faster than koa-router it's no problem. Plus I wouldn't be logging it in all cases. And people who aren't logging it would see no performance penalty at all.

steambap commented 5 years ago

What is the function that you want the router to expose?

rightaway commented 5 years ago

Something like router.getMatchedPattern(ctx), which uses ctx.request.url like /route/1 and returns the actual pattern that was matched, like /route/:param.

steambap commented 5 years ago

Let me think about it. Meanwhile, PRs are welcome.

dosentmatter commented 4 years ago

Can't you just prepend a middleware for each router[method]? You can also move the logic into reusable functions to avoid duplicate code.

// Replace this
router.get('/path', middleware)

// with
router.get('/path', addToLogger('/path'), middleware)

I think router.get('/path', middleware0, middleware1) is an undocumented feature, but I think it should work because handle accepts an array of functions. This feature is in koa-router.

An equivalent alternative is to use koa-compose:

router.get('/path', compose([addToLogger('/path'), middleware]))
rightaway commented 4 years ago

@dosentmatter That's duplication as well. If you change /path it has to always be done in 2 places.

Plus giving us the ability to call a generic function like I've suggested can be used in several ways beyond this.

dosentmatter commented 4 years ago

@rightaway It is duplicate in my example, but I mentioned above

You can also move the logic into reusable functions to avoid duplicate code.

So you can have a helper function that takes the input path '/path' and feeds it into two places. It would also take as input the router method eg. get and the subsequent middleware.

This is just a workaround for the time being since the feature doesn't exist. Though it could be part of how this feature is eventually implemented.

rightaway commented 4 years ago

As a workaround not a solution I understand.