The Wheb package


Wheb's a framework for building robust, high-concurrency web applications simply and effectively.


Wheb makes it easy to write plugins. Plugins can add routes, middlware, settings and even handle resource cleanup on server shutdown. Named routes allow plugins to dynamically generate their routes at runtime based on settings.

Examples of plugins:

Wheb in action:

 import           Web.Wheb
 import           Data.Text.Lazy (pack)

 main :: IO ()
 main = do
   opts <- genMinOpts $ do
      addGET "home" rootPat $ (text (pack "Hi!"))
      addGET "about" ("about" </> "something") $ html (pack "<html><body><h1>About!</h1></body></html>")
   runWhebServer opts

Bigger example (Stateful.hs):

Wheb makes it easy to share a global context and handle requests statefully. The Wheb monad is both a Reader and a State Monad allowing you to seperate thread-safe resources.

Below is an example of site that naively counts the non-unique hits across all pages. MyApp is our Reader's type and MyHandlerData is our State's type. MyApp is shared across requests while MyHandlerData is thread specific with a starting state given in options. We have a middleware that intercepts the request, safely increments the shared resource TVar and sets our MyHandlerData to the correct count before it reaches our handler. We use a TVar in the Global context because any state changes to the handler state will not affect other requests.

  import           Control.Concurrent.STM
  import           Control.Monad.IO.Class
  import           Data.Monoid
  import           Data.Text.Lazy (Text, pack)
  import           Web.Wheb

  data MyApp = MyApp Text (TVar Int)
  data MyHandlerData = MyHandlerData Int

  counterMw :: MonadIO m => WhebMiddleware MyApp MyHandlerData m
  counterMw = do
    (MyApp _ ctr) <- getApp
    number <- liftIO $ atomically $ do
            num <- readTVar ctr
            writeTVar ctr (succ num)
            return num
    putHandlerState (MyHandlerData number)
    return Nothing

  homePage :: WhebHandler MyApp MyHandlerData
  homePage = do
    (MyApp appName _)   <- getApp
    (MyHandlerData num) <- getHandlerState
    html $ ("<h1>Welcome to" <> appName <>
            "</h1><h2>You are visitor #" <> (spack num) <> "</h2>")

  main :: IO ()
  main = do
    opts <- generateOptions $ do
              startingCounter <- liftIO $ newTVarIO 0
              addWhebMiddleware counterMw
              addGET (pack ".") rootPat $ homePage
              return $ (MyApp "AwesomeApp" startingCounter, MyHandlerData 0)
    runWhebServer opts


Dependenciesbase (==4.7.*), blaze-builder (==0.3.*), bytestring (==0.10.*), case-insensitive (==1.2.*), containers (==0.5.*), cookie (==0.4.*), http-types (==0.8.*), mtl (>=2.1 && <2.3), pwstore-fast (==2.4.*), stm (==2.4.*), text (>=1.0 && <1.2), time (==1.4.*), transformers (==0.4.*), unix (==2.7.*), uuid (==1.3.*), wai (==3.0.*), wai-extra (==3.0.*), wai-websockets (==3.0.*), warp (==3.0.*), web-routes (==0.27.*), websockets (==0.8.*) [details]
AuthorKyle Hanson
Home page
Source repositoryhead: git clone git://
UploadedSun Aug 3 16:37:05 UTC 2014 by hansonkd




Maintainers' corner

For package maintainers and hackage trustees