From HAppS to Happstack
October 13, 2009, in haskell

I have been dreading porting my Blog application from HAppS to Happstack for a long time now. It is however apparent that HAppS is dying and Happstack (a fork of HAppS designed to take things further) was the only way to roll.

… a refreshingly innovative web application server written in Haskell. Leveraging the MACID state system, Happstack offers robust and scalable data access without the headache of managing a traditional RDBMS such as MySQL.

The RELEASE_NOTES file had some guidelines for porting existing applications to Happstack. In my case it turned out to be really easy:

  1. Install Happstack
    • sudo cabal install happstack
  2. Change HAppS to Happstack in all .hs-files
    • find . -type f -name '*.hs' -exec sed -i.bak 's/HAppS/Happstack/g' {} \;
  3. Change unServerPartT to runServerPartT
    • find . -type f -name '*.hs' -exec sed -i.bak 's/unServerPartT/runServerPartT/g' {} \;
  4. Change all instances of [ServerPartT m a] to ServerPartT with msum
  5. Compile my code again
Well this sounds almost too easy. And it is. I alway got the error Unsupported socket - both on my Mac (development machine) and on my Linux box (the production machine). On Google Groups I found someone saying that it’s a problem with how Haskell’s Templating System handles  IPv6. The solution was to change Happstack.Server.HTTP.Socket.acceptLite to:
-- | alternative implementation of accept to work around EAI_AGAIN errors 
acceptLite :: S.Socket -> IO (Handle, S.HostName, S.PortNumber) 
acceptLite sock = do 
  (sock', addr) <- S.accept sock 
  h <- S.socketToHandle sock' ReadWriteMode 
  (N.PortNumber p) <- N.socketPort sock' 

  let peer = case addr of 
               (S.SockAddrInet _ ha)      -showHostAddress ha 
               (S.SockAddrInet6 _ _ ha _) -showHostAddress6 ha 
               _                          -error "Unsupported socket"
  return (h, peer, p) 
Actually I used the time to cabalize my code. Outlining the dependencies means that Cabal takes care of downloading all the necessary packages. To date my cabal file looks like this:
name:                gisliblog

version:             0.0
synopsis:            Personal website
description:         
category:            Web
license:             BSD3
license-file:        LICENSE
author:              Gísli Kristjánsson
maintainer:          gislik hamstur.is
build-depends:       base,feed,nano-md5,hscolour,json,curl,HStringTemplate,happstack
build-type:          Simple
hs-source-dirs:      src
executable:          gisli.hamstur.is
main-is:             src/Main.hs
ghc-options:         -isrc        
Also having everything in a git repository meant that I could port the code in a special branch and merge the branches when the code compiled successfully. The next steps are to port my brothers photo site to Happstack and then look into taking the advantage of the new API which has been simplified in many ways. For example
This:
    uriRest :: Monad m => (String -> ServerPartT m a) -> ServerPartT m a
    uriRest handle = withRequest $ \rq -> unServerPartT (handle (rqURL rq)) rq
Becomes this:
    uriRest :: (ServerMonad m, Monad m) => (String -> m a) -> m a
    uriRest handle = askRq >>= handle . rqURL
That’s it for now.
P.S. On a different note I just placed an order for the Arduino Duemilanove microcontroller board. It should be arriving this week. I’m all excited so the next blog could be about that.

About