@andreasp1994 compojure-api is built with macros (like Compojure), generating the source code. The :middleware
is resolved at (macro) compilation time, so it can’t see runtime bound things like mw
variable. I believe the evaluation could be delayed so that would work, feel free to create an issue out of that.
@ikitommi Thanks for the explanation! 🙂
In that case.. Do you have any suggestions for applying the authentication middleware conditionally on some routes?
@andreasp1994 you can put code in the :middleware
vector.
nil
s are stripped away, so :middleware [(if false auth-mw)]
doesn’t mount anything
there is compojure.api.middleware/compose-middleware
function that gets called.
are you thinking of applying mw based on request? or just having a code that selects the suitable mw at api creation time?
Basically just having a code that selects suitable mw at api creation time
In the end, it’s not very easy to know with Compojure what happens when - there are at least three stages: 1) compile-time (e.g. the macros get expanded) 2) creation-time (static parts of the routing tree are created - most of the middleware assembly should happen here) 3) request-time - Compojure is a dynamic routing lib and Some things happen at request-time. Fiddling with mw-chain here has a cost (if performance is a factor, usually not)
ok.
Thanks for letting me know. I really appreciate your help! Thank you! 🙂
np!
here’s an example:
(api
(context "/api" []
(context "/ipa" []
(GET "/drink" []
(ok {:was "good"})))))
;#Route{:info {:coercion :schema},
; :childs [#Route{:childs [#Route{:path "/api",
; :info {:static-context? true},
; :childs [#Route{:path "/ipa",
; :info {:static-context? true},
; :childs [#Route{:path "/drink", :method :get}]}]}]}]}
… all routes are created at creation time (marked with :static-context? true
(api
(context "/api" []
:query-params [q :- String]
(context "/ipa" []
(GET "/drink" []
(ok {:was "good"})))))
;#Route{:info {:coercion :schema},
; :childs [#Route{:childs [#Route{:path "/api",
; :info {:public {:parameters {:query {Keyword Any, :q java.lang.String}}}},
; :childs [#Route{:path "/ipa",
; :info {:static-context? true},
; :childs [#Route{:path "/drink", :method :get}]}]}]}]}
here all routes are re-created at request-time and the data q
is passed via a closure into the subroutes.
the perf is ok in both cases (thanks to precompiled everything), but the first one is still faster.
I get you! Thanks for the example! 😉