Search code examples
haskellmonadsconduithaskell-wai

How to consume a conduit with WAI (raw request body)


I'm using scotty, which is a sinatra-like wrapper around WAI. I want to get the raw request body as a byte string so I can parse it as json. The following is close. This is similar to other questions about consuming a body using WAI, but is different because I want the body as a bytestring, and because I'm in a different monad, ActionM

import Network.Wai (requestBody)
import Web.Scotty (ActionM, request, text)

bodyExample :: ActionM ()
bodyExample = do
    r <- request
    bss <- requestBody r -- this needs a lift or something
    text "ok"
    ...

It obviously won't work, I think I need some kind of lift or something, but I don't know what to use. liftIO isn't right, and lift gives me weird errors.

http://hackage.haskell.org/packages/archive/scotty/0.0.1/doc/html/Web-Scotty.html

http://hackage.haskell.org/packages/archive/wai/latest/doc/html/Network-Wai.html


Solution

  • requestBody isn't a monadic value. It is simply a function that returns a Conduit Source IO ByteString.

    To consume the source, use Data.Conduit.List.consume (or Data.Conduit.Lazy.lazyConsume). You will get a list of ByteStrings as the result. To then exit the ResourceT monad transformer, use runResourceT. The resulting code:

    bss <- liftIO . runResourceT . lazyConsume . requestBody $ r
    bss :: [ByteString]