Archive | DMP Server Console RSS for this section

Happstack’s “Helpful” Exception Handler: A Better Solution

Recently I wrote about Happstack’s mismanagement of exceptions. I offered up a solution thab basically amounted to swallowing the exception and returning mzero. As a follow-up to that post, I’d like to offer a better solution.

I believe Happstack is on the right track. An uncaught exception does in fact represent an internal server error, not a file not found, however Happstack misses the mark in a few ways. First, it prints the exception message, which for reasons I went into last week, is bad. And second, it doesn’t provide a mechanism to override this behavior.

It was suggested to me that I could place a monad on top of the ServerPartT transformer stack that re-implements fail. This represents a few issues for me. If I were to do this, I wouldn’t be able to use the basic ServerPart monad, greatly complicating my code as this locks me out of all library functions that take this type. Secondly, it’s an unnessesary level of indirection. Why should I add a monad to the stack that does nothing except re-implement fail? Why can’t I configure Happstack to use a custom exception response?

So, What Are You Going To Do About It?

Good question. I’ve come up with a solution that I’m fairly satisfied with. At the heart of this issue are IO actions that throw exceptions. To perform an IO action inside of a ServerPart, you must lift ServerPart‘s IO monad. This is done like so:

foo <- liftIO $ bar

This snippet executes the IO action bar and binds its result to foo. Since, typically speaking, only IO actions throw, this represents a good place to start working. We can insert a call to try here, but this can get tedious given enough IO actions. Why don’t we create a function?

tryIO :: Maybe (SomeException -> ServerPart Response) -> IO a -> ServerPart a tryIO mf io = do result <- liftIO $ try io case (result) of Right good -> return good Left exception -> handle exception mf where handle exception (Just handler) = escape $ handler exception handle _ Nothing = mzero

Meet my tryIO function. This function wraps liftIO and try into one nice and neat function. It even takes an optional response generator. Let’s take a look at this bit-by-bit.

tryIO :: Maybe (SomeException -> ServerPart Response) -> IO a -> ServerPart a

This function takes a function that takes a SomeException, and returns a ServerPart Response. This function is wrapped in a Maybe. The function also takes an IO action, and returns a ServerPart a. Basically, this works like a specialized version of liftIO. Unlike a vanilla liftIO, it can take an optional exception handler.

tryIO mf io = do result <- liftIO $ try io case (result) of Right good -> return good Left exception -> handle exception mf

Here we have the meat of this function. First, the IO action is wrapped in a call to try. Next this is promoted to a ServerPart via the call to liftIO. The result of this will be Either a SomeException, or a valid result. We use a case statement to examine the result, and either return the good result, or call handle and pass it the exception and the exception handler.

where handle exception (Just handler) = escape $ handler exception handle _ Nothing = mzero

Finally, we handle the exception. If an exception handler was passed in, it’s called, and then the response is returned to Happstack via escape. If no handler was passed in, the function returns mzero.

The function escape is very useful here. This function is basically like returning mzero, only instead of the response handler failing, it returns a ServerPart Response immediately. This allows you to break out of a deeply nested function easily without having to manually return from each function.

The result

The result of this new function is that I can use tryIO as I would have used liftIO in a ServerPart function. I can either call…

foo <- tryIO Nothing bar

…and have my response handler fail with mzero if an exception is thrown, or I can call…

foo <- tryIO (Just baz) bar

…and have my response handler fail and return the result of baz. baz could even do some cleanup and try to call the initial response handler over again if it wanted to! Currently, when an IO action fails in my application, users see this lovely error message:

none_of_your_business

Much better. Unless you’re a hacker!

Happstack’s “Helpful” Exception Handler

Lately I’ve been messing around with web development in Haskell using Happstack. I believe that web development is something that a pure functional language excels in. Web apps are inherently stateless, so it stands to reason that a stateless programming language would be a good fit.

Happstack provides many of the nice features one would expect of a web framework. Among these things is a top-level exception handler to prevent exceptions from bringing down the server. Suppose you try to call head on an empty list:

willThrow :: ServerPart Response willThrow = ok $ head []

This will of course throw an exception. Happstack “helpfully” catches it and produces this output:

bad_throw_1

Why the air quotes? Notice how Happstack prints the exception message? While this might seem somewhat benign with a simple empty list exception (maybe even helpful if you’re troubleshooting), imagine you’re doing something a little less contrived:

maliciousThrow :: ServerPart Response maliciousThrow = do dirs <- liftIO $ getDirectoryContents "/bar" ok $ toResponse $ show $ dirs

Once again Happstack airs out your dirty laundry.

bad_throw_2

In this case, it prints the fact that /bar doesn’t exist for the whole world to see. Great

