Tuesday, April 7, 2009

Basic Happstack Blog App

Happstack is improving, and my old blog posts on HAppS are now out of date. So we're in need of a bare-bones app to demonstrate functionality. I also wanted a simple app without authentication capability to demonstrate how to integrate Happstack-Auth into a project. Blog apps seem to be one of the canonical beginner's examples in the web framework world, so I thought that would be a good choice to start with. As usual, this post is literate haskell and should compile as Main.lhs.

First, we define a blog post. A post has a title and a body, both of type String. The deriving clause is required by the Happstack state mechanism. The Ord instance isn't actually required for this example, but it is required if you want to build an IxSet from this data type, so I'm in the habit of including it.

Now the required Template Haskell voodoo to build these methods for us.

> $(mkMethods ''BlogState ['addPost, 'getPosts])

Before we go further I want to add a little infrastructure code that will simplify things later. It's a simple function that redirects the client to the specified URL.

> redir url = seeOther url (toResponse "")

New we define the layout of our site. We have one URL at "http://site.com/new". A GET request to this url returns a static HTML file containing a new post form. The form POSTS the results to the same URL, so we have to define a function to handle this request. The last "methodSP GET" matches the root URL "http://site.com/" and will just display the list of posts.

The msum in newPostHandlers is new as of Happstack 0.2. In prior versions, some functions required or returned data of type ServerPartT, and some used [ServerPartT]. Other functions required WebT data. In Happstack 0.2, everything was unified to work around a single ServerPartT. If you have an abstraction that needs several ServerPartTs, you usually want to collapse them using msum.
Our new post handler gets POSTed values from the HTTP request, constructs a Post, passes that to AddPost, and redirects to the root.

The view posts handler queries the GetPosts action for the list of posts. If the list is empty, it returns a simple message, otherwise it returns the posts as a string. toResponse converts strings into responses with a content type of text/plain. Generating proper HTML pages is not hard, but is beyond the scope of this example.

The rest of the code is standard infrastructure for a Happstack application. The only thing we have to do is declare an entry point with our state Component and pass it to startSystemState. Then we pass our previously defined impl function to simpleHTTP and we're done. A clean, working Happstack application in 75 lines of code.

I'm not familiar with all the inner workings of the state system. But it hasn't been too hard to get a basic working knowledge of how to use it. If you're looking for low-level details talk to some of the other gurus in #happs.

@Ram: I've coincidentally been writing a bit about how State works on my blog -- this post on the basics of using Happstack.State might be what you're looking for. My next few posts will correct some flaws in that code; I'm basically writing about some things I learned from writing a toy app while I'm learning the ins and outs of Happstack myself.