reitit

2024-02-02T01:58:17.237969Z

At my company, we use Compojure and have roughly 300 endpoints, not to mention the endpoints with multiple methods associated. This works but is pretty slow and hard to edit. I'm considering transitioning us to use reitit, but it's going to take time to implement and deploy, so there will have to be a period of "using both". Does anyone have tips for supporting both while performing such a transition?

2024-02-02T02:23:35.112269Z

Similar situation here. Except all the routes need to be on the same swagger page, so having them under two routing frameworks seems impossible. I prototyped a layer of macros that expand to reitit routes, it might be interesting to look at for now, eventually I'd like to make it its own library. It would be especially cool to have a tool that could then macroexpand-1 all these compatibility-bridge macros and magically turn the code into reitit. But that's just an idea for now. https://github.com/threatgrid/ctia/pull/1403

2024-02-02T02:24:54.138629Z

The actual compojure-api->reitit bridging macros are in src/ctia/lib/compojure/api/core_reitit.clj https://github.com/threatgrid/ctia/pull/1403/files#diff-c44fa66bbfa3254a08bfbe3f09e1175371728bd59739c2299f4d491ff7e22a01

2024-02-02T02:26:02.006159Z

i don't have access to those channels, but i'll check that out

2024-02-02T02:26:37.811859Z

oh i see, lol that's just slack rendering it funny

👍 1
2024-02-02T02:27:17.772029Z

The tests explain the approach better test/ctia/lib/compojure/api/core_reitit_test.clj https://github.com/threatgrid/ctia/pull/1403/files#diff-1c3acd943e1aeb074115b5d6103c7598f3b18fc524575be5c640d529512cf554

2024-02-02T02:28:43.123469Z

For example

(is (= '["/my-route" {:get {:handler (clojure.core/fn [req__0] (clojure.core/let [] (do {:status 200})))}}]
         (dexpand-1
           `(sut/GET "/my-route" []
                     {:status 200}))))

2024-02-02T02:33:30.069859Z

Couple of things to keep in mind before embarking. 1. You can't have routing logic based on any part of the request other than the uri or request-method, e.g. (context "foo" req (cond (get req ...) ...) 2. You won't necessarily get the full speedup of a reitit-first app, since you might have route conflicts https://cljdoc.org/d/metosin/reitit/0.7.0-alpha7/doc/basics/route-conflicts#:~:text=When%20a%20Router%20is%20created,thrown%20with%20a%20descriptive%20message.

2024-02-02T02:36:12.320509Z

But also, compojure-api can be incredibly slow if you use context , so it's worth trying. I got a 600% speedup in CI runs by changing (context "" (GET )) to (let [r (GET ))] (context "" r)).

2024-02-02T02:38:35.516189Z

That was also programmatically achieved. Might be worth trying first to get a taste of potential speedups, here's how I did it https://github.com/threatgrid/ctia/commit/d5c24198238145d0b387ef9d905b56982108a66b

2024-02-02T02:42:23.158209Z

Though this is with compojure-api 1.x. There might be better optimizations on the 2.x branch.

2024-02-02T02:52:24.505179Z

this is great, thanks

❤️ 1
2024-02-02T02:54:29.982999Z

Oh, and I'm still working out what the equivalent to compojure.api.api/api is in reitit. You might be using a similar batteries-included way of starting the app.

2024-02-02T02:55:18.191209Z

Equivalent in terms of preserving the same middleware.

ikitommi 2024-02-02T05:47:06.561289Z

good discussion. I have migrated few c-api project to reitit. reitit definitely needs the battery-packs, currently copy-pasting the good practice boilerplate from project to another. I have also drafted an functional layer of top of reitit, with ideas picked out from frameworks from other languages. One missing concept in reitit is a module, which would tie together different aspects (routes, data, middleware, schemas) and could be used as a simple abstraction to build up things fast, “web server with api-module”. Opinions and scattered config can be hided an an unified module configuration (backed by malli) - you should be able to write c-api “api” as a module. Has been in the works for 5 years, might be done in a week or in a year. Maybe there should be a open brainstorm of this? c-api + reitit sounds really interesting, looking forward to that.

Ben Sless 2024-02-02T11:59:01.876109Z

One way you could migrate incrementally is by creating a reitit ring handler and specifying the old compojure handler as the default handler, then start migrating routes to the new router

☝️ 1
2024-02-02T14:08:25.423349Z

Oh that's clever

2024-02-02T02:03:08.179839Z

Be careful about sessions: https://github.com/ferdinand-beyer/reitit-ring-defaults#warning-on-session-middleware

👍 1
1
2024-02-02T14:22:28.525439Z

Is there an equivalent to compojure.core/wrap-routes? is it needed?

Ben Sless 2024-02-02T14:35:46.926579Z

No and no, a middleware can be a vector of wrap + args which archives the same effects Regarding application of middlewares, they're all applied after matching a route iirc

👍 1