How to connect a conduit to WAI's StreamingBody (for a Scotty app)

187 views
Skip to first unread message

Doug Burke

unread,
Oct 12, 2014, 10:13:12 AM10/12/14
to haske...@googlegroups.com

I have the following code, which base 64 encodes the responses from a web server [1]. I can do it with a simple "process it all in one go" approach - which is shown by proxy1 below - but I'd like to try it using a streaming approach using conduit (since it's already installed in my sandbox), but can't see how to connect a Conduit to Scotty's stream routine, which accepts WAI's StreamingBody.

Thanks for any pointers,
Doug

[1] as to why I'm doing this, it involves a yak and a sharp blade, but even if the reason is rather silly, I'd still like to know how to do it ;-)

--
-- Simplified code below; hopefully without too many typos
--

import Data.ByteString.Base64.Lazy (encode)
import Data.Default (def)

import Network.HTTP.Client (defaultManagerSettings)
import Network.HTTP.Conduit (Manager, newManager
                            , parseUrl, httpLbs, http
                            , responseBody)

import Web.Scotty

main :: IO ()
main = do
  mgr <- newManager defaultManagerSettings
  scottyOpts def $ webApp mgr

webApp :: Manager -> ScottyM ()
webapp mgr = do
  get "/proxy/:imgnum" $ do
           imgnum <- param "imgnum"
           proxy1 mgr imgnum

-- This works, and given the image sizes I am dealing with, is not a
-- terrible solution, but can it be improved (which is what proxy2 is
-- meant to be)?
--
proxy1 :: Manager -> Int -> ActionM ()
proxy1 mgr i = do
  let url = "http://example.com/img" ++ show i ++ ".png"
  req <- liftIO $ parseUrl url
  rsp <- liftIO $ httpLbs req mgr
  setHeader "Content-Type" "text/plain; charset=utf-8"
  raw $ encode $ responseBody rsp

-- I'd like to change from httpLbs to http and deal with it using
-- encodeBase64 from conduit-combinator, but how do I turn it
-- into the Builder -> IO ()/IO () pair needed to form a StreamingBody?
--
proxy2 :: Manager -> Int -> ActionM ()
proxy2 mgr i = do
  let url = "http://example.com/img" ++ show i
  req <- liftIO $ parseUrl url
  rsp <- liftIO $ http req mgr
  setHeader "Content-Type" "text/plain; charset=utf-8"
  --
  -- I think want to pass responseBody rsp to
  -- Data.Conduit.Combinators.encodeBase64
  -- and then to Scotty's
  -- steam :: StreamingBody -> ActionM ()
  -- but I can't see how to plumb it all
  -- together
  stream $ undefined

Michael Snoyman

unread,
Oct 13, 2014, 2:17:17 AM10/13/14
to Doug Burke, haske...@googlegroups.com
I don't have an exact answer to your question, but perhaps wai-conduit[1] would help?

[1] http://hackage.haskell.org/package/wai-conduit-3.0.0/docs/Network-Wai-Conduit.html

--
You received this message because you are subscribed to the Google Groups "haskell-wai" group.
To unsubscribe from this group and stop receiving emails from it, send an email to haskell-wai...@googlegroups.com.
To post to this group, send email to haske...@googlegroups.com.
To view this discussion on the web visit https://groups.google.com/d/msgid/haskell-wai/c6ae3a8c-226e-4bb2-8800-cf0f9ce876e6%40googlegroups.com.
For more options, visit https://groups.google.com/d/optout.

Doug Burke

unread,
Nov 2, 2014, 12:23:13 PM11/2/14
to Michael Snoyman, haske...@googlegroups.com

Michael,

Thanks for the response (and apologies for the long delay in replying). Unfortunately I haven't had time to work on this problem yet.


Doug

Ashesh Ambasta

unread,
Nov 26, 2018, 12:59:03 PM11/26/18
to haskell-wai
Hello! 

I understand this is an old thread but I stumbled over this as well. Have you managed to solve this?
Reply all
Reply to author
Forward
0 new messages