sessions.md

Sessions

Kit defaults to using cookie-based sessions.

The session middleware is configured in the :cookie-session-config of the :handler/ring component. Session timeout is specified in seconds and defaults to 24 hours (i.e. 86400 seconds) of inactivity. Here is the default configuration. The business logic is provided by ring.middleware.session.cookie/cookie-store.

{:cookie-secret #or [#env COOKIE_SECRET "16charsecrethere"]
 :cookie-name "<project-ns>"
 :cookie-default-max-age 86400}

Accessing the session

Ring tracks sessions using the request map and the current session will be found under the :session key. Below we have a simple example of interaction with the session.

(ns myapp.home
  (:require
   [ring.util.response :refer [response]]))

(defn set-user! [id {session :session}]
  (-> (response (str "User set to: " id))
      (assoc :session (assoc session :user id))
      (assoc :headers {"Content-Type" "text/plain"})))

(defn remove-user! [{session :session}]
  (-> (response "User removed")
      (assoc :session (dissoc session :user))
      (assoc :headers {"Content-Type" "text/plain"})))

(defn clear-session! []
  (-> (response "Session cleared")
      (assoc :session nil)
      (assoc :headers {"Content-Type" "text/plain"})))

(def app-routes
  [""
   {:middleware [middleware/wrap-formats]}
   ["/login/:id" {:get (fn [{:keys [path-params] :as req}]
                         (set-user! (:id path-params) req))}]
   ["/remove" {:get remove-user!}]
   ["/logout" {:get clear-session!]])

Flash sessions

Flash sessions have a lifespan of a single request, these can be accessed using the :flash key instead of the :session key used for regular sessions.

Cookies

Cookies are found under the :cookies key of the request, eg:

{:cookies {"username" {:value "Bob"}}}

Conversely, to set a cookie on the response we simply update the response map with the desired cookie value:

(-> "response with a cookie" response (assoc-in [:cookies "username" :value] "Alice"))

Cookies can contain the following additional attributes in addition to the :value key:

Java objects such as dates must be explicitly encoded when stored in cookie sessions. The following example illustrates how to use tick library to add a reader for a zoned date-time:

(defn wrap-base
  [{:keys [cookie-opts]}]
  (let [{:keys [cookie-secret cookie-name cookie-default-max-age]} cookie-opts
        cookie-store (session.cookie/cookie-store {:key     (.getBytes ^String cookie-secret)
                                                   :readers {'inst                 (fn [x]
                                                                                     (some-> x (tick/parse) (tick/inst)))
                                                             'time/zoned-date-time #'tick/zoned-date-time}})]
    (fn [handler]
      (cond-> handler
              true (session/wrap-session {:store        cookie-store
                                          :cookie-name  cookie-name
                                          :cookie-attrs {:max-age cookie-default-max-age}})
              true (cookies/wrap-cookies)))))