2
votes

I'm struggling with understanding how to properly use sessions in Compojure/Ring.

Some of the examples I have come across:

https://github.com/brentonashworth/sandbar-examples/blob/master/sessions/src/sandbar/examples/session_demo.clj

http://rjevans.net/post/2628238502/session-support-in-compojure-ring

https://github.com/ring-clojure/ring/wiki/Sessions

These examples do not help me understand how to integrate sessions into something like a login mechanism.

(defroutes main-routes
  (POST "/login" request (views/login request)))

;; views.clj
(defn login
  [request]
  (let [{params :params} request
        {username :username} params
        {password :password} params
        {session :session} request]
    (if (db/valid-user? username password)
     (-> (logged-in request)
         (assoc-in [:session :username] username))
      (not-logged-in))))

I realize that this isn't correct as logged-in returns hiccup/html and I believe that the ring response map isn't added on until after the route is fully evaluated. This seems to be why all of the above examples show sessions being added to a complete response map. But, one of the features of Compojure to begin with was abstracting away the requirement of the development having to work with the response map. Therefore I feel like I must me missing something.

What would the correct way be to do the above?

1
compojure is a routing library. It abstracts over the need to manually decide which code should handle a request, and has some conveniences for getting parameters out of a request for a handler function. It does not fully abstract away all usage of the request map.noisesmith

1 Answers

4
votes

If (logged-in request) returns the contents that should be rendered, then instead of associating :session :username onto the results of logged-in, you can return a proper response map:

{:body (logged-in request)
 :session (assoc session :username username)}

:status, :headers, etc. have decent defaults if you do not provide them.