Fine-grained per-method middleware use with Reitit
Table of Contents
Fact: I have middleware performing authentication (in this case, my CAS authentication middleware) Need: This middleware should apply to client-facing SPA-rendered views, which are requested via GET.
- Constraint: This middleware does NOT apply to non-get routes (which are headless so the authentication must be handled differently)
- Constraint: There exist headless GET routes, too, which should not be CAS authenticated
- Constraint: Individual routes may have a CAS-authenticated GET response, as well as non-CAS POST, PATCH, and DELETE responses
Reitit allowed me to specify middleware on a delightfully granular level to solve this. Here’s how it looks:
(defn front-cas-get [& merge-maps]
"Serve the homepage to GET requests, with CAS authentication"
(let [base {:get {:handler home-page
:middleware [middleware/wrap-cas]}}]
(apply merge base merge-maps)))
(defn home-routes
[]
["" {:middleware [middleware/wrap-base
middleware/wrap-formats]}
["/" (front-cas-get)] ;; includes the dashboard
["/form"
["/:form-id" (front-cas-get
{:post submit-initial-form
#_(:patch nil
:delete nil)})]]])
You can see the result on the POST "/:form-id"
route, which has no CAS middleware, while the GET "/:form-id"
is under CAS. Of course, future iterations will apply other authorization middleware to those other routes. Exactly as desired!