Things That Would Have Been Nice To Know: Happstack Requests

Stop me if you’ve heard this one before; after trying and failing to find an existing way to some task, a programmer gives up and creates their own method. No sooner than they’ve finished, they find the existing method. This happened to me.

Flash back a week. I’m sitting here working on my on-again-off-again project for a web app to access my home server. I’m trying to implement an image gallery application, and I need a method to read the URI and return images.

Happstack, my framework of choice, provides two methods for routing. There is some template-haskell magic that I don’t care to deal with, and there is string routing combinators. These combinators look like this:

routeFn = dir "foo" $ dir "bar" $ fooBarRouteFn

Basically, routeFn tests to see if the requested path is /foo/bar, and if so, calls the fooBarRouteFn route function. This is all fine and good for simple static routes, but I want to be able to request an arbitrary path on my server, and this solution won’t work. Looking through the Happstack documentation, I find a function called uriRest that “grab[s] the rest of the URL (dirs + query) and passes it to your handler”. Using this, if I request:

http://localhost:8000/foo/bar?foo=bar

… and I call uriRest, I’ll get:

"foo/bar?foo=bar"

I can then use Parsec to parse that into a usable data structure. Less than ideal, but something I can work with. So, work with it I did, implementing a parser to turn that into:

data URITail = URITail {getRouteDirs :: [String], getQueries :: Maybe [(String, Maybe String)] } deriving (Show)

This worked, though I wouldn’t call it “elegant”. I couldn’t shake the feeling I was doing it wrong. It turns out that I was.

Just Use askRq, Dummy!

It turns out that in any ServerPart, you can call askRq. This returns the Request. Request has a bunch of useful functions, here are a few of particular interest:

rqPaths

rqPaths returns a list of path segments. Exactly what would have been in my URITail‘s getRouteDirs field.

rqInputsQuery

rqInputsQuery returns a list of key-value pairs for each part of the QUERY_STRING. This is exactly what my URITail‘s getQueries field was for. Even better is the fact that this function handles all sorts of encoding issues that I, a web developer with hours of experience, wasn’t even aware of!

and others

Aside from these big two, there are functions to get the request method, get the requesting host, and all sorts of potentially useful information.

Don’t I Feel Silly?

Yeah, but it wouldn’t be the first time. I was pretty proud of my URITail module too, unfortunately it’ll have to languish in the dust bin, serving only as a learning experience. Luckily for you, you can learn from my mistakes.

If you want to route in a dynamic manner in Happstack, feel free to call askRq, and examine the request. Don’t re-invent the wheel.

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: