@@ -1,3 +1,20 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE DataKinds #-}
3+{-# LANGUAGE DeriveDataTypeable #-}
4+{-# LANGUAGE DeriveGeneric #-}
5+{-# LANGUAGE FlexibleInstances #-}
6+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
7+{-# LANGUAGE KindSignatures #-}
8+{-# LANGUAGE LambdaCase #-}
9+{-# LANGUAGE MultiParamTypeClasses #-}
10+{-# LANGUAGE OverloadedStrings #-}
11+{-# LANGUAGE QuasiQuotes #-}
12+{-# LANGUAGE RankNTypes #-}
13+{-# LANGUAGE RecordWildCards #-}
14+{-# LANGUAGE ScopedTypeVariables #-}
15+{-# LANGUAGE TypeFamilies #-}
16+{-# LANGUAGE UndecidableInstances #-}
2-- Module : Network.HTTP.Req
19-- Module : Network.HTTP.Req
3-- Copyright : © 2016–present Mark Karpov
20-- Copyright : © 2016–present Mark Karpov
@@ -87,128 +104,128 @@
87-- the whole Haskell ecosystem uses, there is no risk in using @req@. The
104-- the whole Haskell ecosystem uses, there is no risk in using @req@. The
88-- machinery for performing requests is the same as with @http-conduit@ and
105-- machinery for performing requests is the same as with @http-conduit@ and
89-- @wreq@. The only difference is the API.
106-- @wreq@. The only difference is the API.
91−{-# LANGUAGE BangPatterns #-}
92−{-# LANGUAGE DataKinds #-}
93−{-# LANGUAGE DeriveDataTypeable #-}
94−{-# LANGUAGE DeriveGeneric #-}
95−{-# LANGUAGE FlexibleInstances #-}
96−{-# LANGUAGE GeneralizedNewtypeDeriving #-}
97−{-# LANGUAGE KindSignatures #-}
98−{-# LANGUAGE LambdaCase #-}
99−{-# LANGUAGE MultiParamTypeClasses #-}
100−{-# LANGUAGE OverloadedStrings #-}
101−{-# LANGUAGE QuasiQuotes #-}
102−{-# LANGUAGE RankNTypes #-}
103−{-# LANGUAGE RecordWildCards #-}
104−{-# LANGUAGE ScopedTypeVariables #-}
105−{-# LANGUAGE TypeFamilies #-}
106−{-# LANGUAGE UndecidableInstances #-}
108module Network.HTTP.Req
107module Network.HTTP.Req
109 ( -- * Making a request
108 ( -- * Making a request
110 -- $making-a-request
109 -- $making-a-request
114− , withReqManager
113+ withReqManager,
115 -- * Embedding requests in your monad
115 -- * Embedding requests in your monad
116 -- $embedding-requests
116 -- $embedding-requests
117− , MonadHttp (..)
117+ MonadHttp (..),
118− , HttpConfig (..)
118+ HttpConfig (..),
119− , defaultHttpConfig
119+ defaultHttpConfig,
121− , runReq
121+ runReq,
122 -- * Request
123 -- * Request
123 -- ** Method
125 -- ** Method
124 -- $method
126 -- $method
125− , GET (..)
127+ GET (..),
126− , POST (..)
128+ POST (..),
127− , HEAD (..)
129+ HEAD (..),
128− , PUT (..)
130+ PUT (..),
129− , DELETE (..)
131+ DELETE (..),
130− , TRACE (..)
132+ TRACE (..),
131− , CONNECT (..)
133+ CONNECT (..),
132− , OPTIONS (..)
134+ OPTIONS (..),
133− , PATCH (..)
135+ PATCH (..),
134− , HttpMethod (..)
136+ HttpMethod (..),
135 -- ** URL
138 -- ** URL
142− , useHttpURI
145+ useHttpURI,
143− , useHttpsURI
146+ useHttpsURI,
144− , useURI
147+ useURI,
145 -- ** Body
149 -- ** Body
147− , NoReqBody (..)
151+ NoReqBody (..),
148− , ReqBodyJson (..)
152+ ReqBodyJson (..),
149− , ReqBodyFile (..)
153+ ReqBodyFile (..),
150− , ReqBodyBs (..)
154+ ReqBodyBs (..),
151− , ReqBodyLbs (..)
155+ ReqBodyLbs (..),
152− , ReqBodyUrlEnc (..)
156+ ReqBodyUrlEnc (..),
153− , FormUrlEncodedParam
157+ FormUrlEncodedParam,
154− , ReqBodyMultipart
158+ ReqBodyMultipart,
155− , reqBodyMultipart
159+ reqBodyMultipart,
156− , HttpBody (..)
160+ HttpBody (..),
157− , ProvidesBody
161+ ProvidesBody,
158− , HttpBodyAllowed
162+ HttpBodyAllowed,
159 -- ** Optional parameters
164 -- ** Optional parameters
160 -- $optional-parameters
165 -- $optional-parameters
161− , Option
166+ Option,
162 -- *** Query parameters
168 -- *** Query parameters
163 -- $query-parameters
169 -- $query-parameters
165− , queryFlag
171+ queryFlag,
166− , QueryParam (..)
172+ QueryParam (..),
167 -- *** Headers
174 -- *** Headers
168− , header
175+ header,
169− , attachHeader
176+ attachHeader,
170 -- *** Cookies
178 -- *** Cookies
171 -- $cookies
179 -- $cookies
172− , cookieJar
180+ cookieJar,
173 -- *** Authentication
182 -- *** Authentication
174 -- $authentication
183 -- $authentication
175− , basicAuth
184+ basicAuth,
176− , basicAuthUnsafe
185+ basicAuthUnsafe,
177− , basicProxyAuth
186+ basicProxyAuth,
178− , oAuth1
187+ oAuth1,
179− , oAuth2Bearer
188+ oAuth2Bearer,
180− , oAuth2Token
189+ oAuth2Token,
181− , customAuth
190+ customAuth,
182 -- *** Other
192 -- *** Other
184− , decompress
194+ decompress,
185− , responseTimeout
195+ responseTimeout,
186− , httpVersion
196+ httpVersion,
187 -- * Response
198 -- * Response
188 -- ** Response interpretations
200 -- ** Response interpretations
189− , IgnoreResponse
201+ IgnoreResponse,
190− , ignoreResponse
202+ ignoreResponse,
191− , JsonResponse
203+ JsonResponse,
192− , jsonResponse
204+ jsonResponse,
193− , BsResponse
205+ BsResponse,
194− , bsResponse
206+ bsResponse,
195− , LbsResponse
207+ LbsResponse,
196− , lbsResponse
208+ lbsResponse,
197 -- ** Inspecting a response
210 -- ** Inspecting a response
198− , responseBody
211+ responseBody,
199− , responseStatusCode
212+ responseStatusCode,
200− , responseStatusMessage
213+ responseStatusMessage,
201− , responseHeader
214+ responseHeader,
202− , responseCookieJar
215+ responseCookieJar,
203 -- ** Defining your own interpretation
217 -- ** Defining your own interpretation
204 -- $new-response-interpretation
218 -- $new-response-interpretation
205− , HttpResponse (..)
219+ HttpResponse (..),
206 -- * Other
221 -- * Other
207− , HttpException (..)
222+ HttpException (..),
208− , CanHaveBody (..)
223+ CanHaveBody (..),
209− , Scheme (..) )
224+ Scheme (..),
228+import qualified Blaze.ByteString.Builder as BB
212import Control.Applicative
229import Control.Applicative
213import Control.Arrow (first, second)
230import Control.Arrow (first, second)
214import Control.Exception hiding (TypeError)
231import Control.Exception hiding (TypeError)
@@ -217,40 +234,39 @@ import Control.Monad.IO.Class
217import Control.Monad.Reader
234import Control.Monad.Reader
218import Control.Monad.Trans.Control
235import Control.Monad.Trans.Control
219import Control.Retry
236import Control.Retry
220−import Data.Aeson (ToJSON (..), FromJSON (..))
237+import Data.Aeson (FromJSON (..), ToJSON (..))
238+import qualified Data.Aeson as A
221import Data.ByteString (ByteString)
239import Data.ByteString (ByteString)
240+import qualified Data.ByteString as B
241+import qualified Data.ByteString.Lazy as BL
242+import qualified Data.CaseInsensitive as CI
222import Data.Data (Data)
243import Data.Data (Data)
223import Data.Function (on)
244import Data.Function (on)
224import Data.IORef
245import Data.IORef
225import Data.Kind (Constraint, Type)
246import Data.Kind (Constraint, Type)
226−import Data.List (nubBy, foldl')
247+import Data.List (foldl', nubBy)
227import Data.List.NonEmpty (NonEmpty (..))
248import Data.List.NonEmpty (NonEmpty (..))
249+import qualified Data.List.NonEmpty as NE
228import Data.Maybe (fromMaybe)
250import Data.Maybe (fromMaybe)
229import Data.Proxy
251import Data.Proxy
230import Data.Semigroup hiding (Option, option)
252import Data.Semigroup hiding (Option, option)
231import Data.Text (Text)
253import Data.Text (Text)
254+import qualified Data.Text.Encoding as T
232import Data.Typeable (Typeable)
255import Data.Typeable (Typeable)
233import GHC.Generics
256import GHC.Generics
234import GHC.TypeLits
257import GHC.TypeLits
258+import qualified Network.Connection as NC
259+import qualified Network.HTTP.Client as L
260+import qualified Network.HTTP.Client.Internal as LI
261+import qualified Network.HTTP.Client.MultipartFormData as LM
262+import qualified Network.HTTP.Client.TLS as L
263+import qualified Network.HTTP.Types as Y
235import System.IO.Unsafe (unsafePerformIO)
264import System.IO.Unsafe (unsafePerformIO)
236import Text.URI (URI)
265import Text.URI (URI)
266+import qualified Text.URI as URI
267+import qualified Text.URI.QQ as QQ
268+import qualified Web.Authenticate.OAuth as OAuth
237import Web.HttpApiData (ToHttpApiData (..))
269import Web.HttpApiData (ToHttpApiData (..))
238−import qualified Blaze.ByteString.Builder as BB
239−import qualified Data.Aeson as A
240−import qualified Data.ByteString as B
241−import qualified Data.ByteString.Lazy as BL
242−import qualified Data.CaseInsensitive as CI
243−import qualified Data.List.NonEmpty as NE
244−import qualified Data.Text.Encoding as T
245−import qualified Network.Connection as NC
246−import qualified Network.HTTP.Client as L
247−import qualified Network.HTTP.Client.Internal as LI
248−import qualified Network.HTTP.Client.MultipartFormData as LM
249−import qualified Network.HTTP.Client.TLS as L
250−import qualified Network.HTTP.Types as Y
251−import qualified Text.URI as URI
252−import qualified Text.URI.QQ as QQ
253−import qualified Web.Authenticate.OAuth as OAuth
255----------------------------------------------------------------------------
271----------------------------------------------------------------------------
256-- Making a request
272-- Making a request
@@ -382,19 +398,25 @@ import qualified Web.Authenticate.OAuth as OAuth
382-- > options <> -- contains the ?foo=bar part
398-- > options <> -- contains the ?foo=bar part
383-- > port 443 -- here you can put any port of course
399-- > port 443 -- here you can put any port of course
384-- > liftIO $ print (responseBody response :: Value)
400-- > liftIO $ print (responseBody response :: Value)
387− :: ( MonadHttp m
402+ ( MonadHttp m,
388− , HttpMethod method
403+ HttpMethod method,
389− , HttpBody body
404+ HttpBody body,
390− , HttpResponse response
405+ HttpResponse response,
391− , HttpBodyAllowed (AllowsBody method) (ProvidesBody body) )
406+ HttpBodyAllowed (AllowsBody method) (ProvidesBody body)
392− => method -- ^ HTTP method
408+ -- | HTTP method
393− -> Url scheme -- ^ 'Url'—location of resource
410+ -- | 'Url'—location of resource
394− -> body -- ^ Body of the request
412+ -- | Body of the request
395− -> Proxy response -- ^ A hint how to interpret response
414+ -- | A hint how to interpret response
396− -> Option scheme -- ^ Collection of optional parameters
416+ -- | Collection of optional parameters
397− -> m response -- ^ Response
418+ -- | Response
398req method url body responseProxy options =
420req method url body responseProxy options =
399 reqBr method url body (options <> extraOptions) getHttpResponse
421 reqBr method url body (options <> extraOptions) getHttpResponse
@@ -408,39 +430,49 @@ req method url body responseProxy options =
408-- 'L.BodyReader'@ manually, in a custom way.
430-- 'L.BodyReader'@ manually, in a custom way.
410-- @since 1.0.0
432-- @since 1.0.0
413− :: ( MonadHttp m
434+ ( MonadHttp m,
414− , HttpMethod method
435+ HttpMethod method,
415− , HttpBody body
436+ HttpBody body,
416− , HttpBodyAllowed (AllowsBody method) (ProvidesBody body) )
437+ HttpBodyAllowed (AllowsBody method) (ProvidesBody body)
417− => method -- ^ HTTP method
439+ -- | HTTP method
418− -> Url scheme -- ^ 'Url'—location of resource
441+ -- | 'Url'—location of resource
419− -> body -- ^ Body of the request
443+ -- | Body of the request
420− -> Option scheme -- ^ Collection of optional parameters
445+ -- | Collection of optional parameters
421− -> (L.Response L.BodyReader -> IO a) -- ^ How to consume response
447+ -- | How to consume response
448+ (L.Response L.BodyReader -> IO a) ->
422− -> m a -- ^ Result
449+ -- | Result
423reqBr method url body options consume = req' method url body options $ \request manager -> do
451reqBr method url body options consume = req' method url body options $ \request manager -> do
424− HttpConfig {..} <- getHttpConfig
452+ HttpConfig {..} <- getHttpConfig
425 let wrapVanilla = handle (throwIO . VanillaHttpException)
453 let wrapVanilla = handle (throwIO . VanillaHttpException)
426− wrapExc = handle (throwIO . LI.toHttpException request)
454+ wrapExc = handle (throwIO . LI.toHttpException request)
427− withRRef = bracket
455+ withRRef =
428− (newIORef Nothing)
457+ (newIORef Nothing)
429− (readIORef >=> mapM_ L.responseClose)
458+ (readIORef >=> mapM_ L.responseClose)
430− (liftIO . try . wrapVanilla . wrapExc) (withRRef $ \rref -> do
459+ (liftIO . try . wrapVanilla . wrapExc)
460+ ( withRRef $ \rref -> do
431− let openResponse = mask_ $ do
461+ let openResponse = mask_ $ do
432− r <- readIORef rref
462+ r <- readIORef rref
433− mapM_ L.responseClose r
463+ mapM_ L.responseClose r
434− r' <- L.responseOpen request manager
464+ r' <- L.responseOpen request manager
435− writeIORef rref (Just r')
465+ writeIORef rref (Just r')
436− return r'
466+ return r'
437− r <- retrying
468+ retrying
438− httpConfigRetryPolicy
469+ httpConfigRetryPolicy
439− (\st r -> return $ httpConfigRetryJudge st r)
470+ (\st r -> return $ httpConfigRetryJudge st r)
440− (const openResponse)
471+ (const openResponse)
441− (preview, r') <- grabPreview bodyPreviewLength r
472+ (preview, r') <- grabPreview bodyPreviewLength r
442− mapM_ LI.throwHttp (httpConfigCheckResponse request r' preview)
473+ mapM_ LI.throwHttp (httpConfigCheckResponse request r' preview)
443− consume r')
474+ consume r'
444 >>= either handleHttpException return
476 >>= either handleHttpException return
446-- | Mostly like 'req' with respect to its arguments, but accepts a callback
478-- | Mostly like 'req' with respect to its arguments, but accepts a callback
@@ -451,44 +483,50 @@ reqBr method url body options consume = req' method url body options $ \request
451-- 'L.Request' and allows you to use it.
483-- 'L.Request' and allows you to use it.
453-- @since 0.3.0
485-- @since 0.3.0
456− :: forall m method body scheme a.
487+ forall m method body scheme a.
457− ( MonadHttp m
488+ ( MonadHttp m,
458− , HttpMethod method
489+ HttpMethod method,
459− , HttpBody body
490+ HttpBody body,
460− , HttpBodyAllowed (AllowsBody method) (ProvidesBody body) )
491+ HttpBodyAllowed (AllowsBody method) (ProvidesBody body)
461− => method -- ^ HTTP method
493+ -- | HTTP method
462− -> Url scheme -- ^ 'Url'—location of resource
495+ -- | 'Url'—location of resource
463− -> body -- ^ Body of the request
497+ -- | Body of the request
464− -> Option scheme -- ^ Collection of optional parameters
499+ -- | Collection of optional parameters
465− -> (L.Request -> L.Manager -> m a) -- ^ How to perform request
501+ -- | How to perform request
502+ (L.Request -> L.Manager -> m a) ->
466− -> m a -- ^ Result
503+ -- | Result
467req' method url body options m = do
505req' method url body options m = do
468 config <- getHttpConfig
506 config <- getHttpConfig
469 let -- NOTE First appearance of any given header wins. This allows to
507 let -- NOTE First appearance of any given header wins. This allows to
470 -- “overwrite” headers when we construct a request by cons-ing.
508 -- “overwrite” headers when we construct a request by cons-ing.
471 nubHeaders = Endo $ \x ->
509 nubHeaders = Endo $ \x ->
472− x { L.requestHeaders = nubBy ((==) `on` fst) (L.requestHeaders x) }
510+ x {L.requestHeaders = nubBy ((==) `on` fst) (L.requestHeaders x)}
473− request' = flip appEndo L.defaultRequest $
512+ flip appEndo L.defaultRequest $
474− -- NOTE The order of 'mappend's matters, here method is overwritten
513+ -- NOTE The order of 'mappend's matters, here method is overwritten
475− -- first and 'options' take effect last. In particular, this means
514+ -- first and 'options' take effect last. In particular, this means
476− -- that 'options' can overwrite things set by other request
515+ -- that 'options' can overwrite things set by other request
477− -- components, which is useful for setting port number,
516+ -- components, which is useful for setting port number,
478− -- "Content-Type" header, etc.
517+ -- "Content-Type" header, etc.
479− nubHeaders <>
518+ nubHeaders
480− getRequestMod options <>
519+ <> getRequestMod options
481− getRequestMod config <>
520+ <> getRequestMod config
482− getRequestMod (Womb body :: Womb "body" body) <>
521+ <> getRequestMod (Womb body :: Womb "body" body)
483− getRequestMod url <>
522+ <> getRequestMod url
484− getRequestMod (Womb method :: Womb "method" method)
523+ <> getRequestMod (Womb method :: Womb "method" method)
485 request <- finalizeRequest options request'
524 request <- finalizeRequest options request'
486 withReqManager (m request)
525 withReqManager (m request)
488-- | Perform an action using the global implicit 'L.Manager' that the rest
527-- | Perform an action using the global implicit 'L.Manager' that the rest
489-- of the library uses. This allows to reuse connections that the
528-- of the library uses. This allows to reuse connections that the
490-- 'L.Manager' controls.
529-- 'L.Manager' controls.
492withReqManager :: MonadIO m => (L.Manager -> m a) -> m a
530withReqManager :: MonadIO m => (L.Manager -> m a) -> m a
493withReqManager m = liftIO (readIORef globalManager) >>= m
531withReqManager m = liftIO (readIORef globalManager) >>= m
@@ -503,14 +541,14 @@ withReqManager m = liftIO (readIORef globalManager) >>= m
503-- manager. From that moment on the 'IORef' will be just reused—exactly the
541-- manager. From that moment on the 'IORef' will be just reused—exactly the
504-- behavior we want here in order to maximize connection sharing. GHC could
542-- behavior we want here in order to maximize connection sharing. GHC could
505-- spoil the plan by inlining the definition, hence the @NOINLINE@ pragma.
543-- spoil the plan by inlining the definition, hence the @NOINLINE@ pragma.
507globalManager :: IORef L.Manager
544globalManager :: IORef L.Manager
508globalManager = unsafePerformIO $ do
545globalManager = unsafePerformIO $ do
509 context <- NC.initConnectionContext
546 context <- NC.initConnectionContext
510− let settings = L.mkManagerSettingsContext
548+ L.mkManagerSettingsContext
511− (Just context)
549+ (Just context)
512− (NC.TLSSettingsSimple False False False)
550+ (NC.TLSSettingsSimple False False False)
514 manager <- L.newManager settings
552 manager <- L.newManager settings
515 newIORef manager
553 newIORef manager
516{-# NOINLINE globalManager #-}
554{-# NOINLINE globalManager #-}
@@ -532,15 +570,12 @@ globalManager = unsafePerformIO $ do
532-- | A type class for monads that support performing HTTP requests.
570-- | A type class for monads that support performing HTTP requests.
533-- Typically, you only need to define the 'handleHttpException' method
571-- Typically, you only need to define the 'handleHttpException' method
534-- unless you want to tweak 'HttpConfig'.
572-- unless you want to tweak 'HttpConfig'.
536class MonadIO m => MonadHttp m where
573class MonadIO m => MonadHttp m where
538 -- | This method describes how to deal with 'HttpException' that was
574 -- | This method describes how to deal with 'HttpException' that was
539 -- caught by the library. One option is to re-throw it if you are OK with
575 -- caught by the library. One option is to re-throw it if you are OK with
540 -- exceptions, but if you prefer working with something like
576 -- exceptions, but if you prefer working with something like
541 -- 'Control.Monad.Except.MonadError', this is the right place to pass it to
577 -- 'Control.Monad.Except.MonadError', this is the right place to pass it to
542 -- 'Control.Monad.Except.throwError'.
578 -- 'Control.Monad.Except.throwError'.
544 handleHttpException :: HttpException -> m a
579 handleHttpException :: HttpException -> m a
546 -- | Return 'HttpConfig' to be used when performing HTTP requests. Default
581 -- | Return 'HttpConfig' to be used when performing HTTP requests. Default
@@ -549,32 +584,24 @@ class MonadIO m => MonadHttp m where
549 -- 'getHttpConfig' is to return some hard-coded value, or a value
584 -- 'getHttpConfig' is to return some hard-coded value, or a value
550 -- extracted from 'Control.Monad.Reader.MonadReader' if a more flexible
585 -- extracted from 'Control.Monad.Reader.MonadReader' if a more flexible
551 -- approach to configuration is desirable.
586 -- approach to configuration is desirable.
553 getHttpConfig :: m HttpConfig
587 getHttpConfig :: m HttpConfig
554 getHttpConfig = return defaultHttpConfig
588 getHttpConfig = return defaultHttpConfig
556-- | 'HttpConfig' contains general and default settings to be used when
590-- | 'HttpConfig' contains general and default settings to be used when
557-- making HTTP requests.
591-- making HTTP requests.
559data HttpConfig = HttpConfig
592data HttpConfig = HttpConfig
560− { httpConfigProxy :: Maybe L.Proxy
561− -- ^ Proxy to use. By default values of @HTTP_PROXY@ and @HTTPS_PROXY@
593+ { -- | Proxy to use. By default values of @HTTP_PROXY@ and @HTTPS_PROXY@
562 -- environment variables are respected, this setting overwrites them.
594 -- environment variables are respected, this setting overwrites them.
563 -- Default value: 'Nothing'.
595 -- Default value: 'Nothing'.
564− , httpConfigRedirectCount :: Int
596+ httpConfigProxy :: Maybe L.Proxy,
565− -- ^ How many redirects to follow when getting a resource. Default
597+ -- | How many redirects to follow when getting a resource. Default
566 -- value: 10.
598 -- value: 10.
567− , httpConfigAltManager :: Maybe L.Manager
599+ httpConfigRedirectCount :: Int,
568− -- ^ Alternative 'L.Manager' to use. 'Nothing' (default value) means
600+ -- | Alternative 'L.Manager' to use. 'Nothing' (default value) means
569 -- that the default implicit manager will be used (that's what you want
601 -- that the default implicit manager will be used (that's what you want
570 -- in 99% of cases).
602 -- in 99% of cases).
571− , httpConfigCheckResponse
603+ httpConfigAltManager :: Maybe L.Manager,
576− -> Maybe L.HttpExceptionContent
577− -- ^ Function to check the response immediately after receiving the
604+ -- | Function to check the response immediately after receiving the
578 -- status and headers, before streaming of response body. The third
605 -- status and headers, before streaming of response body. The third
579 -- argument is the beginning of response body (typically first 1024
606 -- argument is the beginning of response body (typically first 1024
580 -- bytes). This is used for throwing exceptions on non-success status
607 -- bytes). This is used for throwing exceptions on non-success status
@@ -596,67 +623,77 @@ data HttpConfig = HttpConfig
596 -- /1.0.0/.
623 -- /1.0.0/.
598 -- @since 0.3.0
625 -- @since 0.3.0
599− , httpConfigRetryPolicy :: RetryPolicyM IO
626+ httpConfigCheckResponse ::
631+ Maybe L.HttpExceptionContent,
600− -- ^ The retry policy to use for request retrying. By default 'def' is
632+ -- | The retry policy to use for request retrying. By default 'def' is
601 -- used (see 'RetryPolicyM').
633 -- used (see 'RetryPolicyM').
603 -- __Note__: signature of this function was changed in the version
635 -- __Note__: signature of this function was changed in the version
604 -- /1.0.0/.
636 -- /1.0.0/.
606 -- @since 0.3.0
638 -- @since 0.3.0
607− , httpConfigRetryJudge :: forall b. RetryStatus -> L.Response b -> Bool
639+ httpConfigRetryPolicy :: RetryPolicyM IO,
608− -- ^ The function is used to decide whether to retry a request. 'True'
640+ -- | The function is used to decide whether to retry a request. 'True'
609 -- means that the request should be retried.
641 -- means that the request should be retried.
611 -- __Note__: signature of this function was changed in the version
643 -- __Note__: signature of this function was changed in the version
612 -- /1.0.0/.
644 -- /1.0.0/.
614 -- @since 0.3.0
646 -- @since 0.3.0
647+ httpConfigRetryJudge :: forall b. RetryStatus -> L.Response b -> Bool
615− } deriving Typeable
649+ deriving (Typeable)
617-- | Default value of 'HttpConfig'.
651-- | Default value of 'HttpConfig'.
619-- @since 2.0.0
653-- @since 2.0.0
621defaultHttpConfig :: HttpConfig
654defaultHttpConfig :: HttpConfig
622−defaultHttpConfig = HttpConfig
655+defaultHttpConfig =
623− { httpConfigProxy = Nothing
657+ { httpConfigProxy = Nothing,
624− , httpConfigRedirectCount = 10
658+ httpConfigRedirectCount = 10,
625− , httpConfigAltManager = Nothing
659+ httpConfigAltManager = Nothing,
626− , httpConfigCheckResponse = \_ response preview ->
660+ httpConfigCheckResponse = \_ response preview ->
627− let scode = statusCode response
661+ let scode = statusCode response
628− in if 200 <= scode && scode < 300
662+ in if 200 <= scode && scode < 300
629− then Nothing
663+ then Nothing
630− else Just (L.StatusCodeException (void response) preview)
664+ else Just (L.StatusCodeException (void response) preview),
631− , httpConfigRetryPolicy = retryPolicyDefault
665+ httpConfigRetryPolicy = retryPolicyDefault,
632− , httpConfigRetryJudge = \_ response ->
666+ httpConfigRetryJudge = \_ response ->
633− statusCode response `elem`
667+ statusCode response
634− [ 408 -- Request timeout
668+ `elem` [ 408, -- Request timeout
635− , 504 -- Gateway timeout
669+ 504, -- Gateway timeout
636− , 524 -- A timeout occurred
670+ 524, -- A timeout occurred
637− , 598 -- (Informal convention) Network read timeout error
671+ 598, -- (Informal convention) Network read timeout error
638− , 599 -- (Informal convention) Network connect timeout error
672+ 599 -- (Informal convention) Network connect timeout error
642 statusCode = Y.statusCode . L.responseStatus
676 statusCode = Y.statusCode . L.responseStatus
644instance RequestComponent HttpConfig where
678instance RequestComponent HttpConfig where
645 getRequestMod HttpConfig {..} = Endo $ \x ->
679 getRequestMod HttpConfig {..} = Endo $ \x ->
646− x { L.proxy = httpConfigProxy
681+ { L.proxy = httpConfigProxy,
647− , L.redirectCount = httpConfigRedirectCount
682+ L.redirectCount = httpConfigRedirectCount,
648− , LI.requestManagerOverride = httpConfigAltManager }
683+ LI.requestManagerOverride = httpConfigAltManager
650-- | A monad that allows to run 'req' in any 'IO'-enabled monad without
686-- | A monad that allows to run 'req' in any 'IO'-enabled monad without
651-- having to define new instances.
687-- having to define new instances.
653-- @since 0.4.0
689-- @since 0.4.0
655newtype Req a = Req (ReaderT HttpConfig IO a)
690newtype Req a = Req (ReaderT HttpConfig IO a)
656− deriving ( Functor
691+ deriving
657− , Applicative
693+ Applicative,
659− , MonadIO )
695+ MonadIO
661instance MonadBase IO Req where
698instance MonadBase IO Req where
662 liftBase = liftIO
699 liftBase = liftIO
@@ -665,22 +702,24 @@ instance MonadBaseControl IO Req where
665 type StM Req a = a
702 type StM Req a = a
666 liftBaseWith f = Req . ReaderT $ \r -> f (runReq r)
703 liftBaseWith f = Req . ReaderT $ \r -> f (runReq r)
667 {-# INLINEABLE liftBaseWith #-}
704 {-# INLINEABLE liftBaseWith #-}
668− restoreM = Req . ReaderT . const . return
705+ restoreM = Req . ReaderT . const . return
669 {-# INLINEABLE restoreM #-}
706 {-# INLINEABLE restoreM #-}
671instance MonadHttp Req where
708instance MonadHttp Req where
672 handleHttpException = Req . lift . throwIO
709 handleHttpException = Req . lift . throwIO
673− getHttpConfig = Req ask
710+ getHttpConfig = Req ask
675-- | Run a computation in the 'Req' monad with the given 'HttpConfig'. In
712-- | Run a computation in the 'Req' monad with the given 'HttpConfig'. In
676-- case of exceptional situation an 'HttpException' will be thrown.
713-- case of exceptional situation an 'HttpException' will be thrown.
678-- @since 0.4.0
715-- @since 0.4.0
680−runReq :: MonadIO m
717+ MonadIO m =>
681− => HttpConfig -- ^ 'HttpConfig' to use
718+ -- | 'HttpConfig' to use
682− -> Req a -- ^ Computation to run
720+ -- | Computation to run
684runReq config (Req m) = liftIO (runReaderT m config)
723runReq config (Req m) = liftIO (runReaderT m config)
686----------------------------------------------------------------------------
725----------------------------------------------------------------------------
@@ -696,7 +735,6 @@ runReq config (Req m) = liftIO (runReaderT m config)
696-- define a new method that will works seamlessly, see 'HttpMethod'.
735-- define a new method that will works seamlessly, see 'HttpMethod'.
698-- | 'GET' method.
737-- | 'GET' method.
700data GET = GET
738data GET = GET
702instance HttpMethod GET where
740instance HttpMethod GET where
@@ -704,7 +742,6 @@ instance HttpMethod GET where
704 httpMethodName Proxy = Y.methodGet
742 httpMethodName Proxy = Y.methodGet
706-- | 'POST' method.
744-- | 'POST' method.
708data POST = POST
745data POST = POST
710instance HttpMethod POST where
747instance HttpMethod POST where
@@ -712,7 +749,6 @@ instance HttpMethod POST where
712 httpMethodName Proxy = Y.methodPost
749 httpMethodName Proxy = Y.methodPost
714-- | 'HEAD' method.
751-- | 'HEAD' method.
716data HEAD = HEAD
752data HEAD = HEAD
718instance HttpMethod HEAD where
754instance HttpMethod HEAD where
@@ -720,7 +756,6 @@ instance HttpMethod HEAD where
720 httpMethodName Proxy = Y.methodHead
756 httpMethodName Proxy = Y.methodHead
722-- | 'PUT' method.
758-- | 'PUT' method.
724data PUT = PUT
759data PUT = PUT
726instance HttpMethod PUT where
761instance HttpMethod PUT where
@@ -731,7 +766,6 @@ instance HttpMethod PUT where
731-- 'DELETE' requests, as it should be. However some APIs may expect 'DELETE'
766-- 'DELETE' requests, as it should be. However some APIs may expect 'DELETE'
732-- requests to have bodies, in that case define your own variation of
767-- requests to have bodies, in that case define your own variation of
733-- 'DELETE' method and allow it to have a body.
768-- 'DELETE' method and allow it to have a body.
735data DELETE = DELETE
769data DELETE = DELETE
737instance HttpMethod DELETE where
771instance HttpMethod DELETE where
@@ -739,7 +773,6 @@ instance HttpMethod DELETE where
739 httpMethodName Proxy = Y.methodDelete
773 httpMethodName Proxy = Y.methodDelete
741-- | 'TRACE' method.
775-- | 'TRACE' method.
743data TRACE = TRACE
776data TRACE = TRACE
745instance HttpMethod TRACE where
778instance HttpMethod TRACE where
@@ -747,7 +780,6 @@ instance HttpMethod TRACE where
747 httpMethodName Proxy = Y.methodTrace
780 httpMethodName Proxy = Y.methodTrace
749-- | 'CONNECT' method.
782-- | 'CONNECT' method.
751data CONNECT = CONNECT
783data CONNECT = CONNECT
753instance HttpMethod CONNECT where
785instance HttpMethod CONNECT where
@@ -755,7 +787,6 @@ instance HttpMethod CONNECT where
755 httpMethodName Proxy = Y.methodConnect
787 httpMethodName Proxy = Y.methodConnect
757-- | 'OPTIONS' method.
789-- | 'OPTIONS' method.
759data OPTIONS = OPTIONS
790data OPTIONS = OPTIONS
761instance HttpMethod OPTIONS where
792instance HttpMethod OPTIONS where
@@ -763,7 +794,6 @@ instance HttpMethod OPTIONS where
763 httpMethodName Proxy = Y.methodOptions
794 httpMethodName Proxy = Y.methodOptions
765-- | 'PATCH' method.
796-- | 'PATCH' method.
767data PATCH = PATCH
797data PATCH = PATCH
769instance HttpMethod PATCH where
799instance HttpMethod PATCH where
@@ -778,23 +808,19 @@ instance HttpMethod PATCH where
778-- > instance HttpMethod COPY where
808-- > instance HttpMethod COPY where
779-- > type AllowsBody COPY = 'CanHaveBody
809-- > type AllowsBody COPY = 'CanHaveBody
780-- > httpMethodName Proxy = "COPY"
810-- > httpMethodName Proxy = "COPY"
782class HttpMethod a where
811class HttpMethod a where
784 -- | Type function 'AllowsBody' returns a type of kind 'CanHaveBody' which
812 -- | Type function 'AllowsBody' returns a type of kind 'CanHaveBody' which
785 -- tells the rest of the library whether the method can have body or not.
813 -- tells the rest of the library whether the method can have body or not.
786 -- We use the special type 'CanHaveBody' lifted to the kind level instead
814 -- We use the special type 'CanHaveBody' lifted to the kind level instead
787 -- of 'Bool' to get more user-friendly compiler messages.
815 -- of 'Bool' to get more user-friendly compiler messages.
789 type AllowsBody a :: CanHaveBody
816 type AllowsBody a :: CanHaveBody
791 -- | Return name of the method as a 'ByteString'.
818 -- | Return name of the method as a 'ByteString'.
793 httpMethodName :: Proxy a -> ByteString
819 httpMethodName :: Proxy a -> ByteString
795instance HttpMethod method => RequestComponent (Womb "method" method) where
821instance HttpMethod method => RequestComponent (Womb "method" method) where
796 getRequestMod _ = Endo $ \x ->
822 getRequestMod _ = Endo $ \x ->
797− x { L.method = httpMethodName (Proxy :: Proxy method) }
823+ x {L.method = httpMethodName (Proxy :: Proxy method)}
799----------------------------------------------------------------------------
825----------------------------------------------------------------------------
800-- Request—URL
826-- Request—URL
@@ -832,34 +858,31 @@ instance HttpMethod method => RequestComponent (Womb "method" method) where
833-- > https "юникод.рф"
859-- > https "юникод.рф"
834-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
860-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
836data Url (scheme :: Scheme) = Url Scheme (NonEmpty Text)
861data Url (scheme :: Scheme) = Url Scheme (NonEmpty Text)
837 -- NOTE The second value is the path segments in reversed order.
862 -- NOTE The second value is the path segments in reversed order.
838 deriving (Eq, Ord, Show, Data, Typeable, Generic)
863 deriving (Eq, Ord, Show, Data, Typeable, Generic)
840-- | Given host name, produce a 'Url' which has “http” as its scheme and
865-- | Given host name, produce a 'Url' which has “http” as its scheme and
841-- empty path. This also sets port to @80@.
866-- empty path. This also sets port to @80@.
843http :: Text -> Url 'Http
867http :: Text -> Url 'Http
844http = Url Http . pure
868http = Url Http . pure
846-- | Given host name, produce a 'Url' which has “https” as its scheme and
870-- | Given host name, produce a 'Url' which has “https” as its scheme and
847-- empty path. This also sets port to @443@.
871-- empty path. This also sets port to @443@.
849https :: Text -> Url 'Https
872https :: Text -> Url 'Https
850https = Url Https . pure
873https = Url Https . pure
852-- | Grow given 'Url' appending a single path segment to it. Note that the
875-- | Grow given 'Url' appending a single path segment to it. Note that the
853-- path segment can be of any type that is an instance of 'ToHttpApiData'.
876-- path segment can be of any type that is an instance of 'ToHttpApiData'.
855infixl 5 /~
877infixl 5 /~
856(/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme
879(/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme
857Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
880Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
859-- | Type-constrained version of @('/~')@ to remove ambiguity in the cases
882-- | Type-constrained version of @('/~')@ to remove ambiguity in the cases
860-- when next URL piece is a 'Data.Text.Text' literal.
883-- when next URL piece is a 'Data.Text.Text' literal.
862infixl 5 /:
884infixl 5 /:
863(/:) :: Url scheme -> Text -> Url scheme
886(/:) :: Url scheme -> Text -> Url scheme
864(/:) = (/~)
887(/:) = (/~)
@@ -870,7 +893,6 @@ infixl 5 /:
870-- This function expects the scheme to be “http” and host to be present.
893-- This function expects the scheme to be “http” and host to be present.
872-- @since 3.0.0
895-- @since 3.0.0
874useHttpURI :: URI -> Maybe (Url 'Http, Option scheme)
896useHttpURI :: URI -> Maybe (Url 'Http, Option scheme)
875useHttpURI uri = do
897useHttpURI uri = do
876 guard (URI.uriScheme uri == Just [QQ.scheme|http|])
898 guard (URI.uriScheme uri == Just [QQ.scheme|http|])
@@ -884,7 +906,6 @@ useHttpURI uri = do
884-- | Just like 'useHttpURI', but expects the “https” scheme.
906-- | Just like 'useHttpURI', but expects the “https” scheme.
886-- @since 3.0.0
908-- @since 3.0.0
888useHttpsURI :: URI -> Maybe (Url 'Https, Option scheme)
909useHttpsURI :: URI -> Maybe (Url 'Https, Option scheme)
889useHttpsURI uri = do
910useHttpsURI uri = do
890 guard (URI.uriScheme uri == Just [QQ.scheme|https|])
911 guard (URI.uriScheme uri == Just [QQ.scheme|https|])
@@ -899,16 +920,17 @@ useHttpsURI uri = do
899-- is not known in advance.
920-- is not known in advance.
901-- @since 3.0.0
922-- @since 3.0.0
905− -> Maybe (Either (Url 'Http, Option scheme0)
927+ (Url 'Http, Option scheme0)
906− (Url 'Https, Option scheme1))
928+ (Url 'Https, Option scheme1)
907useURI uri =
930useURI uri =
908 (Left <$> useHttpURI uri) <|> (Right <$> useHttpsURI uri)
931 (Left <$> useHttpURI uri) <|> (Right <$> useHttpsURI uri)
910-- | An internal helper function to extract host from a 'URI'.
933-- | An internal helper function to extract host from a 'URI'.
912uriHost :: URI -> Maybe Text
934uriHost :: URI -> Maybe Text
913uriHost uri = case URI.uriAuthority uri of
935uriHost uri = case URI.uriAuthority uri of
914 Left _ -> Nothing
936 Left _ -> Nothing
@@ -916,14 +938,14 @@ uriHost uri = case URI.uriAuthority uri of
916 Just (URI.unRText authHost)
938 Just (URI.unRText authHost)
918-- | An internal helper function to extract 'Option's from a 'URI'.
940-- | An internal helper function to extract 'Option's from a 'URI'.
920uriOptions :: forall scheme. URI -> Option scheme
941uriOptions :: forall scheme. URI -> Option scheme
921−uriOptions uri = mconcat
942+uriOptions uri =
925− -- , fragment'
947+ -- , fragment'
928 (auth, port') =
950 (auth, port') =
929 case URI.uriAuthority uri of
951 case URI.uriAuthority uri of
@@ -934,34 +956,37 @@ uriOptions uri = mconcat
934 Just URI.UserInfo {..} ->
956 Just URI.UserInfo {..} ->
935 let username = T.encodeUtf8 (URI.unRText uiUsername)
957 let username = T.encodeUtf8 (URI.unRText uiUsername)
936 password = maybe "" (T.encodeUtf8 . URI.unRText) uiPassword
958 password = maybe "" (T.encodeUtf8 . URI.unRText) uiPassword
937− in basicAuthUnsafe username password
959+ in basicAuthUnsafe username password
938 port0 = case authPort of
960 port0 = case authPort of
939 Nothing -> mempty
961 Nothing -> mempty
940 Just port'' -> port (fromIntegral port'')
962 Just port'' -> port (fromIntegral port'')
941− in (auth0, port0)
963+ in (auth0, port0)
943 let liftQueryParam = \case
965 let liftQueryParam = \case
944 URI.QueryFlag t -> queryFlag (URI.unRText t)
966 URI.QueryFlag t -> queryFlag (URI.unRText t)
945 URI.QueryParam k v -> URI.unRText k =: URI.unRText v
967 URI.QueryParam k v -> URI.unRText k =: URI.unRText v
946− in mconcat (liftQueryParam <$> URI.uriQuery uri)
968+ in mconcat (liftQueryParam <$> URI.uriQuery uri)
947− -- TODO Blocked on upstream: https://github.com/snoyberg/http-client/issues/424
970+-- TODO Blocked on upstream: https://github.com/snoyberg/http-client/issues/424
948− -- fragment' =
971+-- fragment' =
949− -- case URI.uriFragment uri of
972+-- case URI.uriFragment uri of
950− -- Nothing -> mempty
973+-- Nothing -> mempty
951− -- Just fragment'' -> fragment (URI.unRText fragment'')
974+-- Just fragment'' -> fragment (URI.unRText fragment'')
953instance RequestComponent (Url scheme) where
976instance RequestComponent (Url scheme) where
954 getRequestMod (Url scheme segments) = Endo $ \x ->
977 getRequestMod (Url scheme segments) = Endo $ \x ->
955− let (host :| path) = NE.reverse segments in
978+ let (host :| path) = NE.reverse segments
956− x { L.secure = case scheme of
980+ { L.secure = case scheme of
957− Http -> False
981+ Http -> False
958− Https -> True
982+ Https -> True,
959− , L.port = case scheme of
983+ L.port = case scheme of
960− Http -> 80
984+ Http -> 80
961− Https -> 443
985+ Https -> 443,
962− , L.host = Y.urlEncode False (T.encodeUtf8 host)
986+ L.host = Y.urlEncode False (T.encodeUtf8 host),
963− , L.path =
987+ L.path =
964− (BL.toStrict . BB.toLazyByteString . Y.encodePathSegments) path }
988+ (BL.toStrict . BB.toLazyByteString . Y.encodePathSegments) path
966----------------------------------------------------------------------------
991----------------------------------------------------------------------------
967-- Request—Body
992-- Request—Body
@@ -979,7 +1004,6 @@ instance RequestComponent (Url scheme) where
979-- only type for which 'ProvidesBody' returns 'NoBody'.
1004-- only type for which 'ProvidesBody' returns 'NoBody'.
981-- Using of this body option does not set the @Content-Type@ header.
1006-- Using of this body option does not set the @Content-Type@ header.
983data NoReqBody = NoReqBody
1007data NoReqBody = NoReqBody
985instance HttpBody NoReqBody where
1009instance HttpBody NoReqBody where
@@ -992,7 +1016,6 @@ instance HttpBody NoReqBody where
993-- This body option sets the @Content-Type@ header to @\"application/json;
1017-- This body option sets the @Content-Type@ header to @\"application/json;
994-- charset=utf-8\"@ value.
1018-- charset=utf-8\"@ value.
996newtype ReqBodyJson a = ReqBodyJson a
1019newtype ReqBodyJson a = ReqBodyJson a
998instance ToJSON a => HttpBody (ReqBodyJson a) where
1021instance ToJSON a => HttpBody (ReqBodyJson a) where
@@ -1003,7 +1026,6 @@ instance ToJSON a => HttpBody (ReqBodyJson a) where
1003-- the file size does not change during the streaming.
1026-- the file size does not change during the streaming.
1005-- Using of this body option does not set the @Content-Type@ header.
1028-- Using of this body option does not set the @Content-Type@ header.
1007newtype ReqBodyFile = ReqBodyFile FilePath
1029newtype ReqBodyFile = ReqBodyFile FilePath
1009instance HttpBody ReqBodyFile where
1031instance HttpBody ReqBodyFile where
@@ -1013,7 +1035,6 @@ instance HttpBody ReqBodyFile where
1013-- | HTTP request body represented by a strict 'ByteString'.
1035-- | HTTP request body represented by a strict 'ByteString'.
1015-- Using of this body option does not set the @Content-Type@ header.
1037-- Using of this body option does not set the @Content-Type@ header.
1017newtype ReqBodyBs = ReqBodyBs ByteString
1038newtype ReqBodyBs = ReqBodyBs ByteString
1019instance HttpBody ReqBodyBs where
1040instance HttpBody ReqBodyBs where
@@ -1022,7 +1043,6 @@ instance HttpBody ReqBodyBs where
1022-- | HTTP request body represented by a lazy 'BL.ByteString'.
1043-- | HTTP request body represented by a lazy 'BL.ByteString'.
1024-- Using of this body option does not set the @Content-Type@ header.
1045-- Using of this body option does not set the @Content-Type@ header.
1026newtype ReqBodyLbs = ReqBodyLbs BL.ByteString
1046newtype ReqBodyLbs = ReqBodyLbs BL.ByteString
1028instance HttpBody ReqBodyLbs where
1048instance HttpBody ReqBodyLbs where
@@ -1037,7 +1057,6 @@ instance HttpBody ReqBodyLbs where
1038-- This body option sets the @Content-Type@ header to
1058-- This body option sets the @Content-Type@ header to
1039-- @\"application/x-www-form-urlencoded\"@ value.
1059-- @\"application/x-www-form-urlencoded\"@ value.
1041newtype ReqBodyUrlEnc = ReqBodyUrlEnc FormUrlEncodedParam
1060newtype ReqBodyUrlEnc = ReqBodyUrlEnc FormUrlEncodedParam
1043instance HttpBody ReqBodyUrlEnc where
1062instance HttpBody ReqBodyUrlEnc where
@@ -1047,7 +1066,6 @@ instance HttpBody ReqBodyUrlEnc where
1048-- | An opaque monoidal value that allows to collect URL-encoded parameters
1067-- | An opaque monoidal value that allows to collect URL-encoded parameters
1049-- to be wrapped in 'ReqBodyUrlEnc'.
1068-- to be wrapped in 'ReqBodyUrlEnc'.
1051newtype FormUrlEncodedParam = FormUrlEncodedParam [(Text, Maybe Text)]
1069newtype FormUrlEncodedParam = FormUrlEncodedParam [(Text, Maybe Text)]
1052 deriving (Semigroup, Monoid)
1070 deriving (Semigroup, Monoid)
@@ -1083,7 +1101,6 @@ instance QueryParam FormUrlEncodedParam where
1083-- > bsResponse
1101-- > bsResponse
1084-- > mempty
1102-- > mempty
1085-- > liftIO $ print (responseBody response)
1103-- > liftIO $ print (responseBody response)
1087data ReqBodyMultipart = ReqBodyMultipart ByteString LI.RequestBody
1104data ReqBodyMultipart = ReqBodyMultipart ByteString LI.RequestBody
1089instance HttpBody ReqBodyMultipart where
1106instance HttpBody ReqBodyMultipart where
@@ -1094,36 +1111,30 @@ instance HttpBody ReqBodyMultipart where
1094-- | Create 'ReqBodyMultipart' request body from a collection of 'LM.Part's.
1111-- | Create 'ReqBodyMultipart' request body from a collection of 'LM.Part's.
1096-- @since 0.2.0
1113-- @since 0.2.0
1098reqBodyMultipart :: MonadIO m => [LM.Part] -> m ReqBodyMultipart
1114reqBodyMultipart :: MonadIO m => [LM.Part] -> m ReqBodyMultipart
1099reqBodyMultipart parts = liftIO $ do
1115reqBodyMultipart parts = liftIO $ do
1100 boundary <- LM.webkitBoundary
1116 boundary <- LM.webkitBoundary
1101− body <- LM.renderParts boundary parts
1117+ body <- LM.renderParts boundary parts
1102 return (ReqBodyMultipart boundary body)
1118 return (ReqBodyMultipart boundary body)
1104-- | A type class for things that can be interpreted as an HTTP
1120-- | A type class for things that can be interpreted as an HTTP
1105-- 'L.RequestBody'.
1121-- 'L.RequestBody'.
1107class HttpBody body where
1122class HttpBody body where
1109 -- | How to get actual 'L.RequestBody'.
1123 -- | How to get actual 'L.RequestBody'.
1111 getRequestBody :: body -> L.RequestBody
1124 getRequestBody :: body -> L.RequestBody
1113 -- | This method allows us to optionally specify the value of
1126 -- | This method allows us to optionally specify the value of
1114 -- @Content-Type@ header that should be used with particular body option.
1127 -- @Content-Type@ header that should be used with particular body option.
1115 -- By default it returns 'Nothing' and so @Content-Type@ is not set.
1128 -- By default it returns 'Nothing' and so @Content-Type@ is not set.
1117 getRequestContentType :: body -> Maybe ByteString
1129 getRequestContentType :: body -> Maybe ByteString
1118 getRequestContentType = const Nothing
1130 getRequestContentType = const Nothing
1120-- | The type function recognizes 'NoReqBody' as having 'NoBody', while any
1132-- | The type function recognizes 'NoReqBody' as having 'NoBody', while any
1121-- other body option 'CanHaveBody'. This forces the user to use 'NoReqBody'
1133-- other body option 'CanHaveBody'. This forces the user to use 'NoReqBody'
1122-- with 'GET' method and other methods that should not have body.
1134-- with 'GET' method and other methods that should not have body.
1124type family ProvidesBody body :: CanHaveBody where
1135type family ProvidesBody body :: CanHaveBody where
1125 ProvidesBody NoReqBody = 'NoBody
1136 ProvidesBody NoReqBody = 'NoBody
1126− ProvidesBody body = 'CanHaveBody
1137+ ProvidesBody body = 'CanHaveBody
1128-- | This type function allows any HTTP body if method says it
1139-- | This type function allows any HTTP body if method says it
1129-- 'CanHaveBody'. When the method says it should have 'NoBody', the only
1140-- 'CanHaveBody'. When the method says it should have 'NoBody', the only
@@ -1131,24 +1142,29 @@ type family ProvidesBody body :: CanHaveBody where
1132-- __Note__: users of GHC 8.0.1 and later will see a slightly more friendly
1143-- __Note__: users of GHC 8.0.1 and later will see a slightly more friendly
1133-- error message when method does not allow a body and body is provided.
1144-- error message when method does not allow a body and body is provided.
1135−type family HttpBodyAllowed
1145+type family
1136− (allowsBody :: CanHaveBody)
1147+ (allowsBody :: CanHaveBody)
1137− (providesBody :: CanHaveBody) :: Constraint where
1148+ (providesBody :: CanHaveBody) ::
1138− HttpBodyAllowed 'NoBody 'NoBody = ()
1151+ HttpBodyAllowed 'NoBody 'NoBody = ()
1139− HttpBodyAllowed 'CanHaveBody body = ()
1152+ HttpBodyAllowed 'CanHaveBody body = ()
1140− HttpBodyAllowed 'NoBody 'CanHaveBody = TypeError
1153+ HttpBodyAllowed 'NoBody 'CanHaveBody =
1141− ('Text "This HTTP method does not allow attaching a request body.")
1155+ ('Text "This HTTP method does not allow attaching a request body.")
1143instance HttpBody body => RequestComponent (Womb "body" body) where
1157instance HttpBody body => RequestComponent (Womb "body" body) where
1144 getRequestMod (Womb body) = Endo $ \x ->
1158 getRequestMod (Womb body) = Endo $ \x ->
1145− x { L.requestBody = getRequestBody body
1160+ { L.requestBody = getRequestBody body,
1146− , L.requestHeaders =
1161+ L.requestHeaders =
1147− let old = L.requestHeaders x in
1162+ let old = L.requestHeaders x
1148− case getRequestContentType body of
1163+ in case getRequestContentType body of
1149− Nothing -> old
1164+ Nothing -> old
1150− Just contentType ->
1165+ Just contentType ->
1151− (Y.hContentType, contentType) : old }
1166+ (Y.hContentType, contentType) : old
1153----------------------------------------------------------------------------
1169----------------------------------------------------------------------------
1154-- Request—Optional parameters
1170-- Request—Optional parameters
@@ -1164,45 +1180,44 @@ instance HttpBody body => RequestComponent (Womb "body" body) where
1164-- | The opaque 'Option' type is a 'Monoid' you can use to pack collection
1180-- | The opaque 'Option' type is a 'Monoid' you can use to pack collection
1165-- of optional parameters like query parameters and headers. See sections
1181-- of optional parameters like query parameters and headers. See sections
1166-- below to learn which 'Option' primitives are available.
1182-- below to learn which 'Option' primitives are available.
1183+data Option (scheme :: Scheme)
1184+ = Option (Endo (Y.QueryText, L.Request)) (Maybe (L.Request -> IO L.Request))
1168−data Option (scheme :: Scheme) =
1169− Option (Endo (Y.QueryText, L.Request)) (Maybe (L.Request -> IO L.Request))
1170− -- NOTE 'QueryText' is just [(Text, Maybe Text)], we keep it along with
1186+-- NOTE 'QueryText' is just [(Text, Maybe Text)], we keep it along with
1171− -- Request to avoid appending to existing query string in request every
1187+-- Request to avoid appending to existing query string in request every
1172− -- time new parameter is added. Additional Maybe (L.Request -> IO
1188+-- time new parameter is added. Additional Maybe (L.Request -> IO
1173− -- L.Request) is a finalizer that will be applied after all other
1189+-- L.Request) is a finalizer that will be applied after all other
1174− -- transformations. This is for authentication methods that sign requests
1190+-- transformations. This is for authentication methods that sign requests
1175− -- based on data in Request.
1191+-- based on data in Request.
1177instance Semigroup (Option scheme) where
1193instance Semigroup (Option scheme) where
1178− Option er0 mr0 <> Option er1 mr1 = Option
1194+ Option er0 mr0 <> Option er1 mr1 =
1179− (er0 <> er1) (mr0 <|> mr1)
1196+ (er0 <> er1)
1181instance Monoid (Option scheme) where
1199instance Monoid (Option scheme) where
1182− mempty = Option mempty Nothing
1200+ mempty = Option mempty Nothing
1183 mappend = (<>)
1201 mappend = (<>)
1185-- | A helper to create an 'Option' that modifies only collection of query
1203-- | A helper to create an 'Option' that modifies only collection of query
1186-- parameters. This helper is not a part of the public API.
1204-- parameters. This helper is not a part of the public API.
1188withQueryParams :: (Y.QueryText -> Y.QueryText) -> Option scheme
1205withQueryParams :: (Y.QueryText -> Y.QueryText) -> Option scheme
1189withQueryParams f = Option (Endo (first f)) Nothing
1206withQueryParams f = Option (Endo (first f)) Nothing
1191-- | A helper to create an 'Option' that modifies only 'L.Request'. This
1208-- | A helper to create an 'Option' that modifies only 'L.Request'. This
1192-- helper is not a part of public API.
1209-- helper is not a part of public API.
1194withRequest :: (L.Request -> L.Request) -> Option scheme
1210withRequest :: (L.Request -> L.Request) -> Option scheme
1195withRequest f = Option (Endo (second f)) Nothing
1211withRequest f = Option (Endo (second f)) Nothing
1197instance RequestComponent (Option scheme) where
1213instance RequestComponent (Option scheme) where
1198 getRequestMod (Option f _) = Endo $ \x ->
1214 getRequestMod (Option f _) = Endo $ \x ->
1199 let (qparams, x') = appEndo f ([], x)
1215 let (qparams, x') = appEndo f ([], x)
1200− query = Y.renderQuery True (Y.queryTextToQuery qparams)
1216+ query = Y.renderQuery True (Y.queryTextToQuery qparams)
1201− in x' { L.queryString = query }
1217+ in x' {L.queryString = query}
1203-- | Finalize given 'L.Request' by applying a finalizer from the given
1219-- | Finalize given 'L.Request' by applying a finalizer from the given
1204-- 'Option' (if it has any).
1220-- 'Option' (if it has any).
1206finalizeRequest :: MonadIO m => Option scheme -> L.Request -> m L.Request
1221finalizeRequest :: MonadIO m => Option scheme -> L.Request -> m L.Request
1207finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
1222finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
@@ -1222,8 +1237,8 @@ finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
1222-- This operator is defined in terms of 'queryParam':
1237-- This operator is defined in terms of 'queryParam':
1224-- > name =: value = queryParam name (pure value)
1239-- > name =: value = queryParam name (pure value)
1226infix 7 =:
1240infix 7 =:
1227(=:) :: (QueryParam param, ToHttpApiData a) => Text -> a -> param
1242(=:) :: (QueryParam param, ToHttpApiData a) => Text -> a -> param
1228name =: value = queryParam name (pure value)
1243name =: value = queryParam name (pure value)
@@ -1236,7 +1251,6 @@ name =: value = queryParam name (pure value)
1236-- This operator is defined in terms of 'queryParam':
1251-- This operator is defined in terms of 'queryParam':
1238-- > queryFlag name = queryParam name (Nothing :: Maybe ())
1253-- > queryFlag name = queryParam name (Nothing :: Maybe ())
1240queryFlag :: QueryParam param => Text -> param
1254queryFlag :: QueryParam param => Text -> param
1241queryFlag name = queryParam name (Nothing :: Maybe ())
1255queryFlag name = queryParam name (Nothing :: Maybe ())
@@ -1244,14 +1258,11 @@ queryFlag name = queryParam name (Nothing :: Maybe ())
1244-- overloaded 'queryParam' is to be able to use it as an 'Option' and as a
1258-- overloaded 'queryParam' is to be able to use it as an 'Option' and as a
1245-- 'FormUrlEncodedParam' when constructing form URL encoded request bodies.
1259-- 'FormUrlEncodedParam' when constructing form URL encoded request bodies.
1246-- Having the same syntax for these cases seems natural and user-friendly.
1260-- Having the same syntax for these cases seems natural and user-friendly.
1248class QueryParam param where
1261class QueryParam param where
1250 -- | Create a query parameter with given name and value. If value is
1262 -- | Create a query parameter with given name and value. If value is
1251 -- 'Nothing', it won't be included at all (i.e. you create a flag this
1263 -- 'Nothing', it won't be included at all (i.e. you create a flag this
1252 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
1264 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
1253 -- method, because they are easier to read.
1265 -- method, because they are easier to read.
1255 queryParam :: ToHttpApiData a => Text -> Maybe a -> param
1266 queryParam :: ToHttpApiData a => Text -> Maybe a -> param
1257instance QueryParam (Option scheme) where
1268instance QueryParam (Option scheme) where
@@ -1265,20 +1276,20 @@ instance QueryParam (Option scheme) where
1265-- headers with the same names the leftmost header will win. This means, in
1276-- headers with the same names the leftmost header will win. This means, in
1266-- particular, that you cannot create a request with several headers of the
1277-- particular, that you cannot create a request with several headers of the
1267-- same name.
1278-- same name.
1269−header
1279+header ::
1270− :: ByteString -- ^ Header name
1280+ -- | Header name
1271− -> ByteString -- ^ Header value
1282+ -- | Header value
1272− -> Option scheme
1284+ Option scheme
1273header name value = withRequest (attachHeader name value)
1285header name value = withRequest (attachHeader name value)
1275-- | Attach a header with given name and content to a 'L.Request'.
1287-- | Attach a header with given name and content to a 'L.Request'.
1277-- @since 1.1.0
1289-- @since 1.1.0
1279attachHeader :: ByteString -> ByteString -> L.Request -> L.Request
1290attachHeader :: ByteString -> ByteString -> L.Request -> L.Request
1280attachHeader name value x =
1291attachHeader name value x =
1281− x { L.requestHeaders = (CI.mk name, value) : L.requestHeaders x }
1292+ x {L.requestHeaders = (CI.mk name, value) : L.requestHeaders x}
1283----------------------------------------------------------------------------
1294----------------------------------------------------------------------------
1284-- Request—Optional parameters—Cookies
1295-- Request—Optional parameters—Cookies
@@ -1291,10 +1302,9 @@ attachHeader name value x =
1292-- | Use the given 'L.CookieJar'. A 'L.CookieJar' can be obtained from a
1303-- | Use the given 'L.CookieJar'. A 'L.CookieJar' can be obtained from a
1293-- 'L.Response' record.
1304-- 'L.Response' record.
1295cookieJar :: L.CookieJar -> Option scheme
1305cookieJar :: L.CookieJar -> Option scheme
1296cookieJar jar = withRequest $ \x ->
1306cookieJar jar = withRequest $ \x ->
1297− x { L.cookieJar = Just jar }
1307+ x {L.cookieJar = Just jar}
1299----------------------------------------------------------------------------
1309----------------------------------------------------------------------------
1300-- Request—Optional parameters—Authentication
1310-- Request—Optional parameters—Authentication
@@ -1312,11 +1322,13 @@ cookieJar jar = withRequest $ \x ->
1312-- | The 'Option' adds basic authentication.
1322-- | The 'Option' adds basic authentication.
1314-- See also: <https://en.wikipedia.org/wiki/Basic_access_authentication>.
1324-- See also: <https://en.wikipedia.org/wiki/Basic_access_authentication>.
1316−basicAuth
1325+basicAuth ::
1317− :: ByteString -- ^ Username
1326+ -- | Username
1318− -> ByteString -- ^ Password
1327+ ByteString ->
1319− -> Option 'Https -- ^ Auth 'Option'
1330+ -- | Auth 'Option'
1320basicAuth = basicAuthUnsafe
1332basicAuth = basicAuthUnsafe
1322-- | An alternative to 'basicAuth' which works for any scheme. Note that
1334-- | An alternative to 'basicAuth' which works for any scheme. Note that
@@ -1324,41 +1336,52 @@ basicAuth = basicAuthUnsafe
1324-- attacks. Use 'basicAuth' instead unless you know what you are doing.
1336-- attacks. Use 'basicAuth' instead unless you know what you are doing.
1326-- @since 0.3.1
1338-- @since 0.3.1
1328−basicAuthUnsafe
1339+basicAuthUnsafe ::
1329− :: ByteString -- ^ Username
1340+ -- | Username
1330− -> ByteString -- ^ Password
1341+ ByteString ->
1331− -> Option scheme -- ^ Auth 'Option'
1345+ Option scheme
1332−basicAuthUnsafe username password = customAuth
1346+basicAuthUnsafe username password =
1333− (pure . L.applyBasicAuth username password)
1348+ (pure . L.applyBasicAuth username password)
1335-- | The 'Option' set basic proxy authentication header.
1350-- | The 'Option' set basic proxy authentication header.
1337-- @since 1.1.0
1352-- @since 1.1.0
1339−basicProxyAuth
1353+basicProxyAuth ::
1340− :: ByteString -- ^ Username
1354+ -- | Username
1341− -> ByteString -- ^ Password
1355+ ByteString ->
1342− -> Option scheme -- ^ Auth 'Option'
1358+ -- | Auth 'Option'
1343basicProxyAuth username password =
1360basicProxyAuth username password =
1344 withRequest (L.applyBasicProxyAuth username password)
1361 withRequest (L.applyBasicProxyAuth username password)
1346-- | The 'Option' adds OAuth1 authentication.
1363-- | The 'Option' adds OAuth1 authentication.
1348-- @since 0.2.0
1365-- @since 0.2.0
1350−oAuth1
1366+oAuth1 ::
1351− :: ByteString -- ^ Consumer token
1367+ -- | Consumer token
1352− -> ByteString -- ^ Consumer secret
1369+ -- | Consumer secret
1353− -> ByteString -- ^ OAuth token
1370+ ByteString ->
1354− -> ByteString -- ^ OAuth token secret
1373+ -- | OAuth token secret
1355− -> Option scheme -- ^ Auth 'Option'
1375+ -- | Auth 'Option'
1356oAuth1 consumerToken consumerSecret token tokenSecret =
1377oAuth1 consumerToken consumerSecret token tokenSecret =
1357 customAuth (OAuth.signOAuth app creds)
1378 customAuth (OAuth.signOAuth app creds)
1359− app = OAuth.newOAuth
1381+ OAuth.newOAuth
1360− { OAuth.oauthConsumerKey = consumerToken
1382+ { OAuth.oauthConsumerKey = consumerToken,
1361− , OAuth.oauthConsumerSecret = consumerSecret }
1383+ OAuth.oauthConsumerSecret = consumerSecret
1362 creds = OAuth.newCredential token tokenSecret
1385 creds = OAuth.newCredential token tokenSecret
1364-- | The 'Option' adds an OAuth2 bearer token. This is treated by many
1387-- | The 'Option' adds an OAuth2 bearer token. This is treated by many
@@ -1369,12 +1392,14 @@ oAuth1 consumerToken consumerSecret token tokenSecret =
1369-- > oAuth2Bearer token = header "Authorization" ("Bearer " <> token)
1392-- > oAuth2Bearer token = header "Authorization" ("Bearer " <> token)
1371-- See also: <https://en.wikipedia.org/wiki/OAuth>.
1394-- See also: <https://en.wikipedia.org/wiki/OAuth>.
1373−oAuth2Bearer
1395+oAuth2Bearer ::
1374− :: ByteString -- ^ Token
1397+ ByteString ->
1375− -> Option 'Https -- ^ Auth 'Option'
1398+ -- | Auth 'Option'
1376−oAuth2Bearer token = customAuth
1400+oAuth2Bearer token =
1377− (pure . attachHeader "Authorization" ("Bearer " <> token))
1402+ (pure . attachHeader "Authorization" ("Bearer " <> token))
1379-- | The 'Option' adds a not-quite-standard OAuth2 bearer token (that seems
1404-- | The 'Option' adds a not-quite-standard OAuth2 bearer token (that seems
1380-- to be used only by GitHub). This will be treated by whatever services
1405-- to be used only by GitHub). This will be treated by whatever services
@@ -1385,19 +1410,20 @@ oAuth2Bearer token = customAuth
1385-- > oAuth2Token token = header "Authorization" ("token" <> token)
1410-- > oAuth2Token token = header "Authorization" ("token" <> token)
1387-- See also: <https://developer.github.com/v3/oauth#3-use-the-access-token-to-access-the-api>.
1412-- See also: <https://developer.github.com/v3/oauth#3-use-the-access-token-to-access-the-api>.
1389−oAuth2Token
1413+oAuth2Token ::
1390− :: ByteString -- ^ Token
1415+ ByteString ->
1391− -> Option 'Https -- ^ Auth 'Option'
1416+ -- | Auth 'Option'
1392−oAuth2Token token = customAuth
1418+oAuth2Token token =
1393− (pure . attachHeader "Authorization" ("token " <> token))
1420+ (pure . attachHeader "Authorization" ("token " <> token))
1395-- | A helper to create custom authentication 'Option's. The given
1422-- | A helper to create custom authentication 'Option's. The given
1396-- 'IO'-enabled request transformation is applied after all other
1423-- 'IO'-enabled request transformation is applied after all other
1397-- modifications when constructing a request. Use wisely.
1424-- modifications when constructing a request. Use wisely.
1399-- @since 1.1.0
1426-- @since 1.1.0
1401customAuth :: (L.Request -> IO L.Request) -> Option scheme
1427customAuth :: (L.Request -> IO L.Request) -> Option scheme
1402customAuth = Option mempty . pure
1428customAuth = Option mempty . pure
@@ -1407,10 +1433,9 @@ customAuth = Option mempty . pure
1407-- | Specify the port to connect to explicitly. Normally, 'Url' you use
1433-- | Specify the port to connect to explicitly. Normally, 'Url' you use
1408-- determines the default port: @80@ for HTTP and @443@ for HTTPS. This
1434-- determines the default port: @80@ for HTTP and @443@ for HTTPS. This
1409-- 'Option' allows to choose an arbitrary port overwriting the defaults.
1435-- 'Option' allows to choose an arbitrary port overwriting the defaults.
1411port :: Int -> Option scheme
1436port :: Int -> Option scheme
1412port n = withRequest $ \x ->
1437port n = withRequest $ \x ->
1413− x { L.port = n }
1438+ x {L.port = n}
1415-- | This 'Option' controls whether gzipped data should be decompressed on
1440-- | This 'Option' controls whether gzipped data should be decompressed on
1416-- the fly. By default everything except for @\"application\/x-tar\"@ is
1441-- the fly. By default everything except for @\"application\/x-tar\"@ is
@@ -1421,38 +1446,38 @@ port n = withRequest $ \x ->
1421-- You can also choose to decompress everything like this:
1446-- You can also choose to decompress everything like this:
1423-- > decompress (const True)
1448-- > decompress (const True)
1425−decompress
1449+decompress ::
1426− :: (ByteString -> Bool) -- ^ Predicate that is given MIME type, it
1450+ -- | Predicate that is given MIME type, it
1427− -- returns 'True' when content should be decompressed on the fly.
1451+ -- returns 'True' when content should be decompressed on the fly.
1452+ (ByteString -> Bool) ->
1428− -> Option scheme
1453+ Option scheme
1429decompress f = withRequest $ \x ->
1454decompress f = withRequest $ \x ->
1430− x { L.decompress = f }
1455+ x {L.decompress = f}
1432-- | Specify the number of microseconds to wait for response. The default
1457-- | Specify the number of microseconds to wait for response. The default
1433-- value is 30 seconds (defined in 'L.ManagerSettings' of connection
1458-- value is 30 seconds (defined in 'L.ManagerSettings' of connection
1434-- 'L.Manager').
1459-- 'L.Manager').
1436−responseTimeout
1460+responseTimeout ::
1437− :: Int -- ^ Number of microseconds to wait
1461+ -- | Number of microseconds to wait
1438− -> Option scheme
1463+ Option scheme
1439responseTimeout n = withRequest $ \x ->
1464responseTimeout n = withRequest $ \x ->
1440− x { L.responseTimeout = LI.ResponseTimeoutMicro n }
1465+ x {L.responseTimeout = LI.ResponseTimeoutMicro n}
1442-- | HTTP version to send to the server, the default is HTTP 1.1.
1467-- | HTTP version to send to the server, the default is HTTP 1.1.
1444−httpVersion
1468+httpVersion ::
1445− :: Int -- ^ Major version number
1469+ -- | Major version number
1446− -> Int -- ^ Minor version number
1471+ -- | Minor version number
1447− -> Option scheme
1473+ Option scheme
1448httpVersion major minor = withRequest $ \x ->
1474httpVersion major minor = withRequest $ \x ->
1449− x { L.requestVersion = Y.HttpVersion major minor }
1475+ x {L.requestVersion = Y.HttpVersion major minor}
1451----------------------------------------------------------------------------
1477----------------------------------------------------------------------------
1452-- Response interpretations
1478-- Response interpretations
1454-- | Make a request and ignore the body of the response.
1480-- | Make a request and ignore the body of the response.
1456newtype IgnoreResponse = IgnoreResponse (L.Response ())
1481newtype IgnoreResponse = IgnoreResponse (L.Response ())
1458instance HttpResponse IgnoreResponse where
1483instance HttpResponse IgnoreResponse where
@@ -1462,7 +1487,6 @@ instance HttpResponse IgnoreResponse where
1463-- | Use this as the fourth argument of 'req' to specify that you want it to
1488-- | Use this as the fourth argument of 'req' to specify that you want it to
1464-- ignore the response body.
1489-- ignore the response body.
1466ignoreResponse :: Proxy IgnoreResponse
1490ignoreResponse :: Proxy IgnoreResponse
1467ignoreResponse = Proxy
1491ignoreResponse = Proxy
@@ -1470,7 +1494,6 @@ ignoreResponse = Proxy
1470-- 'handleHttpException' method of 'MonadHttp' instance corresponding to
1494-- 'handleHttpException' method of 'MonadHttp' instance corresponding to
1471-- monad in which you use 'req' will determine what to do in the case when
1495-- monad in which you use 'req' will determine what to do in the case when
1472-- parsing fails (the 'JsonHttpException' constructor will be used).
1496-- parsing fails (the 'JsonHttpException' constructor will be used).
1474newtype JsonResponse a = JsonResponse (L.Response a)
1497newtype JsonResponse a = JsonResponse (L.Response a)
1476instance FromJSON a => HttpResponse (JsonResponse a) where
1499instance FromJSON a => HttpResponse (JsonResponse a) where
@@ -1479,19 +1502,17 @@ instance FromJSON a => HttpResponse (JsonResponse a) where
1479 getHttpResponse r = do
1502 getHttpResponse r = do
1480 chunks <- L.brConsume (L.responseBody r)
1503 chunks <- L.brConsume (L.responseBody r)
1481 case A.eitherDecode (BL.fromChunks chunks) of
1504 case A.eitherDecode (BL.fromChunks chunks) of
1482− Left e -> throwIO (JsonHttpException e)
1505+ Left e -> throwIO (JsonHttpException e)
1483 Right x -> return $ JsonResponse (x <$ r)
1506 Right x -> return $ JsonResponse (x <$ r)
1484 acceptHeader Proxy = Just "application/json"
1507 acceptHeader Proxy = Just "application/json"
1486-- | Use this as the fourth argument of 'req' to specify that you want it to
1509-- | Use this as the fourth argument of 'req' to specify that you want it to
1487-- return the 'JsonResponse' interpretation.
1510-- return the 'JsonResponse' interpretation.
1489jsonResponse :: Proxy (JsonResponse a)
1511jsonResponse :: Proxy (JsonResponse a)
1490jsonResponse = Proxy
1512jsonResponse = Proxy
1492-- | Make a request and interpret the body of the response as a strict
1514-- | Make a request and interpret the body of the response as a strict
1493-- 'ByteString'.
1515-- 'ByteString'.
1495newtype BsResponse = BsResponse (L.Response ByteString)
1516newtype BsResponse = BsResponse (L.Response ByteString)
1497instance HttpResponse BsResponse where
1518instance HttpResponse BsResponse where
@@ -1503,13 +1524,11 @@ instance HttpResponse BsResponse where
1504-- | Use this as the fourth argument of 'req' to specify that you want to
1525-- | Use this as the fourth argument of 'req' to specify that you want to
1505-- interpret the response body as a strict 'ByteString'.
1526-- interpret the response body as a strict 'ByteString'.
1507bsResponse :: Proxy BsResponse
1527bsResponse :: Proxy BsResponse
1508bsResponse = Proxy
1528bsResponse = Proxy
1510-- | Make a request and interpret the body of the response as a lazy
1530-- | Make a request and interpret the body of the response as a lazy
1511-- 'BL.ByteString'.
1531-- 'BL.ByteString'.
1513newtype LbsResponse = LbsResponse (L.Response BL.ByteString)
1532newtype LbsResponse = LbsResponse (L.Response BL.ByteString)
1515instance HttpResponse LbsResponse where
1534instance HttpResponse LbsResponse where
@@ -1521,7 +1540,6 @@ instance HttpResponse LbsResponse where
1522-- | Use this as the fourth argument of 'req' to specify that you want to
1541-- | Use this as the fourth argument of 'req' to specify that you want to
1523-- interpret the response body as a lazy 'BL.ByteString'.
1542-- interpret the response body as a lazy 'BL.ByteString'.
1525lbsResponse :: Proxy LbsResponse
1543lbsResponse :: Proxy LbsResponse
1526lbsResponse = Proxy
1544lbsResponse = Proxy
@@ -1531,14 +1549,13 @@ lbsResponse = Proxy
1531-- | Fetch beginning of response and return it together with new
1549-- | Fetch beginning of response and return it together with new
1532-- @'L.Response' 'L.BodyReader'@ that can be passed to 'getHttpResponse' and
1550-- @'L.Response' 'L.BodyReader'@ that can be passed to 'getHttpResponse' and
1535−grabPreview
1552+grabPreview ::
1537− -- ^ How many bytes to fetch
1553+ -- | How many bytes to fetch
1555+ -- | Response with body reader inside
1538− -> L.Response L.BodyReader
1556+ L.Response L.BodyReader ->
1539− -- ^ Response with body reader inside
1557+ -- | Preview 'ByteString' and new response with body reader inside
1540− -> IO (ByteString, L.Response L.BodyReader)
1558+ IO (ByteString, L.Response L.BodyReader)
1541− -- ^ Preview 'ByteString' and new response with body reader inside
1542grabPreview nbytes r = do
1559grabPreview nbytes r = do
1543 let br = L.responseBody r
1560 let br = L.responseBody r
1544 (target, leftover, done) <- brReadN br nbytes
1561 (target, leftover, done) <- brReadN br nbytes
@@ -1561,18 +1578,17 @@ grabPreview nbytes r = do
1562 then return B.empty
1579 then return B.empty
1564− return (target, r { L.responseBody = br' })
1581+ return (target, r {L.responseBody = br'})
1566-- | Consume N bytes from 'L.BodyReader', return the target chunk, the
1583-- | Consume N bytes from 'L.BodyReader', return the target chunk, the
1567-- leftover (may be empty), and whether we're done consuming the body.
1584-- leftover (may be empty), and whether we're done consuming the body.
1569−brReadN
1585+brReadN ::
1571− -- ^ Body reader to stream from
1586+ -- | Body reader to stream from
1572− -> Int
1587+ L.BodyReader ->
1573− -- ^ How many bytes to consume
1588+ -- | How many bytes to consume
1574− -> IO (ByteString, ByteString, Bool)
1589+ Int ->
1575− -- ^ Target chunk, the leftover, whether we're done
1590+ -- | Target chunk, the leftover, whether we're done
1591+ IO (ByteString, ByteString, Bool)
1576brReadN br n = go 0 id id
1592brReadN br n = go 0 id id
1578 go !tlen t l = do
1594 go !tlen t l = do
@@ -1581,9 +1597,9 @@ brReadN br n = go 0 id id
1581 then return (r t, r l, True)
1597 then return (r t, r l, True)
1583 let (target, leftover) = B.splitAt (n - tlen) chunk
1599 let (target, leftover) = B.splitAt (n - tlen) chunk
1584− tlen' = B.length target
1600+ tlen' = B.length target
1585− t' = t . (target:)
1601+ t' = t . (target :)
1586− l' = l . (leftover:)
1602+ l' = l . (leftover :)
1587 if tlen + tlen' < n
1603 if tlen + tlen' < n
1588 then go (tlen + tlen') t' l'
1604 then go (tlen + tlen') t' l'
1589 else return (r t', r l', False)
1605 else return (r t', r l', False)
@@ -1593,47 +1609,45 @@ brReadN br n = go 0 id id
1593-- Inspecting a response
1609-- Inspecting a response
1595-- | Get the response body.
1611-- | Get the response body.
1597−responseBody
1612+responseBody ::
1598− :: HttpResponse response
1613+ HttpResponse response =>
1599− => response
1614+ response ->
1600− -> HttpResponseBody response
1615+ HttpResponseBody response
1601responseBody = L.responseBody . toVanillaResponse
1616responseBody = L.responseBody . toVanillaResponse
1603-- | Get the response status code.
1618-- | Get the response status code.
1605−responseStatusCode
1619+responseStatusCode ::
1606− :: HttpResponse response
1620+ HttpResponse response =>
1607− => response
1621+ response ->
1609responseStatusCode =
1623responseStatusCode =
1610 Y.statusCode . L.responseStatus . toVanillaResponse
1624 Y.statusCode . L.responseStatus . toVanillaResponse
1612-- | Get the response status message.
1626-- | Get the response status message.
1614−responseStatusMessage
1627+responseStatusMessage ::
1615− :: HttpResponse response
1628+ HttpResponse response =>
1616− => response
1629+ response ->
1617− -> ByteString
1630+ ByteString
1618responseStatusMessage =
1631responseStatusMessage =
1619 Y.statusMessage . L.responseStatus . toVanillaResponse
1632 Y.statusMessage . L.responseStatus . toVanillaResponse
1621-- | Lookup a particular header from a response.
1634-- | Lookup a particular header from a response.
1623−responseHeader
1635+responseHeader ::
1624− :: HttpResponse response
1636+ HttpResponse response =>
1625− => response -- ^ Response interpretation
1637+ -- | Response interpretation
1626− -> ByteString -- ^ Header to lookup
1639+ -- | Header to lookup
1627− -> Maybe ByteString -- ^ Header value if found
1641+ -- | Header value if found
1628responseHeader r h =
1643responseHeader r h =
1629 (lookup (CI.mk h) . L.responseHeaders . toVanillaResponse) r
1644 (lookup (CI.mk h) . L.responseHeaders . toVanillaResponse) r
1631-- | Get the response 'L.CookieJar'.
1646-- | Get the response 'L.CookieJar'.
1633−responseCookieJar
1647+responseCookieJar ::
1634− :: HttpResponse response
1648+ HttpResponse response =>
1635− => response
1649+ response ->
1636− -> L.CookieJar
1650+ L.CookieJar
1637responseCookieJar = L.responseCookieJar . toVanillaResponse
1651responseCookieJar = L.responseCookieJar . toVanillaResponse
1639----------------------------------------------------------------------------
1653----------------------------------------------------------------------------
@@ -1647,16 +1661,12 @@ responseCookieJar = L.responseCookieJar . toVanillaResponse
1647-- | A type class for response interpretations. It allows to describe how to
1661-- | A type class for response interpretations. It allows to describe how to
1648-- consume response from a @'L.Response' 'L.BodyReader'@ and produce the
1662-- consume response from a @'L.Response' 'L.BodyReader'@ and produce the
1649-- final result that is to be returned to the user.
1663-- final result that is to be returned to the user.
1651class HttpResponse response where
1664class HttpResponse response where
1653 -- | The associated type is the type of body that can be extracted from an
1665 -- | The associated type is the type of body that can be extracted from an
1654 -- instance of 'HttpResponse'.
1666 -- instance of 'HttpResponse'.
1656 type HttpResponseBody response :: Type
1667 type HttpResponseBody response :: Type
1658 -- | The method describes how to get the underlying 'L.Response' record.
1669 -- | The method describes how to get the underlying 'L.Response' record.
1660 toVanillaResponse :: response -> L.Response (HttpResponseBody response)
1670 toVanillaResponse :: response -> L.Response (HttpResponseBody response)
1662 -- | This method describes how to consume response body and, more
1672 -- | This method describes how to consume response body and, more
@@ -1672,12 +1682,11 @@ class HttpResponse response where
1673 -- __Note__: signature of this function was changed in the version
1683 -- __Note__: signature of this function was changed in the version
1674 -- /1.0.0/.
1684 -- /1.0.0/.
1676− getHttpResponse
1685+ getHttpResponse ::
1677− :: L.Response L.BodyReader
1678− -- ^ Response with body reader inside
1686+ -- | Response with body reader inside
1679− -> IO response
1687+ L.Response L.BodyReader ->
1680− -- ^ The final result
1688+ -- | The final result
1682 -- | The value of @\"Accept\"@ header. This is useful, for example, if a
1691 -- | The value of @\"Accept\"@ header. This is useful, for example, if a
1683 -- website supports both @XML@ and @JSON@ responses, and decides what to
1692 -- website supports both @XML@ and @JSON@ responses, and decides what to
@@ -1687,7 +1696,6 @@ class HttpResponse response where
1687 -- will take precedence.
1696 -- will take precedence.
1689 -- @since 2.1.0
1698 -- @since 2.1.0
1691 acceptHeader :: Proxy response -> Maybe ByteString
1699 acceptHeader :: Proxy response -> Maybe ByteString
1692 acceptHeader Proxy = Nothing
1700 acceptHeader Proxy = Nothing
@@ -1701,15 +1709,12 @@ class HttpResponse response where
1701-- request components easier using @('<>')@.
1709-- request components easier using @('<>')@.
1703-- __Note__: this type class is not a part of the public API.
1711-- __Note__: this type class is not a part of the public API.
1705class RequestComponent a where
1712class RequestComponent a where
1707 -- | Get a function that takes a 'L.Request' and changes it somehow
1713 -- | Get a function that takes a 'L.Request' and changes it somehow
1708 -- returning another 'L.Request'. For example, the 'HttpMethod' instance
1714 -- returning another 'L.Request'. For example, the 'HttpMethod' instance
1709 -- of 'RequestComponent' just overwrites method. The function is wrapped
1715 -- of 'RequestComponent' just overwrites method. The function is wrapped
1710 -- in 'Endo' so it's easier to chain such “modifying applications”
1716 -- in 'Endo' so it's easier to chain such “modifying applications”
1711 -- together building bigger and bigger 'RequestComponent's.
1717 -- together building bigger and bigger 'RequestComponent's.
1713 getRequestMod :: a -> Endo L.Request
1718 getRequestMod :: a -> Endo L.Request
1715-- | This wrapper is only used to attach a type-level tag to a given type.
1720-- | This wrapper is only used to attach a type-level tag to a given type.
@@ -1719,17 +1724,15 @@ class RequestComponent a where
1719-- method@ and @'HttpBody' body => 'RequestComponent' body@ when it decides
1724-- method@ and @'HttpBody' body => 'RequestComponent' body@ when it decides
1720-- which instance to use (i.e. the constraints are taken into account later,
1725-- which instance to use (i.e. the constraints are taken into account later,
1721-- when instance is already chosen).
1726-- when instance is already chosen).
1723newtype Womb (tag :: Symbol) a = Womb a
1727newtype Womb (tag :: Symbol) a = Womb a
1725-- | Exceptions that this library throws.
1729-- | Exceptions that this library throws.
1727data HttpException
1730data HttpException
1728− = VanillaHttpException L.HttpException
1729− -- ^ A wrapper with an 'L.HttpException' from "Network.HTTP.Client"
1731+ = -- | A wrapper with an 'L.HttpException' from "Network.HTTP.Client"
1730− | JsonHttpException String
1732+ VanillaHttpException L.HttpException
1731− -- ^ A wrapper with Aeson-produced 'String' describing why decoding
1733+ | -- | A wrapper with Aeson-produced 'String' describing why decoding
1732 -- failed
1734 -- failed
1735+ JsonHttpException String
1733 deriving (Show, Typeable, Generic)
1736 deriving (Show, Typeable, Generic)
1735instance Exception HttpException
1738instance Exception HttpException
@@ -1739,24 +1742,25 @@ instance Exception HttpException
1741-- See also: 'HttpMethod' and 'HttpBody'.
1744-- See also: 'HttpMethod' and 'HttpBody'.
1743data CanHaveBody
1745data CanHaveBody
1744− = CanHaveBody -- ^ Indeed can have a body
1746+ = -- | Indeed can have a body
1745− | NoBody -- ^ Should not have a body
1748+ | -- | Should not have a body
1747-- | A type-level tag that specifies URL scheme used (and thus if HTTPS is
1751-- | A type-level tag that specifies URL scheme used (and thus if HTTPS is
1748-- enabled). This is used to force TLS requirement for some authentication
1752-- enabled). This is used to force TLS requirement for some authentication
1749-- 'Option's.
1753-- 'Option's.
1751data Scheme
1754data Scheme
1752− = Http -- ^ HTTP
1756+ Http
1753− | Https -- ^ HTTPS
1758+ Https
1754 deriving (Eq, Ord, Show, Data, Typeable, Generic)
1759 deriving (Eq, Ord, Show, Data, Typeable, Generic)
1756----------------------------------------------------------------------------
1761----------------------------------------------------------------------------
1757-- Constants
1762-- Constants
1759-- | Max length of preview fragment of response body.
1764-- | Max length of preview fragment of response body.
1761bodyPreviewLength :: Num a => a
1765bodyPreviewLength :: Num a => a
1762bodyPreviewLength = 1024
1766bodyPreviewLength = 1024