0
votes

How do I modify session in Ring middleware? I basically want to have a history of accessed urls stored there and I just can't get the session to store values.

Sessions works correctly elsewhere at the code where I can return responses. I assume this has something to do with the issue and I'm not understanding something about how middlewares work.

Here is my current code

(defn wrap-history [handler]                                                                                                                                              
  (fn [req]                                                                                                                            
    (handler (assoc-in req [:session :history]                                                                                                                            
                       (vec (concat (-> req :session :history)  [(request/request-url req)]))))))                                                                

Here is the app (I'm using ring-defaults which includes session middleware)

(def app                                                                                                                                                          
  (-> all-routes                                                                                                                                                          
      (wrap-history)                                                                                                                                                      
      (wrap-defaults (assoc-in site-defaults [:security :anti-forgery] false))))                                                                  

The answer is probably pretty easy (probably something to do with how to return response from middleware instead of request) but I just don't seem to be able to find correct documentation for this..

1

1 Answers

0
votes

Okay I was correct that I misunderstood the basics of middleware. I tried to modify the handler request whereas I should have modified the returned response.

Here is working version of wrap-history. It checks both request and response for existing session as the session can be modified by some other code before the middleware as well.

(defn wrap-history 
  "Middleware that stores last 20 visited urls in session"
  [handler]                                                                   
  (fn [req]                                                                                                                                                               
    (let [resp (handler req)                                                                                                                                              
          session (or (:session resp) (:session req))                                                                                                                     
          updated-session (assoc session :history                                                                                                                         
                                 (vec (take-last 20 (concat (:history session) [(request/request-url req)]))))]                                                           
      (assoc resp :session updated-session))))