profile picture

From HAppS to Happstack

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<br/>
version:             0.0
synopsis:            Personal website
description:         
category:            Web
license:             BSD3
license-file:        LICENSE
author:              G&iacute;sli Kristj&aacute;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.

@code #haskell