-
Notifications
You must be signed in to change notification settings - Fork 261
Open
Description
Reitit is a route-first architecture: the middleware/interceptor chain is created and optimized per endpoint and the chain is only applied if a route is matched.
The approach has a caveat: some middleware, like Ring's wrap-session don't work as expected: wrap-session
instantiates the default memory store per instance. This means that every route will have their own memory-store. This is a surprising default and should be resolved.
How to fix:
- mount the
wrap-session
outside of the router so there is only one instance of the mw for the whole app. There is:middleware
option inring-handler
for this:
(require '[reitit.ring :as ring])
(require '[ring.middleware.session :as session])
(defn handler [{session :session}]
(let [counter (inc (:counter session 0))]
{:status 200
:body {:counter counter}
:session {:counter counter}}))
(def app
(ring/ring-handler
(ring/router
["/api"
["/ping" handler]
["/pong" handler]])
(ring/create-default-handler)
;; the middleware on ring-handler runs before routing
{:middleware [session/wrap-session]}))
- create a single session store and use it within the routing table (all instances of the session middleware will share the single store).
(require '[ring.middleware.session.memory :as memory])
;; single instance
(def store (memory/memory-store))
;; inside, with shared store
(def app
(ring/ring-handler
(ring/router
["/api"
{:middleware [[session/wrap-session {:store store}]]}
["/ping" handler]
["/pong" handler]])))
- Lift the
wrap-session
into Reitit Middleware & Interceptor and things just work.
(require '[reitit.ring.middleware.session :as session])
(def app
(ring/ring-handler
(ring/router
["/api"
{:middleware [(session/session-middleware)]}
["/ping" handler]
["/pong" handler]])))
kennyjwilli, khmelevskii, stelcodes, avocade, prestancedesign and 6 moregreen-coder, turlando, khmelevskii, acobster, prestancedesign and 2 more