So if `pipes-http` is built on top of `http-client` the glue code would
be incredibly small, so it would probably not be worth abstracting over
this.
To summarize this for people who are not familiar with the `http-client`
API, the relevant parts are the `RequestBodyStreamChunked` constructor
that you use to build `Request`s:
https://hackage.haskell.org/package/http-client-0.2.1.1/docs/Network-HTTP-Client.html#v:RequestBodyStream
... and the `brRead` accessor for the `BodyReader` you get from a
`Response`:
https://hackage.haskell.org/package/http-client-0.2.1.1/docs/Network-HTTP-Client.html#v:brRead
The `RequestBodyStreamChunked` constructor expects an argument of type:
(IO ByteString -> IO ()) -> IO ()
It's a little bit confusing if you're not familiar with continuations,
but it basically means that you need to provide the `Request` with an
`IO ByteString` action that outputs request chunks and returns an empty
bytestring to denote stream termination.
The equivalent `pipes` abstraction is a `Producer ByteString IO ()`, and
here's the code to convert a `Producer` to the necessary format that
`http-client` expects:
import Data.ByteString (ByteString, empty)
import Data.IORef (newIORef, readIORef, writeIORef)
import Pipes
convert :: Producer ByteString IO () -> (IO ByteString -> IO ()) ->
IO ()
convert p0 k = do
ioref <- newIORef p0
let readAction :: IO ByteString
readAction = do
p <- readIORef ioref
x <- next p
case x of
Left () -> do
writeIORef ioref (return ())
return empty
Right (bs, p') -> do
writeIORef ioref p'
return bs
k readAction
Note that this is very similar to how `draw` from `pipes-parse` works,
except storing the `Producer` in an `IORef` instead of a `StateT` monad.
Interfacing with the `BodyReader` is also easy since it just returns an
`IO ByteString` action, which we can convert back to a `Producer`:
import Control.Monad (unless)
import Data.ByteString (ByteString)
import qualified Data.ByteString as B
import Pipes
convert :: IO ByteString -> Producer ByteString IO ()
convert io = go
where
go = do
bs <- lift io
unless (B.null bs) $ do
yield bs
go
So that's pretty much the entirety of the conversion. I'd probably
dress it up a little bit and create the `pipes` analogs of
`http-conduit`'s `http`, `requestBodySource`, and
`requestBodySourceChunked` functions:
http://hackage.haskell.org/package/http-conduit-2.0.0.4/docs/Network-HTTP-Conduit.html#v:http
http://hackage.haskell.org/package/http-conduit-2.0.0.4/docs/Network-HTTP-Conduit.html#v:requestBodySource
http://hackage.haskell.org/package/http-conduit-2.0.0.4/docs/Network-HTTP-Conduit.html#v:requestBodySourceChunked
... but that's about it.
The only reason I raised this topic is not because the wrapper is
difficult (it's not), but just to see if anybody had objections to
`http-client` (i.e. API, technical issues, security, or performance).
Judging from the responses it seems that most people would be happy with
building this on top of `http-client` and `http-client-tls` so I will
write up a quick skeleton.
On 01/28/2014 05:41 PM, Pierre R wrote:
Is it possible to provide a sane "pipes-http-client API" that would
work whatever the underline implementation is ?
Then make one that works choosing the easiest path possible. At that
point anyone can try to beat the underline implementation using other
facilities (whether it is based on `http-streams`, `pipes`, `conduit`
or a mix of them).
Is the Haskell module system to weak for this ?
--
You received this message because you are subscribed to the Google
Groups "Haskell Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send
an email to [email protected].
To post to this group, send email to [email protected].
--
You received this message because you are subscribed to the Google Groups "Haskell
Pipes" group.
To unsubscribe from this group and stop receiving emails from it, send an email
to [email protected].
To post to this group, send email to [email protected].