I spent some time searching around for the proper way to deal with exceptions in Happstack. There doesn’t seem to be much other than “handle them”. Personally, I feel that if an unhandled exception is thrown, Happstack should treat it as mzero.

This can be accomplished pretty simply:

noThrow :: ServerPart Response noThrow = do dirs <- liftIO $ tryGDC "/bar" case (dirs) of Right d -> ok $ toResponse $ show $ d Left _ -> mzero where tryGDC :: String -> IO (Either SomeException [FilePath]) tryGDC a = try $ getDirectoryContents a

This function is similar to the previous maliciousThrow, except for the tryGDC function. This function uses the try function found within Control.Exception. Try attempts to perform some IO action, and returns Either an exception or a result, wrapped within an IO.

It is necessary to give tryGDC a function signature. Since functions can throw multiple exception types, the type checker cannot infer which is correct. In this case I’ve used the top-level exception class SomeException.

After trying, I check the result. On Right I return a ServerPart Response, on Left, I return mzero. Now when I attempt to access the page using this new version of maliciousThrow, I get this:

no_throw

As it should be. It’s nobody’s business what went wrong.

Best Practices

It should be noted that the function noThrow is equivalent in quality to the following snippet of Java:

public static ThingDoer newThingDoer () { try { return ThingDoerFactory.constructThingDoer(); } catch (Exception ex) { return null; } }

If you wrote that in a real application, you would be a Bad Person. Similarly, noThrow discards all info about what went wrong. You really should do something with it. Don’t show it to the user, but log it somewhere.

Update: I’ve posted a follow-up to this article, which can be found here!

Maybe I Should Be In The Maybe Monad

If you’ve spent any time with Haskell, then you’ve surely encountered Maybe. Maybe is Haskell’s version of testing your pointer for NULL, only its better because it’s impossible to accidentally dereference a Nothing.

You’ve also probably thought it was just so annoying. You test your Maybe a to ensure it’s not Nothing, but you still have to go about getting the value out of the Maybe so you can actually do something with it.

The Problem

Let’s forgo the usual contrived examples and look at an actual problem I faced. While working on the Server Console, I was faced with dealing with a query string. The end of a query string contains key/value pairs. Happstack conveniently decodes these into this type:

[(String, Input)]

I needed to write a function to lookup a key within this pair, and return it’s value. As we all know, there’s no way to guarantee that a given key is in the list, so the function must be able to handle this. There are a few ways we could go about this, but this seems to me to be an ideal place to use a Maybe. Suppose we write our lookup function like so:

lookup :: Request -> String -> Maybe String

This is logically sound, but now we have an annoying Maybe to work with. Suppose we’re working in a ServerPart Response. We might write a response function like so:

handler :: ServerPart Response handler = do req <- askRq paths <- return $ rqPaths req page <- return $ lookup req "page_number" case page of Nothing -> mzero (Just a) -> do items <- return $ lookup req "items_per_page" case items of Nothing -> mzero (just b) -> h' paths a b

Yucky! After each call to lookup, we check to see if the call succeeded. This gives us a giant tree that’s surely pushing off the right side of my blog page. There must be a better way.

Doing It Wrong

Shockingly, this is not the best way to do this. It turns out that writing our functions in the Maybe monad is the answer. Take the following function:

hTrpl :: Request -> Maybe ([String], String, String) hTrpl r = do paths <- return $ rqPaths r page <- lookup r "page_number" items <- lookup r "items_per_page" return (paths, page, items)

… now we can re-write handler like so:

handler :: ServerPart Response handler = do req <- askRq triple <- return $ hTrpl req case triple of Nothing -> mzero (Just (a, b, c)) -> h' a b c

Much better, right? But why don’t we have to test the return values of lookup? The answer to that question lies in the implementation of Maybe‘s >>= operator:

instance Monad Maybe where (Just x) >>= k = k x Nothing >>= _ = Nothing

Recall that do notation is just syntactic sugar around >>= and a whole bunch of lambdas. With that in mind, you can see that we are actually binding functions together. Per Maybe‘s bind implementation, if you bind Just a to a function, it calls the function on a. If you bind Nothing to a function, it ignores the function, and just returns Nothing.

What this means for us is that so long as we’re inside the Maybe monad, we can pretend all functions return successful values. Maybe allows us to defer testing for failure! The first time a Nothing is returned, functions stop getting called, so we don’t even have to worry about performance losses from not immediately returning from the function! So long as we’re inside of Maybe, there will be Peace On Earth. We code our successful code branch, and then when all is said and done and the dust has settled, we can see if it all worked out.

Next time you find yourself testing a Maybe more than once in a function, ask yourself: should I be in the Maybe monad right now?

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.

%d bloggers like this: