{-# LANGUAGE DeriveTraversable #-}
{-# LANGUAGE DeriveDataTypeable #-}
{-# LANGUAGE DeriveGeneric #-}
{-# LANGUAGE CPP #-}
-- |
--
-- = Simpler API
--
-- The API below is rather low-level. The @Network.HTTP.Simple@ module (from
-- the @http-conduit@ package) provides a higher-level API with built-in
-- support for things like JSON request and response bodies. For most users,
-- this will be an easier place to start. You can read the tutorial at:
--
-- https://haskell-lang.org/library/http-client
--
-- = Lower-level API
--
-- This is the main entry point for using http-client. Used by itself, this
-- module provides low-level access for streaming request and response bodies,
-- and only non-secure HTTP connections. Helper packages such as http-conduit
-- provide higher level streaming approaches, while other helper packages like
-- http-client-tls provide secure connections.
--
-- There are three core components to be understood here: requests, responses,
-- and managers. A 'Manager' keeps track of open connections to various hosts,
-- and when requested, will provide either an existing open connection or
-- create a new connection on demand. A 'Manager' also automatically reaps
-- connections which have been unused for a certain period of time. A 'Manager'
-- allows for more efficient HTTP usage by allowing for keep-alive connections.
-- Secure HTTP connections can be allowed by modifying the settings used for
-- creating a manager. The simplest way to create a 'Manager' is with:
--
-- @
-- 'newManager' 'defaultManagerSettings'
-- @
--
-- While generally speaking it is a good idea to share a single 'Manager'
-- throughout your application, there are cases where it makes more sense to
-- create and destroy 'Manager's more frequently. As an example, if you have an
-- application which will make a large number of requests to different hosts,
-- and will never make more than one connection to a single host, then sharing
-- a 'Manager' will result in idle connections being kept open longer than
-- necessary. In such a situation, it makes sense to use 'newManager' before
-- each new request, to avoid running out of file descriptors. (Note that the
-- 'managerIdleConnectionCount' setting mitigates the risk of leaking too many
-- file descriptors.)
--
-- The next core component is a 'Request', which represents a single HTTP
-- request to be sent to a specific server. 'Request's allow for many settings
-- to control exact how they function, but usually the simplest approach for
-- creating a 'Request' is to use 'parseRequest'.
--
-- Finally, a 'Response' is the result of sending a single 'Request' to a
-- server, over a connection which was acquired from a 'Manager'. Note that you
-- must close the response when you're done with it to ensure that the
-- connection is recycled to the 'Manager' to either be used by another
-- request, or to be reaped. Usage of 'withResponse' will ensure that this
-- happens automatically.
--
-- Helper packages may provide replacements for various recommendations listed
-- above. For example, if using http-client-tls, instead of using
-- 'defaultManagerSettings', you would want to use 'tlsManagerSettings'. Be
-- sure to read the relevant helper library documentation for more information.
--
-- A note on exceptions: for the most part, all actions that perform I/O should
-- be assumed to throw an 'HttpException' in the event of some problem, and all
-- pure functions will be total. For example, 'withResponse', 'httpLbs', and
-- 'BodyReader' can all throw exceptions. Functions like 'responseStatus' and
-- 'applyBasicAuth' are guaranteed to be total (or there's a bug in the
-- library).
--
-- One thing to be cautioned about: the type of 'parseRequest' allows it to work in
-- different monads. If used in the 'IO' monad, it will throw an exception in
-- the case of an invalid URI. In addition, if you leverage the @IsString@
-- instance of the 'Request' value via @OverloadedStrings@, an invalid URI will
-- result in a partial value. Caveat emptor!
module Network.HTTP.Client
    ( -- $example1

      -- * Performing requests
      withResponse
    , httpLbs
    , httpNoBody
    , responseOpen
    , responseClose
      -- ** Tracking redirect history
    , withResponseHistory
    , responseOpenHistory
    , HistoriedResponse
    , hrRedirects
    , hrFinalRequest
    , hrFinalResponse
      -- * Connection manager
    , Manager
    , newManager
    , closeManager
    , withManager
    , HasHttpManager(..)
      -- ** Connection manager settings
    , ManagerSettings
    , defaultManagerSettings
    , managerConnCount
    , managerRawConnection
    , managerTlsConnection
    , managerResponseTimeout
    , managerRetryableException
    , managerWrapException
    , managerIdleConnectionCount
    , managerModifyRequest
    , managerModifyResponse
      -- *** Manager proxy settings
    , managerSetProxy
    , managerSetInsecureProxy
    , managerSetSecureProxy
    , ProxyOverride
    , proxyFromRequest
    , noProxy
    , useProxy
    , useProxySecureWithoutConnect
    , proxyEnvironment
    , proxyEnvironmentNamed
    , defaultProxy
      -- *** Response timeouts
    , ResponseTimeout
    , responseTimeoutMicro
    , responseTimeoutNone
    , responseTimeoutDefault
      -- *** Helpers
    , rawConnectionModifySocket
    , rawConnectionModifySocketSize
      -- * Request
      -- $parsing-request
    , parseUrl
    , parseUrlThrow
    , parseRequest
    , parseRequest_
    , requestFromURI
    , requestFromURI_
    , defaultRequest
    , applyBasicAuth
    , urlEncodedBody
    , getUri
    , setRequestIgnoreStatus
    , setRequestCheckStatus
    , setQueryString
#if MIN_VERSION_http_types(0,12,1)
    , setQueryStringPartialEscape
#endif
      -- ** Request type and fields
    , Request
    , method
    , secure
    , host
    , port
    , path
    , queryString
    , requestHeaders
    , requestBody
    , proxy
    , applyBasicProxyAuth
    , decompress
    , redirectCount
    , shouldStripHeaderOnRedirect
    , checkResponse
    , responseTimeout
    , cookieJar
    , requestVersion
      -- ** Request body
    , RequestBody (..)
    , Popper
    , NeedsPopper
    , GivesPopper
    , streamFile
    , observedStreamFile
    , StreamFileStatus (..)
      -- * Response
    , Response
    , responseStatus
    , responseVersion
    , responseHeaders
    , responseBody
    , responseCookieJar
    , throwErrorStatusCodes
      -- ** Response body
    , BodyReader
    , brRead
    , brReadSome
    , brConsume
      -- * Advanced connection creation
    , makeConnection
    , socketConnection
      -- * Misc
    , HttpException (..)
    , HttpExceptionContent (..)
    , Cookie (..)
    , equalCookie
    , equivCookie
    , compareCookies
    , CookieJar
    , equalCookieJar
    , equivCookieJar
    , Proxy (..)
    , withConnection
      -- * Cookies
    , module Network.HTTP.Client.Cookies
    ) where

import Network.HTTP.Client.Body
import Network.HTTP.Client.Connection (makeConnection, socketConnection)
import Network.HTTP.Client.Cookies
import Network.HTTP.Client.Core
import Network.HTTP.Client.Manager
import Network.HTTP.Client.Request
import Network.HTTP.Client.Response
import Network.HTTP.Client.Types

import Data.IORef (newIORef, writeIORef, readIORef, modifyIORef)
import qualified Data.ByteString.Lazy as L
import Data.Foldable (Foldable)
import Data.Traversable (Traversable)
import Network.HTTP.Types (statusCode)
import GHC.Generics (Generic)
import Data.Typeable (Typeable)
import Control.Exception (bracket, handle, throwIO)

-- | A datatype holding information on redirected requests and the final response.
--
-- Since 0.4.1
data HistoriedResponse body = HistoriedResponse
    { HistoriedResponse body -> [(Request, Response ByteString)]
hrRedirects :: [(Request, Response L.ByteString)]
    -- ^ Requests which resulted in a redirect, together with their responses.
    -- The response contains the first 1024 bytes of the body.
    --
    -- Since 0.4.1
    , HistoriedResponse body -> Request
hrFinalRequest :: Request
    -- ^ The final request performed.
    --
    -- Since 0.4.1
    , HistoriedResponse body -> Response body
hrFinalResponse :: Response body
    -- ^ The response from the final request.
    --
    -- Since 0.4.1
    }
    deriving (a -> HistoriedResponse b -> HistoriedResponse a
(a -> b) -> HistoriedResponse a -> HistoriedResponse b
(forall a b.
 (a -> b) -> HistoriedResponse a -> HistoriedResponse b)
-> (forall a b. a -> HistoriedResponse b -> HistoriedResponse a)
-> Functor HistoriedResponse
forall a b. a -> HistoriedResponse b -> HistoriedResponse a
forall a b. (a -> b) -> HistoriedResponse a -> HistoriedResponse b
forall (f :: * -> *).
(forall a b. (a -> b) -> f a -> f b)
-> (forall a b. a -> f b -> f a) -> Functor f
<$ :: a -> HistoriedResponse b -> HistoriedResponse a
$c<$ :: forall a b. a -> HistoriedResponse b -> HistoriedResponse a
fmap :: (a -> b) -> HistoriedResponse a -> HistoriedResponse b
$cfmap :: forall a b. (a -> b) -> HistoriedResponse a -> HistoriedResponse b
Functor, Functor HistoriedResponse
Foldable HistoriedResponse
Functor HistoriedResponse
-> Foldable HistoriedResponse
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> HistoriedResponse a -> f (HistoriedResponse b))
-> (forall (f :: * -> *) a.
    Applicative f =>
    HistoriedResponse (f a) -> f (HistoriedResponse a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> HistoriedResponse a -> m (HistoriedResponse b))
-> (forall (m :: * -> *) a.
    Monad m =>
    HistoriedResponse (m a) -> m (HistoriedResponse a))
-> Traversable HistoriedResponse
(a -> f b) -> HistoriedResponse a -> f (HistoriedResponse b)
forall (t :: * -> *).
Functor t
-> Foldable t
-> (forall (f :: * -> *) a b.
    Applicative f =>
    (a -> f b) -> t a -> f (t b))
-> (forall (f :: * -> *) a. Applicative f => t (f a) -> f (t a))
-> (forall (m :: * -> *) a b.
    Monad m =>
    (a -> m b) -> t a -> m (t b))
-> (forall (m :: * -> *) a. Monad m => t (m a) -> m (t a))
-> Traversable t
forall (m :: * -> *) a.
Monad m =>
HistoriedResponse (m a) -> m (HistoriedResponse a)
forall (f :: * -> *) a.
Applicative f =>
HistoriedResponse (f a) -> f (HistoriedResponse a)
forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> HistoriedResponse a -> m (HistoriedResponse b)
forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> HistoriedResponse a -> f (HistoriedResponse b)
sequence :: HistoriedResponse (m a) -> m (HistoriedResponse a)
$csequence :: forall (m :: * -> *) a.
Monad m =>
HistoriedResponse (m a) -> m (HistoriedResponse a)
mapM :: (a -> m b) -> HistoriedResponse a -> m (HistoriedResponse b)
$cmapM :: forall (m :: * -> *) a b.
Monad m =>
(a -> m b) -> HistoriedResponse a -> m (HistoriedResponse b)
sequenceA :: HistoriedResponse (f a) -> f (HistoriedResponse a)
$csequenceA :: forall (f :: * -> *) a.
Applicative f =>
HistoriedResponse (f a) -> f (HistoriedResponse a)
traverse :: (a -> f b) -> HistoriedResponse a -> f (HistoriedResponse b)
$ctraverse :: forall (f :: * -> *) a b.
Applicative f =>
(a -> f b) -> HistoriedResponse a -> f (HistoriedResponse b)
$cp2Traversable :: Foldable HistoriedResponse
$cp1Traversable :: Functor HistoriedResponse
Data.Traversable.Traversable, HistoriedResponse a -> Bool
(a -> m) -> HistoriedResponse a -> m
(a -> b -> b) -> b -> HistoriedResponse a -> b
(forall m. Monoid m => HistoriedResponse m -> m)
-> (forall m a. Monoid m => (a -> m) -> HistoriedResponse a -> m)
-> (forall m a. Monoid m => (a -> m) -> HistoriedResponse a -> m)
-> (forall a b. (a -> b -> b) -> b -> HistoriedResponse a -> b)
-> (forall a b. (a -> b -> b) -> b -> HistoriedResponse a -> b)
-> (forall b a. (b -> a -> b) -> b -> HistoriedResponse a -> b)
-> (forall b a. (b -> a -> b) -> b -> HistoriedResponse a -> b)
-> (forall a. (a -> a -> a) -> HistoriedResponse a -> a)
-> (forall a. (a -> a -> a) -> HistoriedResponse a -> a)
-> (forall a. HistoriedResponse a -> [a])
-> (forall a. HistoriedResponse a -> Bool)
-> (forall a. HistoriedResponse a -> Int)
-> (forall a. Eq a => a -> HistoriedResponse a -> Bool)
-> (forall a. Ord a => HistoriedResponse a -> a)
-> (forall a. Ord a => HistoriedResponse a -> a)
-> (forall a. Num a => HistoriedResponse a -> a)
-> (forall a. Num a => HistoriedResponse a -> a)
-> Foldable HistoriedResponse
forall a. Eq a => a -> HistoriedResponse a -> Bool
forall a. Num a => HistoriedResponse a -> a
forall a. Ord a => HistoriedResponse a -> a
forall m. Monoid m => HistoriedResponse m -> m
forall a. HistoriedResponse a -> Bool
forall a. HistoriedResponse a -> Int
forall a. HistoriedResponse a -> [a]
forall a. (a -> a -> a) -> HistoriedResponse a -> a
forall m a. Monoid m => (a -> m) -> HistoriedResponse a -> m
forall b a. (b -> a -> b) -> b -> HistoriedResponse a -> b
forall a b. (a -> b -> b) -> b -> HistoriedResponse a -> b
forall (t :: * -> *).
(forall m. Monoid m => t m -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall m a. Monoid m => (a -> m) -> t a -> m)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall a b. (a -> b -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall b a. (b -> a -> b) -> b -> t a -> b)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. (a -> a -> a) -> t a -> a)
-> (forall a. t a -> [a])
-> (forall a. t a -> Bool)
-> (forall a. t a -> Int)
-> (forall a. Eq a => a -> t a -> Bool)
-> (forall a. Ord a => t a -> a)
-> (forall a. Ord a => t a -> a)
-> (forall a. Num a => t a -> a)
-> (forall a. Num a => t a -> a)
-> Foldable t
product :: HistoriedResponse a -> a
$cproduct :: forall a. Num a => HistoriedResponse a -> a
sum :: HistoriedResponse a -> a
$csum :: forall a. Num a => HistoriedResponse a -> a
minimum :: HistoriedResponse a -> a
$cminimum :: forall a. Ord a => HistoriedResponse a -> a
maximum :: HistoriedResponse a -> a
$cmaximum :: forall a. Ord a => HistoriedResponse a -> a
elem :: a -> HistoriedResponse a -> Bool
$celem :: forall a. Eq a => a -> HistoriedResponse a -> Bool
length :: HistoriedResponse a -> Int
$clength :: forall a. HistoriedResponse a -> Int
null :: HistoriedResponse a -> Bool
$cnull :: forall a. HistoriedResponse a -> Bool
toList :: HistoriedResponse a -> [a]
$ctoList :: forall a. HistoriedResponse a -> [a]
foldl1 :: (a -> a -> a) -> HistoriedResponse a -> a
$cfoldl1 :: forall a. (a -> a -> a) -> HistoriedResponse a -> a
foldr1 :: (a -> a -> a) -> HistoriedResponse a -> a
$cfoldr1 :: forall a. (a -> a -> a) -> HistoriedResponse a -> a
foldl' :: (b -> a -> b) -> b -> HistoriedResponse a -> b
$cfoldl' :: forall b a. (b -> a -> b) -> b -> HistoriedResponse a -> b
foldl :: (b -> a -> b) -> b -> HistoriedResponse a -> b
$cfoldl :: forall b a. (b -> a -> b) -> b -> HistoriedResponse a -> b
foldr' :: (a -> b -> b) -> b -> HistoriedResponse a -> b
$cfoldr' :: forall a b. (a -> b -> b) -> b -> HistoriedResponse a -> b
foldr :: (a -> b -> b) -> b -> HistoriedResponse a -> b
$cfoldr :: forall a b. (a -> b -> b) -> b -> HistoriedResponse a -> b
foldMap' :: (a -> m) -> HistoriedResponse a -> m
$cfoldMap' :: forall m a. Monoid m => (a -> m) -> HistoriedResponse a -> m
foldMap :: (a -> m) -> HistoriedResponse a -> m
$cfoldMap :: forall m a. Monoid m => (a -> m) -> HistoriedResponse a -> m
fold :: HistoriedResponse m -> m
$cfold :: forall m. Monoid m => HistoriedResponse m -> m
Data.Foldable.Foldable, Int -> HistoriedResponse body -> ShowS
[HistoriedResponse body] -> ShowS
HistoriedResponse body -> String
(Int -> HistoriedResponse body -> ShowS)
-> (HistoriedResponse body -> String)
-> ([HistoriedResponse body] -> ShowS)
-> Show (HistoriedResponse body)
forall body. Show body => Int -> HistoriedResponse body -> ShowS
forall body. Show body => [HistoriedResponse body] -> ShowS
forall body. Show body => HistoriedResponse body -> String
forall a.
(Int -> a -> ShowS) -> (a -> String) -> ([a] -> ShowS) -> Show a
showList :: [HistoriedResponse body] -> ShowS
$cshowList :: forall body. Show body => [HistoriedResponse body] -> ShowS
show :: HistoriedResponse body -> String
$cshow :: forall body. Show body => HistoriedResponse body -> String
showsPrec :: Int -> HistoriedResponse body -> ShowS
$cshowsPrec :: forall body. Show body => Int -> HistoriedResponse body -> ShowS
Show, Typeable, (forall x.
 HistoriedResponse body -> Rep (HistoriedResponse body) x)
-> (forall x.
    Rep (HistoriedResponse body) x -> HistoriedResponse body)
-> Generic (HistoriedResponse body)
forall x. Rep (HistoriedResponse body) x -> HistoriedResponse body
forall x. HistoriedResponse body -> Rep (HistoriedResponse body) x
forall a.
(forall x. a -> Rep a x) -> (forall x. Rep a x -> a) -> Generic a
forall body x.
Rep (HistoriedResponse body) x -> HistoriedResponse body
forall body x.
HistoriedResponse body -> Rep (HistoriedResponse body) x
$cto :: forall body x.
Rep (HistoriedResponse body) x -> HistoriedResponse body
$cfrom :: forall body x.
HistoriedResponse body -> Rep (HistoriedResponse body) x
Generic)

-- | A variant of @responseOpen@ which keeps a history of all redirects
-- performed in the interim, together with the first 1024 bytes of their
-- response bodies.
--
-- Since 0.4.1
responseOpenHistory :: Request -> Manager -> IO (HistoriedResponse BodyReader)
responseOpenHistory :: Request -> Manager -> IO (HistoriedResponse BodyReader)
responseOpenHistory Request
reqOrig Manager
man0 = (HttpExceptionContentWrapper -> IO (HistoriedResponse BodyReader))
-> IO (HistoriedResponse BodyReader)
-> IO (HistoriedResponse BodyReader)
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
handle (HttpException -> IO (HistoriedResponse BodyReader)
forall e a. Exception e => e -> IO a
throwIO (HttpException -> IO (HistoriedResponse BodyReader))
-> (HttpExceptionContentWrapper -> HttpException)
-> HttpExceptionContentWrapper
-> IO (HistoriedResponse BodyReader)
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> HttpExceptionContentWrapper -> HttpException
toHttpException Request
reqOrig) (IO (HistoriedResponse BodyReader)
 -> IO (HistoriedResponse BodyReader))
-> IO (HistoriedResponse BodyReader)
-> IO (HistoriedResponse BodyReader)
forall a b. (a -> b) -> a -> b
$ do
    IORef Request
reqRef <- Request -> IO (IORef Request)
forall a. a -> IO (IORef a)
newIORef Request
reqOrig
    IORef
  ([(Request, Response ByteString)]
   -> [(Request, Response ByteString)])
historyRef <- ([(Request, Response ByteString)]
 -> [(Request, Response ByteString)])
-> IO
     (IORef
        ([(Request, Response ByteString)]
         -> [(Request, Response ByteString)]))
forall a. a -> IO (IORef a)
newIORef [(Request, Response ByteString)]
-> [(Request, Response ByteString)]
forall a. a -> a
id
    let go :: Request -> IO (Response BodyReader, Request, Bool)
go Request
req0 = do
            (Manager
man, Request
req) <- Manager -> Request -> IO (Manager, Request)
getModifiedRequestManager Manager
man0 Request
req0
            (Request
req', Response BodyReader
res') <- Request -> Manager -> IO (Request, Response BodyReader)
httpRaw' Request
req Manager
man
            let res :: Response BodyReader
res = Response BodyReader
res'
                    { responseBody :: BodyReader
responseBody = (HttpExceptionContentWrapper -> BodyReader)
-> BodyReader -> BodyReader
forall e a. Exception e => (e -> IO a) -> IO a -> IO a
handle (HttpException -> BodyReader
forall e a. Exception e => e -> IO a
throwIO (HttpException -> BodyReader)
-> (HttpExceptionContentWrapper -> HttpException)
-> HttpExceptionContentWrapper
-> BodyReader
forall b c a. (b -> c) -> (a -> b) -> a -> c
. Request -> HttpExceptionContentWrapper -> HttpException
toHttpException Request
req0)
                                            (Response BodyReader -> BodyReader
forall body. Response body -> body
responseBody Response BodyReader
res')
                    }
            case Request -> ResponseHeaders -> CookieJar -> Int -> Maybe Request
getRedirectedRequest
                    Request
req'
                    (Response BodyReader -> ResponseHeaders
forall body. Response body -> ResponseHeaders
responseHeaders Response BodyReader
res)
                    (Response BodyReader -> CookieJar
forall body. Response body -> CookieJar
responseCookieJar Response BodyReader
res)
                    (Status -> Int
statusCode (Status -> Int) -> Status -> Int
forall a b. (a -> b) -> a -> b
$ Response BodyReader -> Status
forall body. Response body -> Status
responseStatus Response BodyReader
res) of
                Maybe Request
Nothing -> (Response BodyReader, Request, Bool)
-> IO (Response BodyReader, Request, Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Response BodyReader
res, Request
req', Bool
False)
                Just Request
req'' -> do
                    IORef Request -> Request -> IO ()
forall a. IORef a -> a -> IO ()
writeIORef IORef Request
reqRef Request
req''
                    ByteString
body <- BodyReader -> Int -> IO ByteString
brReadSome (Response BodyReader -> BodyReader
forall body. Response body -> body
responseBody Response BodyReader
res) Int
1024
                    IORef
  ([(Request, Response ByteString)]
   -> [(Request, Response ByteString)])
-> (([(Request, Response ByteString)]
     -> [(Request, Response ByteString)])
    -> [(Request, Response ByteString)]
    -> [(Request, Response ByteString)])
-> IO ()
forall a. IORef a -> (a -> a) -> IO ()
modifyIORef IORef
  ([(Request, Response ByteString)]
   -> [(Request, Response ByteString)])
historyRef (([(Request, Response ByteString)]
 -> [(Request, Response ByteString)])
-> ([(Request, Response ByteString)]
    -> [(Request, Response ByteString)])
-> [(Request, Response ByteString)]
-> [(Request, Response ByteString)]
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ((Request
req, Response BodyReader
res { responseBody :: ByteString
responseBody = ByteString
body })(Request, Response ByteString)
-> [(Request, Response ByteString)]
-> [(Request, Response ByteString)]
forall a. a -> [a] -> [a]
:))
                    (Response BodyReader, Request, Bool)
-> IO (Response BodyReader, Request, Bool)
forall (m :: * -> *) a. Monad m => a -> m a
return (Response BodyReader
res, Request
req'', Bool
True)
    (Request
_, Response BodyReader
res) <- Int
-> (Request -> IO (Response BodyReader, Request, Bool))
-> Request
-> IO (Request, Response BodyReader)
httpRedirect' (Request -> Int
redirectCount Request
reqOrig) Request -> IO (Response BodyReader, Request, Bool)
go Request
reqOrig
    Request
reqFinal <- IORef Request -> IO Request
forall a. IORef a -> IO a
readIORef IORef Request
reqRef
    [(Request, Response ByteString)]
-> [(Request, Response ByteString)]
history <- IORef
  ([(Request, Response ByteString)]
   -> [(Request, Response ByteString)])
-> IO
     ([(Request, Response ByteString)]
      -> [(Request, Response ByteString)])
forall a. IORef a -> IO a
readIORef IORef
  ([(Request, Response ByteString)]
   -> [(Request, Response ByteString)])
historyRef
    HistoriedResponse BodyReader -> IO (HistoriedResponse BodyReader)
forall (m :: * -> *) a. Monad m => a -> m a
return HistoriedResponse :: forall body.
[(Request, Response ByteString)]
-> Request -> Response body -> HistoriedResponse body
HistoriedResponse
        { hrRedirects :: [(Request, Response ByteString)]
hrRedirects = [(Request, Response ByteString)]
-> [(Request, Response ByteString)]
history []
        , hrFinalRequest :: Request
hrFinalRequest = Request
reqFinal
        , hrFinalResponse :: Response BodyReader
hrFinalResponse = Response BodyReader
res
        }

-- | A variant of @withResponse@ which keeps a history of all redirects
-- performed in the interim, together with the first 1024 bytes of their
-- response bodies.
--
-- Since 0.4.1
withResponseHistory :: Request
                    -> Manager
                    -> (HistoriedResponse BodyReader -> IO a)
                    -> IO a
withResponseHistory :: Request
-> Manager -> (HistoriedResponse BodyReader -> IO a) -> IO a
withResponseHistory Request
req Manager
man = IO (HistoriedResponse BodyReader)
-> (HistoriedResponse BodyReader -> IO ())
-> (HistoriedResponse BodyReader -> IO a)
-> IO a
forall a b c. IO a -> (a -> IO b) -> (a -> IO c) -> IO c
bracket
    (Request -> Manager -> IO (HistoriedResponse BodyReader)
responseOpenHistory Request
req Manager
man)
    (Response BodyReader -> IO ()
forall a. Response a -> IO ()
responseClose (Response BodyReader -> IO ())
-> (HistoriedResponse BodyReader -> Response BodyReader)
-> HistoriedResponse BodyReader
-> IO ()
forall b c a. (b -> c) -> (a -> b) -> a -> c
. HistoriedResponse BodyReader -> Response BodyReader
forall body. HistoriedResponse body -> Response body
hrFinalResponse)

-- | Set the proxy override value, only for HTTP (insecure) connections.
--
-- Since 0.4.7
managerSetInsecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetInsecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetInsecureProxy ProxyOverride
po ManagerSettings
m = ManagerSettings
m { managerProxyInsecure :: ProxyOverride
managerProxyInsecure = ProxyOverride
po }

-- | Set the proxy override value, only for HTTPS (secure) connections.
--
-- Since 0.4.7
managerSetSecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetSecureProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetSecureProxy ProxyOverride
po ManagerSettings
m = ManagerSettings
m { managerProxySecure :: ProxyOverride
managerProxySecure = ProxyOverride
po }

-- | Set the proxy override value, for both HTTP (insecure) and HTTPS
-- (insecure) connections.
--
-- Since 0.4.7
managerSetProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetProxy :: ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetProxy ProxyOverride
po = ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetInsecureProxy ProxyOverride
po (ManagerSettings -> ManagerSettings)
-> (ManagerSettings -> ManagerSettings)
-> ManagerSettings
-> ManagerSettings
forall b c a. (b -> c) -> (a -> b) -> a -> c
. ProxyOverride -> ManagerSettings -> ManagerSettings
managerSetSecureProxy ProxyOverride
po

-- $example1
-- = Example Usage
--
-- === Making a GET request
--
-- > import Network.HTTP.Client
-- > import Network.HTTP.Types.Status (statusCode)
-- >
-- > main :: IO ()
-- > main = do
-- >   manager <- newManager defaultManagerSettings
-- >
-- >   request <- parseRequest "http://httpbin.org/get"
-- >   response <- httpLbs request manager
-- >
-- >   putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response)
-- >   print $ responseBody response
--
--
-- === Posting JSON to a server
--
-- > {-# LANGUAGE OverloadedStrings #-}
-- > import Network.HTTP.Client
-- > import Network.HTTP.Types.Status (statusCode)
-- > import Data.Aeson (object, (.=), encode)
-- > import Data.Text (Text)
-- >
-- > main :: IO ()
-- > main = do
-- >   manager <- newManager defaultManagerSettings
-- >
-- >   -- Create the request
-- >   let requestObject = object ["name" .= "Michael", "age" .= 30]
-- >   let requestObject = object
-- >    [ "name" .= ("Michael" :: Text)
-- >    , "age"  .= (30 :: Int)
-- >    ]
-- >
-- >   initialRequest <- parseRequest "http://httpbin.org/post"
-- >   let request = initialRequest { method = "POST", requestBody = RequestBodyLBS $ encode requestObject }
-- >
-- >   response <- httpLbs request manager
-- >   putStrLn $ "The status code was: " ++ (show $ statusCode $ responseStatus response)
-- >   print $ responseBody response
--

-- | Specify maximum time in microseconds the retrieval of response
-- headers is allowed to take
--
-- @since 0.5.0
responseTimeoutMicro :: Int -> ResponseTimeout
responseTimeoutMicro :: Int -> ResponseTimeout
responseTimeoutMicro = Int -> ResponseTimeout
ResponseTimeoutMicro

-- | Do not have a response timeout
--
-- @since 0.5.0
responseTimeoutNone :: ResponseTimeout
responseTimeoutNone :: ResponseTimeout
responseTimeoutNone = ResponseTimeout
ResponseTimeoutNone

-- | Use the default response timeout
--
-- When used on a 'Request', means: use the manager's timeout value
--
-- When used on a 'ManagerSettings', means: default to 30 seconds
--
-- @since 0.5.0
responseTimeoutDefault :: ResponseTimeout
responseTimeoutDefault :: ResponseTimeout
responseTimeoutDefault = ResponseTimeout
ResponseTimeoutDefault

-- $parsing-request
--
-- The way you parse string of characters to construct a 'Request' will
-- determine whether exceptions will be thrown on non-2XX response status
-- codes. This is because the behavior is controlled by a setting in
-- 'Request' itself (see 'checkResponse') and different parsing functions
-- set it to different 'IO' actions.