I attempted to recreate it in #haskell, but we don't really have a library on the same level of abstraction. wai is too abstract and network is not abstract enough.
Actually, if you combine network with network-run then it is the right level of abstraction:
{- cabal:
build-depends: base, network, network-run, monad-loops
-}
import Network.Run.TCP
import Network.Socket
import System.IO
import Control.Monad.Loops
main = runTCPServer (Just "127.0.0.1") "9999" talk where
talk s = do
h <- socketToHandle s ReadWriteMode
l <- hGetLine h
case words l of
["GET", resource, "HTTP/1.1"] -> do
whileM_ (("\r" /=) <$> hGetLine h) (pure ())
let path = concat
[ "htdocs/"
, dropWhile (== '/') resource
, if last resource == '/' then "index.html" else ""
]
hPutStr h "HTTP/1.1 200 OK\r\n\r\n"
hPutStr h =<< readFile path
hClose h
_ -> error "todo"