Search code examples
haskellyesodhaskell-wai

How do I use wai-handler-devel with a simple wai application


I have the basic "hello world" application setup using wai, and would like to use wai-handler-devel, but am unsure how to go about it and can't find any examples of it in usage on a wai project.

{-# LANGUAGE OverloadedStrings #-}
import Network.Wai
import Network.HTTP.Types
import Network.Wai.Handler.Warp (run)
import Data.ByteString.Lazy.Char8 () -- Just for an orphan instance

app :: Application
app _ = return $ responseLBS
    status200
    [("Content-Type", "text/plain")]
    "Hello, World!"

main :: IO ()
main = do
    putStrLn $ "http://localhost:8080/"
    run 8080 app

What do I need to do to get wai-handler-devel working with a basic wai app?

Note: There is a fix here ( https://gist.github.com/1499226) i f you run into issues with "wai-handler-devel: command not found"


Solution

  • wai-handler-devel's Hackage page says that it should be invoked from the command-line like so:

    $ wai-handler-devel <port> My.App.Module myApp
    

    and that your application's type must look like this:

    myApp :: (Application -> IO ()) -> IO ()
    

    In this case, you should define myApp as follows:

    myApp :: (Application -> IO ()) -> IO ()
    myApp handler = handler app
    

    although you may want to inline app entirely:

    myApp :: (Application -> IO ()) -> IO ()
    myApp handler = handler $ \_ -> return $ responseLBS
        status200
        [("Content-Type", "text/plain")]
        "Hello, World!"
    

    The type is like this so that you can do initialisation on start-up and the like in IO. I suggest reading the SmallApp and FullApp examples from wai-handler-devel's git repository; the latter is especially helpful, as it has debug output showing the flow of the code during a reload, and shows how to integrate a long-running database connection.

    The run script for the FullApp example also shows how to use wai-handler-devel programmatically, including manually specifying Hamlet template dependencies (which the wai-handler-devel command-line tool determines automatically).

    You should then be able to rewrite your main as follows:

    main :: IO ()
    main = do
        putStrLn $ "http://localhost:8080/"
        myApp (run 8080)
    

    Of course, you could just as easily pass the run function from wai-handler-fastcgi, wai-handler-scgi or even wai-handler-webkit.