packages feed

hack-2009.4.22: readme.md

## Hack: a sexy Haskell Webserver Interface

Hack is a brain-dead port of the brilliant Ruby [Rack](http://rack.rubyforge.org/) webserver interface.

### What does a Hack app look like

    module Main where

    import Hack
    import Hack.Handler.Kibro

    hello :: Application
    hello = \env -> return $ Response 
        { status  = 200
        , headers = [ ("Content-Type", "text/plain") ]
        , body    = "Hello World"
        }

    main = run hello

### 1 minute tutorial

#### Install Hack

    cabal install hack

#### Install Kibro (the only handler at the moment)

    cabal install kibro

#### Install lighttpd 1.4.19 (used by kibro)

    wget http://www.lighttpd.net/download/lighttpd-1.4.19.tar.gz
    tar zxfv lighttpd-1.4.19.tar.gz
    cd lighttpd-1.4.19
    ./configure --prefix=$HOME
    make
    make install

#### Create a new Kibro project

    kibro new hello-world

#### Test if Kibro works

    cd hello-world
    kibro start

#### Create our hack app

put the following code in `src/Main.hs`

    module Main where

    import Hack
    import Hack.Handler.Kibro

    hello :: Application
    hello = \env -> return $ Response 
        { status  = 200
        , headers = [ ("Content-Type", "text/plain") ]
        , body    = "Hello World"
        }

    main = run hello


restart kibro

    kibro restart

### demo usage of middle-ware

    module Main where

    import Hack
    import Hack.Utils
    import Hack.SimpleRoute
    import Hack.Handler.Kibro

    import Data.Default
    import MPS
    import Prelude hiding ((.))
    
    hello :: Application
    hello = \env -> def {body = env.show} .return

    app :: Application
    app = route [("/hello", hello), ("", hello)] empty_app

    main = run app

### make a middle-ware

inside Hack.hs:

    type MiddleWare = Application -> Application

since Haskell has curry, middle-ware api can be of type

    Params -> Application -> Application

just pass an applied middle-ware into a chain.

finally the source code of SimpleRoute.hs:

    {-# LANGUAGE NoMonomorphismRestriction#-}
    {-# LANGUAGE QuasiQuotes #-}

    module Hack.SimpleRoute where

    import Hack
    import Hack.Utils
    import List (find)
    import Prelude hiding ((.), (^), (>))
    import MPS
    
    type RoutePath = (String, Application)

    route :: [RoutePath] -> Application -> Application
    route h _ = \env ->
      let path = env.path_info
          script = env.script_name
          mod_env location = env 
            { script_name = script ++ location
            , path_info = path.drop (location.length)
            }
      in
      case h.find (fst > flip starts_with path) of
        Nothing -> not_found [$here|Not Found: #{path}|]
        Just (location, app) -> app (mod_env location)