@johnjtran thanks for the pointer to the examples! Let me know how your process goes -- I will do the same 🙂
One thing I'm curious about is an idiomatic way of handling mid-path destructuring logic like compojure
's context
. Since the different HTTP methods of a particular endpoint often re-use the same data out of the request, we have a habit of defining:
(context "/path/to/endpoint" {:keys [thing-from-request] :as req}
(let-routes [processed-things (process thing-from-request)]
(GET ....
(PUT ....
(POST ....
(DELETE ....
Which prevents a bunch of boilerplate.
I know reitit
allows attaching mid-path data, as well as middleware, but I haven't seen anywhere that the request
is exposed for processing mid-route, perhaps because of the "match first" semantics?
Is the best way to handle this by adding a middleware that adds processed-things
to the request, and only applying that middleware on those routes? Thanks in advance 🙂@david.russell one of the reasons for starting to create reitit was how compojure handles the context
. All the child-routes are re-created for each request, with real-life 4-levels deep context tree, basically the whole routing tree is re-created for each request. The macros help a bit - much of the computation still happens just once, but it's still… not good. Here's analysis what happens: https://www.slideshare.net/metosin/naked-performance-with-clojure#20 (slides 20-23).
with reitit, you need to write a middleware/interceptor for the common things, and destructure on the handler. It’s more verbose, but hopefully, easier to understand.
… or you can have a custom wrapper fn or macro to build the handler. Haven’t used in a long time, but plumbings fnk
removes a lot of boilerplate from destucturing:
["/api/{id}" {:parameters {:body {:x int?, :y int?}
:path {:id uuid?}}
:get (fnk [[:parameters
[:body x y]
[:path id]
[:user login]
session] ...)}]
you could also add schema-annotations on the fnk
itself and pull out the :paremeters
schemas out of those. Less verbose, more magic:
["/api/{id}" {:get (fnk [[:parameters
[:body x :- int?, y :- int?]
[:path id :- uuid?]
[:user login]
session] ...)}]
@ikitommi thanks so much for the feedback! Given the overhead of context
, I will be very curious to run some perf tests before and after a transition..
For our purposes I think a combination of the options you suggest will work fine -- a middleware to replace the logic in let-routes
, insert data back into the request, and then destructure them on the handlers. For common destructures we could even re-use the same map, given the endpoint definitions are data 🙂
I haven't used fnk
before and will have to check it out.
Appreciate all the input!!