pipes-http 1.0.0 → 1.0.1
raw patch · 4 files changed
+183/−183 lines, 4 filesdep ~http-clientsetup-changed
Dependency ranges changed: http-client
Files
- LICENSE +24/−24
- Setup.hs +2/−2
- pipes-http.cabal +27/−27
- src/Pipes/HTTP.hs +130/−130
LICENSE view
@@ -1,24 +1,24 @@-Copyright (c) 2014 Gabriel Gonzalez-All rights reserved.--Redistribution and use in source and binary forms, with or without modification,-are permitted provided that the following conditions are met:- * Redistributions of source code must retain the above copyright notice,- this list of conditions and the following disclaimer.- * Redistributions in binary form must reproduce the above copyright notice,- this list of conditions and the following disclaimer in the documentation- and/or other materials provided with the distribution.- * Neither the name of Gabriel Gonzalez nor the names of other contributors- may be used to endorse or promote products derived from this software- without specific prior written permission.--THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND-ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED-WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE-DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR-ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES-(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;-LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON-ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT-(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS-SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.+Copyright (c) 2014 Gabriel Gonzalez +All rights reserved. + +Redistribution and use in source and binary forms, with or without modification, +are permitted provided that the following conditions are met: + * Redistributions of source code must retain the above copyright notice, + this list of conditions and the following disclaimer. + * Redistributions in binary form must reproduce the above copyright notice, + this list of conditions and the following disclaimer in the documentation + and/or other materials provided with the distribution. + * Neither the name of Gabriel Gonzalez nor the names of other contributors + may be used to endorse or promote products derived from this software + without specific prior written permission. + +THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" AND +ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED +WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE +DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR +ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES +(INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; +LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON +ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT +(INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF THIS +SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
Setup.hs view
@@ -1,2 +1,2 @@-import Distribution.Simple-main = defaultMain+import Distribution.Simple +main = defaultMain
pipes-http.cabal view
@@ -1,27 +1,27 @@-Name: pipes-http-Version: 1.0.0-Cabal-Version: >=1.8.0.2-Build-Type: Simple-License: BSD3-License-File: LICENSE-Copyright: 2014 Gabriel Gonzalez-Author: Gabriel Gonzalez-Maintainer: Gabriel439@gmail.com-Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-HTTP-Client-Library/issues-Synopsis: HTTP client with pipes interface-Description: @pipes-http@ is a @pipes@ wrapper around the @http-client@ library-Category: Pipes, Web-Source-Repository head- Type: git- Location: https://github.com/Gabriel439/Haskell-Pipes-HTTP-Library--Library- HS-Source-Dirs: src- Build-Depends:- base >= 4 && < 5 ,- bytestring >= 0.9.2.1 && < 0.11,- pipes >= 4.0 && < 4.2 ,- http-client >= 0.2 && < 0.3 ,- http-client-tls < 0.3- Exposed-Modules: Pipes.HTTP- GHC-Options: -O2 -Wall+Name: pipes-http +Version: 1.0.1 +Cabal-Version: >=1.8.0.2 +Build-Type: Simple +License: BSD3 +License-File: LICENSE +Copyright: 2014 Gabriel Gonzalez +Author: Gabriel Gonzalez +Maintainer: Gabriel439@gmail.com +Bug-Reports: https://github.com/Gabriel439/Haskell-Pipes-HTTP-Library/issues +Synopsis: HTTP client with pipes interface +Description: @pipes-http@ is a @pipes@ wrapper around the @http-client@ library +Category: Pipes, Web +Source-Repository head + Type: git + Location: https://github.com/Gabriel439/Haskell-Pipes-HTTP-Library + +Library + HS-Source-Dirs: src + Build-Depends: + base >= 4 && < 5 , + bytestring >= 0.9.2.1 && < 0.11, + pipes >= 4.0 && < 4.2 , + http-client >= 0.2 && < 0.4 , + http-client-tls < 0.3 + Exposed-Modules: Pipes.HTTP + GHC-Options: -O2 -Wall
src/Pipes/HTTP.hs view
@@ -1,130 +1,130 @@--- | Here is an example GET request that streams the response body to standard--- output:------ > import Pipes--- > import Pipes.HTTP--- > import qualified Pipes.ByteString as PB -- from `pipes-bytestring`--- >--- > main = do--- > req <- parseUrl "https://www.example.com"--- > withManager tlsManagerSettings $ \m ->--- > withHTTP req m $ \resp ->--- > runEffect $ responseBody resp >-> PB.stdout------ Here is an example POST request that also streams the request body from--- standard input:------ > {-# LANGUAGE OverloadedStrings #-}--- >--- > import Pipes--- > import Pipes.HTTP--- > import qualified Pipes.ByteString as PB--- >--- > main = do--- > req <- parseUrl "https://www.example.com"--- > let req' = req--- > { method = "POST"--- > , requestBody = stream PB.stdin--- > }--- > withManager tlsManagerSettings $ \m ->--- > withHTTP req' m $ \resp ->--- > runEffect $ responseBody resp >-> PB.stdout------ For non-streaming request bodies, study the 'RequestBody' type, which also--- accepts strict \/ lazy bytestrings or builders.---module Pipes.HTTP (- -- * http-client- -- $httpclient- module Network.HTTP.Client- , module Network.HTTP.Client.TLS-- -- * Pipes Interface- , withHTTP- , streamN- , stream-- ) where--import Control.Monad (unless)-import Data.ByteString (ByteString)-import qualified Data.ByteString as B-import Data.Int (Int64)-import Data.IORef (newIORef, readIORef, writeIORef)-import Network.HTTP.Client-import Network.HTTP.Client.TLS-import Pipes--{- $httpclient- This module is a thin @pipes@ wrapper around the @http-client@ and- @http-client-tls@ libraries.-- Read the documentation in the "Network.HTTP.Client" module of the- @http-client@ library to learn about how to:-- * manage connections using connection pooling,-- * use more advanced request\/response features,-- * handle exceptions, and:-- * manage cookies.-- @http-client-tls@ provides support for TLS connections (i.e. HTTPS).--}---- | Send an HTTP 'Request' and wait for an HTTP 'Response'-withHTTP- :: Request- -- ^- -> Manager- -- ^- -> (Response (Producer ByteString IO ()) -> IO a)- -- ^ Handler for response- -> IO a-withHTTP r m k = withResponse r m k'- where- k' resp = do- let p = (from . brRead . responseBody) resp- k (resp { responseBody = p})-{-# INLINABLE withHTTP #-}---- | Create a 'RequestBody' from a content length and 'Producer'-streamN :: Int64 -> Producer ByteString IO () -> RequestBody-streamN n p = RequestBodyStream n (to p)-{-# INLINABLE streamN #-}--{-| Create a 'RequestBody' from a 'Producer'-- 'stream' is more flexible than 'streamN', but requires the server to support- chunked transfer encoding.--}-stream :: Producer ByteString IO () -> RequestBody-stream p = RequestBodyStreamChunked (to p)-{-# INLINABLE stream #-}--to :: Producer ByteString IO () -> (IO ByteString -> IO ()) -> IO ()-to 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 B.empty- Right (bs, p') -> do- writeIORef ioref p'- return bs- k readAction --from :: IO ByteString -> Producer ByteString IO ()-from io = go- where- go = do- bs <- lift io- unless (B.null bs) $ do- yield bs- go +-- | Here is an example GET request that streams the response body to standard +-- output: +-- +-- > import Pipes +-- > import Pipes.HTTP +-- > import qualified Pipes.ByteString as PB -- from `pipes-bytestring` +-- > +-- > main = do +-- > req <- parseUrl "https://www.example.com" +-- > withManager tlsManagerSettings $ \m -> +-- > withHTTP req m $ \resp -> +-- > runEffect $ responseBody resp >-> PB.stdout +-- +-- Here is an example POST request that also streams the request body from +-- standard input: +-- +-- > {-# LANGUAGE OverloadedStrings #-} +-- > +-- > import Pipes +-- > import Pipes.HTTP +-- > import qualified Pipes.ByteString as PB +-- > +-- > main = do +-- > req <- parseUrl "https://www.example.com" +-- > let req' = req +-- > { method = "POST" +-- > , requestBody = stream PB.stdin +-- > } +-- > withManager tlsManagerSettings $ \m -> +-- > withHTTP req' m $ \resp -> +-- > runEffect $ responseBody resp >-> PB.stdout +-- +-- For non-streaming request bodies, study the 'RequestBody' type, which also +-- accepts strict \/ lazy bytestrings or builders. + + +module Pipes.HTTP ( + -- * http-client + -- $httpclient + module Network.HTTP.Client + , module Network.HTTP.Client.TLS + + -- * Pipes Interface + , withHTTP + , streamN + , stream + + ) where + +import Control.Monad (unless) +import Data.ByteString (ByteString) +import qualified Data.ByteString as B +import Data.Int (Int64) +import Data.IORef (newIORef, readIORef, writeIORef) +import Network.HTTP.Client +import Network.HTTP.Client.TLS +import Pipes + +{- $httpclient + This module is a thin @pipes@ wrapper around the @http-client@ and + @http-client-tls@ libraries. + + Read the documentation in the "Network.HTTP.Client" module of the + @http-client@ library to learn about how to: + + * manage connections using connection pooling, + + * use more advanced request\/response features, + + * handle exceptions, and: + + * manage cookies. + + @http-client-tls@ provides support for TLS connections (i.e. HTTPS). +-} + +-- | Send an HTTP 'Request' and wait for an HTTP 'Response' +withHTTP + :: Request + -- ^ + -> Manager + -- ^ + -> (Response (Producer ByteString IO ()) -> IO a) + -- ^ Handler for response + -> IO a +withHTTP r m k = withResponse r m k' + where + k' resp = do + let p = (from . brRead . responseBody) resp + k (resp { responseBody = p}) +{-# INLINABLE withHTTP #-} + +-- | Create a 'RequestBody' from a content length and 'Producer' +streamN :: Int64 -> Producer ByteString IO () -> RequestBody +streamN n p = RequestBodyStream n (to p) +{-# INLINABLE streamN #-} + +{-| Create a 'RequestBody' from a 'Producer' + + 'stream' is more flexible than 'streamN', but requires the server to support + chunked transfer encoding. +-} +stream :: Producer ByteString IO () -> RequestBody +stream p = RequestBodyStreamChunked (to p) +{-# INLINABLE stream #-} + +to :: Producer ByteString IO () -> (IO ByteString -> IO ()) -> IO () +to 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 B.empty + Right (bs, p') -> do + writeIORef ioref p' + return bs + k readAction + +from :: IO ByteString -> Producer ByteString IO () +from io = go + where + go = do + bs <- lift io + unless (B.null bs) $ do + yield bs + go