@@ -8,7 +8,7 @@
88-- Portability : portable
99--
1010-- This is an easy-to-use, type-safe, expandable, high-level HTTP library
11−-- that just works without fooling around.
11+-- that just works without any fooling around.
1212--
1313-- /(A modest intro goes here, click on 'req' to start making requests.)/
1414--
@@ -19,19 +19,17 @@
1919-- currently modify 'L.ManagerSettings' of default manager because the
2020-- library always use the same implicit global manager for simplicity and
2121-- maximal connection sharing. There is a way to use your own manager with
22−-- different settings, but it requires a bit more typing. Just like with my
23−-- other library, Megaparsec, I spent considerable amount of time working on
24−-- the documentation and examples, because doing HTTP requests is a common
25−-- task and Haskell library for this should be very approachable and clear
26−-- to beginners.
22+-- different settings, but it requires a bit more typing. Doing HTTP
23+-- requests is a common task and Haskell library for this should be very
24+-- approachable and clear to beginners.
2725--
2826-- “Type-safe” means that the library is protective and eliminates certain
2927-- class of errors compared to alternative libraries like @wreq@ or vanilla
30−-- @http-client@. For example it makes sure user does not send request body
31−-- when using methods like 'GET' or 'DELETE', minimizes amount of implicit
32−-- assumptions making user specify his\/her intentions in explicit form (for
33−-- example it's not possible to avoid specifying body or method of a
34−-- request). It carefully hides underlying types from lower-level
28+-- @http-client@. For example it makes sure that user does not send request
29+-- body when using methods like 'GET' or 'DELETE', minimizes amount of
30+-- implicit assumptions making user specify his\/her intentions in explicit
31+-- form (for example it's not possible to avoid specifying body or method of
32+-- a request). It carefully hides underlying types from lower-level
3533-- @http-client@ package because it's not type safe enough (for example
3634-- 'L.Request' is an instance of 'Data.String.IsString' and if it's
3735-- malformed, it will blow up at run-time).
@@ -39,10 +37,10 @@
3937-- “Expandable” refers to the ability of the library to be expanded without
4038-- ugly hacking. For example it's possible to define your own HTTP methods,
4139-- new ways to construct body of request, new authorization options, new
42−-- ways to actually perform request and how to represent\/parse it. As user
43−-- extends the library to satisfy his\/her special needs, the new solutions
44−-- work just like built-ins. That said, all common cases are covered by the
45−-- library out-of-the-box.
40+-- ways to actually perform request and how to represent\/parse its
41+-- response. As user extends the library to satisfy his\/her special needs,
42+-- the new solutions work just like built-ins. That said, all common cases
43+-- are covered by the library out-of-the-box.
4644--
4745-- “High-level” means that there are less details to worry about. The
4846-- library is a result of my experiences as a Haskell consultant, working
@@ -52,12 +50,12 @@
5250-- concerned with purity: just define 'handleHttpException' accordingly when
5351-- making your monad instance of 'MonadHttp' and it will play seamlessly.
5452-- Finally, the library cuts boilerplate considerably and helps write
55−-- concise, easy to read code, thanks to its minimal and very uniform API.
53+-- concise, easy to read code, thanks to its minimal and uniform API.
5654--
5755-- The documentation below is structured in such a way that most important
5856-- information goes first: you learn how to do HTTP requests, then how to
59−-- embed them any monad you have, then it goes on giving you details about
60−-- less-common things you may want to know about. The documentation is
57+-- embed them in any monad you have, then it goes on giving you details
58+-- about less-common things you may want to know about. The documentation is
6159-- written with sufficient coverage of details and examples, it's designed
6260-- to be a complete tutorial on its own.
6361--
@@ -68,7 +66,7 @@
6866-- * <https://hackage.haskell.org/package/http-client> — low level HTTP
6967-- client used everywhere in Haskell.
7068-- * <https://hackage.haskell.org/package/http-client-tls> — TLS (HTTPS)
71−-- support.
69+-- support for @http-client@.
7270-- * <https://hackage.haskell.org/package/http-conduit> — conduit
7371-- interface to @http-client@.
7472--
@@ -80,15 +78,11 @@
8078{-# LANGUAGE DeriveDataTypeable #-}
8179{-# LANGUAGE DeriveGeneric #-}
8280{-# LANGUAGE FlexibleInstances #-}
83−{-# LANGUAGE GADTs #-}
8481{-# LANGUAGE GeneralizedNewtypeDeriving #-}
8582{-# LANGUAGE KindSignatures #-}
86−{-# LANGUAGE MultiParamTypeClasses #-}
87−{-# LANGUAGE OverloadedStrings #-}
8883{-# LANGUAGE RecordWildCards #-}
8984{-# LANGUAGE ScopedTypeVariables #-}
9085{-# LANGUAGE TypeFamilies #-}
91−{-# LANGUAGE UndecidableInstances #-}
9286{-# OPTIONS_GHC -fno-warn-redundant-constraints #-}
9387
9488module Network.HTTP.Req
@@ -151,12 +145,13 @@ import Data.Typeable (Typeable)
151145import GHC.Generics
152146import GHC.TypeLits
153147import System.IO.Unsafe (unsafePerformIO)
154−import qualified Data.ByteString as B
155−import qualified Data.ByteString.Lazy as BL
156−import qualified Network.Connection as NC
157−import qualified Network.HTTP.Client as L
158−import qualified Network.HTTP.Client.TLS as L
159−import qualified Network.HTTP.Types as Y
148+import qualified Data.ByteString as B
149+import qualified Data.ByteString.Lazy as BL
150+import qualified Network.Connection as NC
151+import qualified Network.HTTP.Client as L
152+import qualified Network.HTTP.Client.Internal as LI
153+import qualified Network.HTTP.Client.TLS as L
154+import qualified Network.HTTP.Types as Y
160155
161156----------------------------------------------------------------------------
162157-- Making a request
@@ -193,24 +188,17 @@ req method url body options = do
193188 liftIO (try $ getHttpResponse manager request)
194189 >>= either handleHttpException return
195190
196−----------------------------------------------------------------------------
197−-- Embedding requests into your monad
198−
199−-- $embedding-requests
200−--
201−-- To use 'req' in your monad, all you need to do is to make it an instance
202−-- of the 'MonadHttp' type class, which see.
203−
204191-- | Global 'L.Manager' that 'req' uses. Here we just go with the default
205192-- settings, so users don't need to deal with this manager stuff at all, but
206193-- when we create a request, instance 'HttpConfig' can affect the default
207194-- settings via 'getHttpConfig'.
208195--
209−-- A note about safety in case 'unsafePerformIO' looks suspicious to you.
196+-- A note about safety, in case 'unsafePerformIO' looks suspicious to you.
210197-- The value of 'globalManager' is named and lives on top level. This means
211198-- it will be shared, i.e. computed only once on first use of manager. From
212199-- that moment on the 'IORef' will be just reused — exactly the behaviour we
213−-- want here in order to maximize connection sharing.
200+-- want here in order to maximize connection sharing. GHC could spoil the
201+-- plan by inlining the definition, hence the @NOINLINE@ pragma.
214202
215203globalManager :: IORef L.Manager
216204globalManager = unsafePerformIO $ do
@@ -220,6 +208,14 @@ globalManager = unsafePerformIO $ do
220208 newIORef manager
221209{-# NOINLINE globalManager #-}
222210
211+----------------------------------------------------------------------------
212+-- Embedding requests into your monad
213+
214+-- $embedding-requests
215+--
216+-- To use 'req' in your monad, all you need to do is to make the monad an
217+-- instance of the 'MonadHttp' type class, which see.
218+
223219-- | A type class for monads that support performing HTTP requests.
224220-- Typically, you only need to define the 'handleHttpException' method
225221-- unless you want to tweak 'HttpConfig'.
@@ -257,18 +253,23 @@ data HttpConfig = HttpConfig
257253 , httpConfigRedirectCount :: Word
258254 -- ^ How many redirects to follow when getting a resource. Default
259255 -- value: 10.
260− } deriving (Show, Read, Eq, Ord, Typeable, Generic)
261− -- ↑ NOTE We can't derive 'Data' here because of 'L.Proxy'.
256+ , httpConfigAltManager :: Maybe L.Manager
257+ -- ^ Alternative 'L.Manager' to use. 'Nothing' (default value) means
258+ -- that default implicit manager will be used (that's what you want in
259+ -- 99% of cases).
260+ } deriving Typeable
262261
263262instance Default HttpConfig where
264263 def = HttpConfig
265264 { httpConfigProxy = Nothing
266− , httpConfigRedirectCount = 10 }
265+ , httpConfigRedirectCount = 10
266+ , httpConfigAltManager = Nothing }
267267
268268instance RequestComponent HttpConfig where
269269 getRequestMod HttpConfig {..} = Endo $ \x ->
270− x { L.proxy = httpConfigProxy
271− , L.redirectCount = fromIntegral httpConfigRedirectCount }
270+ x { L.proxy = httpConfigProxy
271+ , L.redirectCount = fromIntegral httpConfigRedirectCount
272+ , LI.requestManagerOverride = httpConfigAltManager }
272273
273274----------------------------------------------------------------------------
274275-- Request — Methods
@@ -376,9 +377,6 @@ class HttpMethod a where
376377
377378 httpMethodName :: Proxy a -> Y.Method
378379
379−-- NOTE Now we state how to get an endomorphism on 'Request's that changes
380−-- given 'Request' so it has the specified method.
381−
382380instance HttpMethod method => RequestComponent (Womb "method" method) where
383381 getRequestMod _ = Endo $ \x ->
384382 x { L.method = httpMethodName (Proxy :: Proxy method) }