git clone 'https://github.com/hozumi/mongodb-session.git'

(ql:quickload :hozumi.mongodb-session)


Mongodb-session use mongodb as a Clojure/Ring's http session storage.

Alternative: This library relies on congomongo as a MongoDB client. If you are using monger, consider using mongers built-in session support.


Functional access

ring.middleware.session version.
Following examples are originated from sandbar-examples.
Ring-core must be higher than 0.3.0, because mongodb-session depend on the protocol defined ring.middleware.session.store.

(ns hello
  (:require [ring.middleware.session :as rs]
            [somnium.congomongo :as congo]
            [hozumi.mongodb-session :as mongoss]

(congo/mongo! :db "mydb" :host "")

(defroutes my-routes ....)

(def app (-> my-routes
           (rs/wrap-session {:store (mongoss/mongodb-store)})))

Then, you can use mongodb session in the same way as in-memory one.

(defn functional-handler
  "Functional style of working with a session."
  (let [counter (if-let [counter (-> request :session :counter)]
                  (+ counter 1)
    {:status 200
     :headers {"Content-Type" "text/html"}
     :body (html
            (layout "Functional" counter (link-to "/stateful" "Stateful")))
     :session {:counter counter}}))

Let's look at the mongodb.

% bin/mongo
MongoDB shell version: 1.6.3
connecting to: test
> use mydb
switched to db mydb
> db.ring_sessions.find()
{ "_id" : "0a7047f6-ad8a-45b0-b214-ba18830b9851",
  "_date" : "Sat Nov 06 2010 08:33:58 GMT+0900 (JST)",
  "counter" : 3 }

_id means cookie value of ring-session.
_date means when this session is started.
Default collection name mongodb-session use is ring_sessions. You can change this like below.

(mongoss/mongodb-store {:collection-name :my_sessions})

You can also change session id everytime when session is updated. This behavior prevents session fixation attack.

(mongoss/mongodb-store {:auto-key-change? true})

Statuful access

sandbar.stateful-session version.

(ns hello
  (:require [sandbar.stateful-session :as stateful]
            [somnium.congomongo :as mongo]
            [hozumi.mongodb-session :as mongoss]))
(mongo/mongo! :db "mydb" :host "")

(defroutes my-routes ....)

(def app (-> my-routes
           (stateful/wrap-stateful-session {:store (mongoss/mongodb-store)})))

You don't need to include :session entry in the response map.

(defn stateful-handler
  "Stateful style of working with a session."
  (let [counter (+ 1 (stateful/session-get :counter 0))]
    (do (stateful/session-put! :counter counter)
        {:status 200
         :headers {"Content-Type" "text/html"}
         :body (html
                 (layout "Stateful" counter
             (link-to "/functional" "Functional")))})))


> db.ring_sessions.find()
{ "_id" : "0a7047f6-ad8a-45b0-b214-ba18830b9851",
  "_date" : "Sat Nov 06 2010 08:33:58 GMT+0900 (JST)",
  "sandbar.stateful-session/session" : { "counter" : 2 } }



[org.clojars.hozumi/mongodb-session "1.0.1"]