Dealing with Sessions in Compojure
I recently started working with Compojure, a web framework for programming language Clojure. After playing around with basic GET and POST requests I tried to store and load data from a session. As Compojure is quiet new, there is not much documentation how to deal with sessions, particularly as Compojure and it’s API still changes fast.
In the following post I’ll show a brief example on how to create a login page with Compojure 0.3.2 running on Clojure 1.1.0.
What is Clojure?
Clojure is a Lisp dialect. So it’s a programming language based on the principles of Lisp. The interesting part about Clojure is that it runs on the Java Virtual Machine. As a developer you can therefore use the bright variety of Java written libraries in your code without touching one line of Java. Use the power of Java libraries together with the power of Lisp.
What is Compojure?
Compojure is a web framework for Clojure. It handles incoming request, offers an easy way to create servlets and provides basic functionality for HTML templates. The current stable version 0.3.2. Compojure is a young project and things change fast there, so be aware that a 0.3.2 application might not run on 0.4.
What is a session?
Basically it’s a per-user store managed by the server. For example a server backend can store the credentials of a user that it received in a request in this store making it possible to identify the user again when he or she does a second request. Usually this functionality is achieved by a library or by the interpreter itself (for example in PHP) and is implemented by storing the session data either in memory or on disk together with a unique identifier that is then stored in a cookie at the users computer. So when the user comes back, the cookie is read and the identifier is used to find the data for the user.
A basic example
Before we work with a session, let’s create a simple webpage that displays hello world for us.
The example is straight forward. We define a set of routes. In our example the route is “/*”, so it matches everything. The route then takes a function as a second argument. In our case we use the templating mechanism of Compojure and create a simple HTML response with the (html) macro.
We then start the server using the (run-server) macro and binding our routes to a specified mountpoint. I won’t go into details about servlets but usually it is sufficient if you have a servlet running on the mountpoint “/*” and then a set of routes.
To run the server you can use a small script like this one:
java -cp $CLASSPATH clojure.lang.Script net/experimentalworks/clojure/serve.clj
Before we can start adding sessions we have to be aware that Compojure has a mechanism called decorating. So you can decorate a set or routes with what Compojure calls a middleware. We will think of it as a way to enable advanced mechanism. To add the session mechanism to a set of routes use the (decorate) macro as shown in the following code:
Note the that we define a session decoration. At the moment sessions only support in-memory storage (which by the way should be usually the way you want to manage sessions). The :memory keyword here is to tell Compojure to store it’s sessions in memory. Although you can omit the keyword, I prefer writing it down so people can easily figure out how our session is stored.
Creating a login
Let’s create a login. We will first add a new route called /login/:user. This will tell Compojure that the last part of the query string is a parameter and it should extract it. We can then access the value using (:user params). We use the (session-assoc) function to associate our username with the session-key :loggedin. Here is what the code looks like:
You can then “login” to your site using http://localhost:8080/login/test and you Compojure will recognize you again if you go back to http://localhost:8080/
To logout, we clear the key itself. Let’s a have a look directly into the code. We use the (session-dissoc) function to drop the key (it seems that clear-session is broken in my Compojure checkout for whatever reasons..need to debug *debug*).
Use http://localhost:8080/logout to get rid of your session.
The basic idea behind Compojure sessions is simple and I hope you were able to grasp the idea a little bit. What can be annoying and what I didn’t show you is that you might run into problems within the actual implementation, although the basic stuff should work fine. Once you figured out the basics you can read and write sessions withing seconds and the code becomes clean and beautiful. Feel free to comment on this article if you like the post, it’s the only measurement for me that I can use to make sure I’m not writing stupid stuff.