Hi folks, I’m trying to migrate from Bidi to Reitit and have a few routes that are proving to be a bit tricky. We used regex based routes in bidi quite heavily and I’m not sure how to apply them in Reitit. I wasn’t sure whether to discuss them here or in the bug tracker, so I opened some bugs there: https://github.com/metosin/reitit/issues/721, https://github.com/metosin/reitit/issues/722
@ikitommi so is there no way to express a Regex based route in Reitit like shown in https://github.com/metosin/reitit/issues/722? In theory, could there be a Regex based router which could dispatch on these kinds of routes?
answered on the issue. I think there might be a simple way, but nothing built-in, sorry
Nice, thanks! I’ve opened a PR to start a discussion about possibly building this in more directly too: https://github.com/metosin/reitit/pull/723
in the docs https://github.com/metosin/reitit/blob/master/doc/basics/route_conflicts.md
the key is :conflicting (no ? at the end) so maybe that's the issue?
Thanks for catching that. I’ve retested and updated the issues, but it doesn’t resolve the routing issues
You can try composing routers so that the non-conflicting routes will have as good performance as it gets while conflicting ones can still be used https://cljdoc.org/d/metosin/reitit/0.7.2/doc/advanced/composing-routers#performance
You can also try setting :conflicts nil on the whole router to see if there's some other issues too
Could I use that to satisfy something like these routes?
/inbox
/teams/:uuid
/:uuid
;; also have a not found route when it doesn't match
My existing routing structure has item IDs (UUIDs) at the same nesting level as /inbox and /teams. How could I setup routing so that I could match on all of these routes?First goal I guess is just to get it work and this should
(r/router
[["/"
["inbox" ::inbox]
["teams/:uuid" ::team]
[":uuid" ::uuid]]]
{:conflicts nil})
(let [rtr (r/router ["/users"
["" :user/list]
["/new" :user/new]
["/:id" :user/detail]]
{:conflicts nil})]
(map #(get-in % [:data :name])
[(r/match-by-path rtr "/users")
(r/match-by-path rtr "/users/new")
(r/match-by-path rtr "/users/123")]))
=> (:user/list :user/new :user/detail)
Nice! ThanksAs for your issue with regex param matching, I don't know of a way to do that (but it could be possible nonetheless). I'd use a middleware to handle coercion errors and return 400 or 404 or whatever appropriate
Is it “ok” to have to use {:conflicts nil} on your routes? I understand it will have a performance impact, but is there anything else it would affect?
Not that I know of... It'll use a less-efficient (probably linear) routing algo but it'll work just fine. I've used it without issues while implementing a mastodon-compatible api
You can try looking at how it quarantines conflicting routes and play around with nested routers to optimize that, but I've never done that myself https://github.com/metosin/reitit/blob/30fd739fa987ba3538b4ad66028241f74778d63c/modules/reitit-core/src/reitit/core.cljc#L354
> Is it “ok” to have to use {:conflicts nil} on your routes? I understand it will have a performance impact, but is there anything else it would affect?
@danielcompton yes it is, and for simplicity, this could be the default (and could be for 1.0.0, when it’s ok to break things). What happens here:
1. only the conflicting routes will be put behind linear-router (which is the default router algo in compojure, bidi etc)
2. rest will be served with best router algo: tree, static, whatnot
… as all router algos satisfy the same Router protocol, they behave exactly the same.
performance is not optimal, but just for the conflicting routes and it will still be order of magnitude faster than most of the regex-based routers.
but, there are no guards (e.g. router based path parameter type) in reitit routing, like there is in bidi.