packages feed

req-conduit 0.2.1 → 1.0.0

raw patch · 6 files changed

+80/−70 lines, 6 filesdep ~basedep ~bytestringdep ~conduit

Dependency ranges changed: base, bytestring, conduit, conduit-extra, http-client, req, resourcet, temporary

Files

CHANGELOG.md view
@@ -1,3 +1,9 @@+## Req Conduit 1.0.0++* This version is to be used with Req 1.0.0 and later.++* Dropped support for GHC 7.8.+ ## Req Conduit 0.2.1  * Fixed weigh benchmark.@@ -6,7 +12,7 @@  ## Req Conduit 0.2.0 -* This version is to be used with Req 0.3.0.+* This version is to be used with Req 0.3.0 and later.  * Removed `req'` as it's now in Req itself. 
Network/HTTP/Req/Conduit.hs view
@@ -11,11 +11,12 @@ -- Conduit helpers for streaming big request bodies. -- -- The package re-uses some pieces of code from the @http-conduit@ package,--- but not to the extent that depending on that package is reasonable.+-- but not to the extent that depending on that package becomes reasonable. -{-# LANGUAGE CPP             #-}-{-# LANGUAGE RankNTypes      #-}-{-# LANGUAGE TypeFamilies    #-}+{-# LANGUAGE CPP               #-}+{-# LANGUAGE OverloadedStrings #-}+{-# LANGUAGE RankNTypes        #-}+{-# LANGUAGE TypeFamilies      #-}  #if __GLASGOW_HASKELL__ <  710 {-# LANGUAGE ConstraintKinds #-}@@ -26,12 +27,11 @@     ReqBodySource (..)     -- * Streaming response bodies     -- $streaming-response-  , httpSource )+  , responseBodySource ) where  import Control.Monad import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Trans.Resource (MonadResource (..)) import Data.ByteString (ByteString) import Data.Conduit (Source, ($$+), ($$++), await, yield) import Data.IORef@@ -60,24 +60,33 @@  -- $streaming-response ----- Streaming response is a bit tricky as acquiring and releasing a resource--- (initiating a connection and then closing it in our case) in the context--- of @conduit@ streaming requires working with the--- 'Control.Monad.Trans.Resource.ResourceT' monad transformer. This does not--- play well with the framework @req@ builds.+-- The easiest way to stream response of an HTTP request is to use the+-- 'reqBr' function in conjunction with 'responseBodySource': ----- Essentially there are only two ways to make it work:+-- > {-# LANGUAGE OverloadedStrings #-}+-- >+-- > module Main (main) where+-- >+-- > import Data.Conduit ((.|), runConduitRes)+-- > import Data.Default.Class+-- > import Network.HTTP.Req+-- > import Network.HTTP.Req.Conduit+-- > import qualified Data.Conduit.Binary as CB+-- >+-- > main :: IO ()+-- > main = runReq def $ do+-- >   let size = 100000 :: Int+-- >   reqBr GET (https "httpbin.org" /: "bytes" /~ size) NoReqBody mempty $ \r ->+-- >     runConduitRes $+-- >       responseBodySource r .| CB.sinkFile "my-file.bin" -----     * Require that every 'MonadHttp' must be an instance of---       'MonadResource'. This obviously makes the @req@ package harder to---       work with and less user-friendly. Not to mention that most of the---       time the instance won't be necessary.---     * Use the 'withReqManager' in combination with 'ReturnRequest'---       response interpretation to get both 'L.Manager' and 'L.Request' and---       then delegate the work to a custom callback.+-- This solution benefits from the fact that Req still handles all the+-- details like handling of exceptions and retrying for us. However this+-- approach is only viable when the entire pipeline can be run in 'IO' monad+-- (in the function that is the last argument of 'reqBr'). ----- We go with the second option. Here is an example of how to stream 100000--- bytes and save them to a file:+-- If you need to use a more complex monad, you'll need to deal with the+-- lower-level function 'req'': -- -- > {-# LANGUAGE FlexibleInstances #-} -- > {-# LANGUAGE OverloadedStrings #-}@@ -87,10 +96,11 @@ -- > import Control.Exception (throwIO) -- > import Control.Monad.IO.Class (MonadIO (..)) -- > import Control.Monad.Trans.Resource (ResourceT)--- > import Data.Conduit ((=$=), runConduitRes, ConduitM)+-- > import Data.Conduit -- > import Network.HTTP.Req -- > import Network.HTTP.Req.Conduit -- > import qualified Data.Conduit.Binary as CB+-- > import qualified Network.HTTP.Client as L -- > -- > instance MonadHttp (ConduitM i o (ResourceT IO)) where -- >   handleHttpException = liftIO . throwIO@@ -98,19 +108,23 @@ -- > main :: IO () -- > main = runConduitRes $ do -- >   let size = 100000 :: Int--- >   req' GET (https "httpbin.org" /: "bytes" /~ size) NoReqBody mempty httpSource--- >     =$= CB.sinkFile "my-favorite-file.bin"+-- >   req' GET (https "httpbin.org" /: "bytes" /~ size) NoReqBody mempty+-- >     (\request manager ->+-- >       bracketP (L.responseOpen request manager) L.responseClose+-- >         responseBodySource)+-- >     .| CB.sinkFile "my-file.bin"+--+-- 'req'' does not open\/close connections, handle exceptions, and does not+-- perform retrying though, so you're on your own. --- | Perform an HTTP request and get the response as a 'C.Producer'.+-- | Turn @'L.Response' 'L.BodyReader'@ into a 'C.Producer'.+--+-- @since 1.0.0 -httpSource-  :: MonadResource m-  => L.Request         -- ^ Pre-formed 'L.Request'-  -> L.Manager         -- ^ Manger to use+responseBodySource :: MonadIO m+  => L.Response L.BodyReader -- ^ Response with body reader   -> C.Producer m ByteString -- ^ Response body as a 'C.Producer'-httpSource request manager =-  C.bracketP (L.responseOpen request manager) L.responseClose-    (bodyReaderSource . L.responseBody)+responseBodySource = bodyReaderSource . L.responseBody  ---------------------------------------------------------------------------- -- Helpers
README.md view
@@ -7,9 +7,9 @@ [![Build Status](https://travis-ci.org/mrkkrp/req-conduit.svg?branch=master)](https://travis-ci.org/mrkkrp/req-conduit) [![Coverage Status](https://coveralls.io/repos/mrkkrp/req-conduit/badge.svg?branch=master&service=github)](https://coveralls.io/github/mrkkrp/req-conduit?branch=master) -This library extends functionality of-the [`req`](https://hackage.haskell.org/package/req) package-with [`conduit`](https://hackage.haskell.org/package/conduit) helpers for+This library extends functionality of the+[`req`](https://hackage.haskell.org/package/req) package with+[`conduit`](https://hackage.haskell.org/package/conduit) helpers for streaming big request bodies in constant space.  ## Contribution
httpbin-tests/Network/HTTP/Req/ConduitSpec.hs view
@@ -10,9 +10,7 @@  import Control.Exception (throwIO) import Control.Monad-import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Trans.Resource (ResourceT)-import Data.Conduit ((=$=), runConduitRes, ConduitM)+import Data.Conduit ((.|), runConduitRes) import Data.Int (Int64) import Network.HTTP.Req import Network.HTTP.Req.Conduit@@ -42,21 +40,18 @@     it "works" $ do       let tempi :: (Handle -> IO ()) -> IO ()           tempi f = withSystemTempFile "req-conduit" (const f)-      tempi $ \h ->-        runConduitRes $ do-          let size :: Int-              size = 10 * 1024 * 1024-          req' GET (httpbin /: "stream-bytes" /~ size) NoReqBody-            mempty httpSource =$= CB.sinkHandle h+      tempi $ \h -> do+        let size :: Int+            size = 10 * 1024 * 1024+        reqBr GET (httpbin /: "stream-bytes" /~ size) NoReqBody mempty $ \r ->+          runConduitRes $+             responseBodySource r .| CB.sinkHandle h  ---------------------------------------------------------------------------- -- Instances  instance MonadHttp IO where   handleHttpException = throwIO--instance MonadHttp (ConduitM i o (ResourceT IO)) where-  handleHttpException = liftIO . throwIO  ---------------------------------------------------------------------------- -- Helpers
req-conduit.cabal view
@@ -1,7 +1,7 @@ name:                 req-conduit-version:              0.2.1+version:              1.0.0 cabal-version:        >= 1.18-tested-with:          GHC==7.8.4, GHC==7.10.3, GHC==8.0.2, GHC==8.2.1+tested-with:          GHC==7.10.3, GHC==8.0.2, GHC==8.2.2 license:              BSD3 license-file:         LICENSE.md author:               Mark Karpov <markkarpov92@gmail.com>, Michael Snoyman <michael@snoyman.com>@@ -25,11 +25,11 @@   default:            False  library-  build-depends:      base             >= 4.7   && < 5.0+  build-depends:      base             >= 4.8   && < 5.0                     , bytestring       >= 0.2   && < 0.11-                    , conduit          >= 0.5.5 && < 1.3+                    , conduit          >= 1.2.8 && < 1.3                     , http-client      >= 0.5   && < 0.6-                    , req              >= 0.3   && < 0.4+                    , req              >= 1.0   && < 2.0                     , resourcet        >= 1.1   && < 1.2                     , transformers     >= 0.4   && < 0.6   exposed-modules:    Network.HTTP.Req.Conduit@@ -44,12 +44,12 @@   other-modules:      Network.HTTP.Req.ConduitSpec   hs-source-dirs:     httpbin-tests   type:               exitcode-stdio-1.0-  build-depends:      base             >= 4.7   && < 5.0+  build-depends:      base             >= 4.8   && < 5.0                     , bytestring       >= 0.2   && < 0.11-                    , conduit          >= 0.5.5 && < 1.3-                    , conduit-extra    >= 1.1.10 && < 1.2+                    , conduit          >= 1.2.8 && < 1.3+                    , conduit-extra    >= 1.1.10 && < 1.3                     , hspec            >= 2.0   && < 3.0-                    , req              >= 0.3   && < 0.4+                    , req              >= 1.0   && < 2.0                     , req-conduit                     , resourcet        >= 1.1   && < 1.2                     , temporary        >= 1.1   && < 1.3@@ -64,11 +64,11 @@   main-is:            Main.hs   hs-source-dirs:     weigh-bench   type:               exitcode-stdio-1.0-  build-depends:      base             >= 4.7   && < 5.0+  build-depends:      base             >= 4.8   && < 5.0                     , bytestring       >= 0.2   && < 0.11-                    , conduit          >= 0.5.5 && < 1.3-                    , conduit-extra    >= 1.1.10 && < 1.2-                    , req              >= 0.3   && < 0.4+                    , conduit          >= 1.2.8 && < 1.3+                    , conduit-extra    >= 1.1.10 && < 1.3+                    , req              >= 1.0   && < 2.0                     , req-conduit                     , resourcet        >= 1.1   && < 1.2                     , temporary        >= 1.1   && < 1.3
weigh-bench/Main.hs view
@@ -7,9 +7,7 @@  import Control.Exception (throwIO) import Control.Monad-import Control.Monad.IO.Class (MonadIO (..))-import Control.Monad.Trans.Resource (ResourceT)-import Data.Conduit ((=$=), runConduitRes, ConduitM)+import Data.Conduit ((.|), runConduitRes) import Data.Int (Int64) import Network.HTTP.Req import Network.HTTP.Req.Conduit@@ -41,18 +39,15 @@  bigResponse :: Int -> IO () bigResponse size = withSystemTempFile "req-conduit" $ \_ h ->-  runConduitRes $-    req' GET (httpbin /: "stream-bytes" /~ size) NoReqBody-      mempty httpSource =$= CB.sinkHandle h+  reqBr GET (httpbin /: "stream-bytes" /~ size) NoReqBody mempty $ \r ->+    runConduitRes $+      responseBodySource r .| CB.sinkHandle h  ---------------------------------------------------------------------------- -- Instances  instance MonadHttp IO where   handleHttpException = throwIO--instance MonadHttp (ConduitM i o (ResourceT IO)) where-  handleHttpException = liftIO . throwIO  ---------------------------------------------------------------------------- -- Helpers