Skip to content

ring.middleware.session/wrap-session doesn't work with reitit #205

@ikitommi

Description

@ikitommi

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:

  1. 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 in ring-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]}))
  1. 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]])))
  1. 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]])))

Metadata

Metadata

Assignees

No one assigned

    Type

    No type

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions