on 67be279 help sign in
.github/dependabot.ymldeleted−6
since splitsnapshots
unifiedsplit
@@ -1,6 +0,0 @@
1−version: 2
2−updates:
3− - package-ecosystem: "github-actions"
4− directory: "/"
5− schedule:
6− interval: "weekly"
.github/workflows/ci.yaml+13−14
@@ -11,25 +11,27 @@ jobs:
11 ormolu:
11 ormolu:
12 runs-on: ubuntu-latest
12 runs-on: ubuntu-latest
13 steps:
13 steps:
14− - uses: actions/checkout@v4
14+ - uses: actions/checkout@v2.3.4
15− - uses: haskell-actions/run-ormolu@v17
15+ - uses: mrkkrp/ormolu-action@v5
16 build:
16 build:
17 runs-on: ubuntu-latest
17 runs-on: ubuntu-latest
18 needs: ormolu
18 needs: ormolu
19 strategy:
19 strategy:
20 matrix:
20 matrix:
21− cabal: ["3.12"]
21+ cabal: ["3.6"]
22− ghc: ["9.6.3", "9.8.2", "9.10.1"]
22+ ghc: ["8.10.7", "9.0.2", "9.2.1"]
23+ env:
24+ CONFIG: "--enable-tests --enable-benchmarks --flags=dev"
23 steps:
25 steps:
24− - uses: actions/checkout@v4
26+ - uses: actions/checkout@v2.3.4
25− - uses: haskell-actions/setup@v2
27+ - uses: haskell/actions/setup@v1.2.9
26 id: setup-haskell-cabal
28 id: setup-haskell-cabal
27 with:
29 with:
28 ghc-version: ${{ matrix.ghc }}
30 ghc-version: ${{ matrix.ghc }}
29 cabal-version: ${{ matrix.cabal }}
31 cabal-version: ${{ matrix.cabal }}
30 - run: cabal update
32 - run: cabal update
31− - run: cabal freeze
33+ - run: cabal freeze $CONFIG
32− - uses: actions/cache@v4.2.3
34+ - uses: actions/cache@v2.1.3
33 with:
35 with:
34 path: |
36 path: |
35 ${{ steps.setup-haskell-cabal.outputs.cabal-store }}
37 ${{ steps.setup-haskell-cabal.outputs.cabal-store }}
@@ -38,10 +40,7 @@ jobs:
38 restore-keys: |
40 restore-keys: |
39 ${{ runner.os }}-${{ matrix.ghc }}-
41 ${{ runner.os }}-${{ matrix.ghc }}-
40 - run: cabal format && git diff --exit-code --color=always
42 - run: cabal format && git diff --exit-code --color=always
41− - run: cabal build
43+ - run: cabal build $CONFIG
42− - run: |
43− docker pull kennethreitz/httpbin
44− docker run -p 1234:80 kennethreitz/httpbin &
45− cabal test
44+ - run: cabal test $CONFIG
46− - run: cabal haddock
45+ - run: cabal haddock $CONFIG
47 - run: cabal sdist
46 - run: cabal sdist
.gitignore−1
@@ -25,6 +25,5 @@ cabal.project.local
25cabal.sandbox.config
25cabal.sandbox.config
26dist-*/
26dist-*/
27dist/
27dist/
28−hie.yaml
29stack.yaml
28stack.yaml
30stack.yaml.lock
29stack.yaml.lock
CHANGELOG.md−36
@@ -1,39 +1,3 @@
1−## Req 3.13.4
2−
3−* Fixed empty ciphersuite list when compiling against `tls < 2.0.6`
4− (see [PR 175](https://github.com/mrkkrp/req/pull/175)). As a side effect, now
5− compatible with older versions of `crypton-connection` (>= 0.3).
6−
7−## Req 3.13.3
8−
9−* Works with `crypton-connection-0.4` and newer.
10−
11−## Req 3.13.2
12−
13−* Disable the problematic `httpbin-tests` test suite by default. Only enable
14− it when the `dev` flag is enabled. In that case it is expected that an
15− httpbin server is run locally at `localhost:1234`.
16−
17−## Req 3.13.1
18−
19−* Switched the non-pure test suite to use https://httpbun.org instead of
20− https://httpbin.org since the latter proved to be highly unreliable
21− lately.
22−
23−* Switched from `connection` to `crypton-connection`.
24−
25−* Builds with GHC 9.6.1.
26−
27−## Req 3.13.0
28−
29−* Add `headerRedacted` function to add header fields, which will be with
30− redacted values on print.
31−
32−## Req 3.12.0
33−
34−* Add `isStatusCodeException` function.
35−* Add `instance HttpResponse (Network.HTTP.Client.Response ())`.
36−
37## Req 3.11.0
1## Req 3.11.0
38
2
39* Add the `queryParamToList` method to the `QueryParam` type class.
3* Add the `queryParamToList` method to the `QueryParam` type class.
Network/HTTP/Req.hs+83−103
@@ -1,9 +1,20 @@
1+{-# LANGUAGE BangPatterns #-}
2+{-# LANGUAGE CPP #-}
1{-# LANGUAGE DataKinds #-}
3{-# LANGUAGE DataKinds #-}
4+{-# LANGUAGE DeriveDataTypeable #-}
5+{-# LANGUAGE DeriveGeneric #-}
6+{-# LANGUAGE DeriveLift #-}
7+{-# LANGUAGE FlexibleInstances #-}
8+{-# LANGUAGE GeneralizedNewtypeDeriving #-}
2{-# LANGUAGE LambdaCase #-}
9{-# LANGUAGE LambdaCase #-}
10+{-# LANGUAGE MultiParamTypeClasses #-}
3{-# LANGUAGE OverloadedStrings #-}
11{-# LANGUAGE OverloadedStrings #-}
4{-# LANGUAGE QuasiQuotes #-}
12{-# LANGUAGE QuasiQuotes #-}
13+{-# LANGUAGE RankNTypes #-}
5{-# LANGUAGE RecordWildCards #-}
14{-# LANGUAGE RecordWildCards #-}
6{-# LANGUAGE RoleAnnotations #-}
15{-# LANGUAGE RoleAnnotations #-}
16+{-# LANGUAGE ScopedTypeVariables #-}
17+{-# LANGUAGE StandaloneDeriving #-}
7{-# LANGUAGE TemplateHaskellQuotes #-}
18{-# LANGUAGE TemplateHaskellQuotes #-}
8{-# LANGUAGE TypeFamilies #-}
19{-# LANGUAGE TypeFamilies #-}
9{-# LANGUAGE UndecidableInstances #-}
20{-# LANGUAGE UndecidableInstances #-}
@@ -150,7 +161,6 @@ module Network.HTTP.Req
150 -- *** Headers
161 -- *** Headers
151 header,
162 header,
152 attachHeader,
163 attachHeader,
153− headerRedacted,
154
164
155 -- *** Cookies
165 -- *** Cookies
156 -- $cookies
166 -- $cookies
@@ -197,78 +207,74 @@ module Network.HTTP.Req
197
207
198 -- * Other
208 -- * Other
199 HttpException (..),
209 HttpException (..),
200− isStatusCodeException,
201 CanHaveBody (..),
210 CanHaveBody (..),
202 Scheme (..),
211 Scheme (..),
203 )
212 )
204where
213where
205
214
206−import Blaze.ByteString.Builder qualified as BB
215+import qualified Blaze.ByteString.Builder as BB
207import Control.Applicative
216import Control.Applicative
208import Control.Arrow (first, second)
217import Control.Arrow (first, second)
209import Control.Exception hiding (Handler (..), TypeError)
218import Control.Exception hiding (Handler (..), TypeError)
210−import Control.Monad (guard, void, (>=>))
211import Control.Monad.Base
219import Control.Monad.Base
212import Control.Monad.Catch (Handler (..), MonadCatch, MonadMask, MonadThrow)
220import Control.Monad.Catch (Handler (..), MonadCatch, MonadMask, MonadThrow)
213import Control.Monad.IO.Class
221import Control.Monad.IO.Class
214import Control.Monad.IO.Unlift
222import Control.Monad.IO.Unlift
215−import Control.Monad.Reader (ReaderT (ReaderT), ask, lift, runReaderT)
223+import Control.Monad.Reader
216import Control.Monad.Trans.Accum (AccumT)
224import Control.Monad.Trans.Accum (AccumT)
217import Control.Monad.Trans.Cont (ContT)
225import Control.Monad.Trans.Cont (ContT)
218import Control.Monad.Trans.Control
226import Control.Monad.Trans.Control
219import Control.Monad.Trans.Except (ExceptT)
227import Control.Monad.Trans.Except (ExceptT)
220import Control.Monad.Trans.Identity (IdentityT)
228import Control.Monad.Trans.Identity (IdentityT)
221import Control.Monad.Trans.Maybe (MaybeT)
229import Control.Monad.Trans.Maybe (MaybeT)
222−import Control.Monad.Trans.RWS.CPS qualified as RWS.CPS
230+import qualified Control.Monad.Trans.RWS.CPS as RWS.CPS
223−import Control.Monad.Trans.RWS.Lazy qualified as RWS.Lazy
231+import qualified Control.Monad.Trans.RWS.Lazy as RWS.Lazy
224−import Control.Monad.Trans.RWS.Strict qualified as RWS.Strict
232+import qualified Control.Monad.Trans.RWS.Strict as RWS.Strict
225import Control.Monad.Trans.Select (SelectT)
233import Control.Monad.Trans.Select (SelectT)
226−import Control.Monad.Trans.State.Lazy qualified as State.Lazy
234+import qualified Control.Monad.Trans.State.Lazy as State.Lazy
227−import Control.Monad.Trans.State.Strict qualified as State.Strict
235+import qualified Control.Monad.Trans.State.Strict as State.Strict
228−import Control.Monad.Trans.Writer.CPS qualified as Writer.CPS
236+import qualified Control.Monad.Trans.Writer.CPS as Writer.CPS
229−import Control.Monad.Trans.Writer.Lazy qualified as Writer.Lazy
237+import qualified Control.Monad.Trans.Writer.Lazy as Writer.Lazy
230−import Control.Monad.Trans.Writer.Strict qualified as Writer.Strict
238+import qualified Control.Monad.Trans.Writer.Strict as Writer.Strict
231import Control.Retry
239import Control.Retry
232import Data.Aeson (FromJSON (..), ToJSON (..))
240import Data.Aeson (FromJSON (..), ToJSON (..))
233−import Data.Aeson qualified as A
241+import qualified Data.Aeson as A
234import Data.ByteString (ByteString)
242import Data.ByteString (ByteString)
235−import Data.ByteString qualified as B
243+import qualified Data.ByteString as B
236−import Data.ByteString.Lazy qualified as BL
244+import qualified Data.ByteString.Lazy as BL
237−import Data.CaseInsensitive qualified as CI
245+import qualified Data.CaseInsensitive as CI
238import Data.Data (Data)
246import Data.Data (Data)
239−import Data.Default.Class (def)
240import Data.Function (on)
247import Data.Function (on)
241import Data.IORef
248import Data.IORef
242import Data.Kind (Constraint, Type)
249import Data.Kind (Constraint, Type)
243import Data.List (foldl', nubBy)
250import Data.List (foldl', nubBy)
244import Data.List.NonEmpty (NonEmpty (..))
251import Data.List.NonEmpty (NonEmpty (..))
245−import Data.List.NonEmpty qualified as NE
252+import qualified Data.List.NonEmpty as NE
246import Data.Maybe (fromMaybe)
253import Data.Maybe (fromMaybe)
247import Data.Proxy
254import Data.Proxy
248import Data.Semigroup (Endo (..))
255import Data.Semigroup (Endo (..))
249−import Data.Set qualified as S
250import Data.Text (Text)
256import Data.Text (Text)
251−import Data.Text qualified as T
257+import qualified Data.Text as T
252−import Data.Text.Encoding qualified as T
258+import qualified Data.Text.Encoding as T
253import Data.Typeable (Typeable, cast)
259import Data.Typeable (Typeable, cast)
254import GHC.Generics
260import GHC.Generics
255import GHC.TypeLits
261import GHC.TypeLits
256−import Language.Haskell.TH qualified as TH
262+import qualified Language.Haskell.TH as TH
257−import Language.Haskell.TH.Quote qualified as TH
263+import qualified Language.Haskell.TH.Quote as TH
258−import Language.Haskell.TH.Syntax qualified as TH
264+import qualified Language.Haskell.TH.Syntax as TH
259−import Network.Connection qualified as NC
265+import qualified Network.Connection as NC
260−import Network.HTTP.Client qualified as L
266+import qualified Network.HTTP.Client as L
261−import Network.HTTP.Client.Internal qualified as LI
267+import qualified Network.HTTP.Client.Internal as LI
262−import Network.HTTP.Client.MultipartFormData qualified as LM
268+import qualified Network.HTTP.Client.MultipartFormData as LM
263−import Network.HTTP.Client.TLS qualified as L
269+import qualified Network.HTTP.Client.TLS as L
264−import Network.HTTP.Types qualified as Y
270+import qualified Network.HTTP.Types as Y
265import System.IO.Unsafe (unsafePerformIO)
271import System.IO.Unsafe (unsafePerformIO)
266import Text.URI (URI)
272import Text.URI (URI)
267−import Text.URI qualified as URI
273+import qualified Text.URI as URI
268−import Text.URI.QQ qualified as QQ
274+import qualified Text.URI.QQ as QQ
269−import Web.Authenticate.OAuth qualified as OAuth
275+import qualified Web.Authenticate.OAuth as OAuth
270import Web.FormUrlEncoded (FromForm (..), ToForm (..))
276import Web.FormUrlEncoded (FromForm (..), ToForm (..))
271−import Web.FormUrlEncoded qualified as Form
277+import qualified Web.FormUrlEncoded as Form
272import Web.HttpApiData (ToHttpApiData (..))
278import Web.HttpApiData (ToHttpApiData (..))
273
279
274----------------------------------------------------------------------------
280----------------------------------------------------------------------------
@@ -489,7 +495,7 @@ reqCb method url body responseProxy options adjustRequest =
489--
495--
490-- @since 3.7.0
496-- @since 3.7.0
491reqHandler ::
497reqHandler ::
492− (MonadHttp m) =>
498+ MonadHttp m =>
493 -- | How to get final result from a 'L.Response'
499 -- | How to get final result from a 'L.Response'
494 (L.Response L.BodyReader -> IO b) ->
500 (L.Response L.BodyReader -> IO b) ->
495 -- | 'L.Request' to perform
501 -- | 'L.Request' to perform
@@ -585,10 +591,10 @@ req' method url body options m = do
585 withReqManager (m request)
591 withReqManager (m request)
586
592
587-- | Perform an action using the global implicit 'L.Manager' that the rest
593-- | Perform an action using the global implicit 'L.Manager' that the rest
588−-- of the library uses. This allows us to reuse connections that the
594+-- of the library uses. This allows to reuse connections that the
589-- 'L.Manager' controls.
595-- 'L.Manager' controls.
590−withReqManager :: (MonadIO m) => (L.Manager -> m a) -> m a
596+withReqManager :: MonadIO m => (L.Manager -> m a) -> m a
591−withReqManager m = m globalManager
597+withReqManager m = liftIO (readIORef globalManager) >>= m
592
598
593-- | The global 'L.Manager' that 'req' uses. Here we just go with the
599-- | The global 'L.Manager' that 'req' uses. Here we just go with the
594-- default settings, so users don't need to deal with this manager stuff at
600-- default settings, so users don't need to deal with this manager stuff at
@@ -601,16 +607,16 @@ withReqManager m = m globalManager
601-- manager. From that moment on the 'IORef' will be just reused—exactly the
607-- manager. From that moment on the 'IORef' will be just reused—exactly the
602-- behavior we want here in order to maximize connection sharing. GHC could
608-- behavior we want here in order to maximize connection sharing. GHC could
603-- spoil the plan by inlining the definition, hence the @NOINLINE@ pragma.
609-- spoil the plan by inlining the definition, hence the @NOINLINE@ pragma.
604−globalManager :: L.Manager
610+globalManager :: IORef L.Manager
605globalManager = unsafePerformIO $ do
611globalManager = unsafePerformIO $ do
606 context <- NC.initConnectionContext
612 context <- NC.initConnectionContext
607 let settings =
613 let settings =
608 L.mkManagerSettingsContext
614 L.mkManagerSettingsContext
609 (Just context)
615 (Just context)
610− def
616+ (NC.TLSSettingsSimple False False False)
611 Nothing
617 Nothing
612 manager <- L.newManager settings
618 manager <- L.newManager settings
613− return manager
619+ newIORef manager
614{-# NOINLINE globalManager #-}
620{-# NOINLINE globalManager #-}
615
621
616----------------------------------------------------------------------------
622----------------------------------------------------------------------------
@@ -630,7 +636,7 @@ globalManager = unsafePerformIO $ do
630-- | A type class for monads that support performing HTTP requests.
636-- | A type class for monads that support performing HTTP requests.
631-- Typically, you only need to define the 'handleHttpException' method
637-- Typically, you only need to define the 'handleHttpException' method
632-- unless you want to tweak 'HttpConfig'.
638-- unless you want to tweak 'HttpConfig'.
633−class (MonadIO m) => MonadHttp m where
639+class MonadIO m => MonadHttp m where
634 -- | This method describes how to deal with 'HttpException' that was
640 -- | This method describes how to deal with 'HttpException' that was
635 -- caught by the library. One option is to re-throw it if you are OK with
641 -- caught by the library. One option is to re-throw it if you are OK with
636 -- exceptions, but if you prefer working with something like
642 -- exceptions, but if you prefer working with something like
@@ -714,8 +720,9 @@ data HttpConfig = HttpConfig
714 -- | Max length of preview fragment of response body.
720 -- | Max length of preview fragment of response body.
715 --
721 --
716 -- @since 3.6.0
722 -- @since 3.6.0
717− httpConfigBodyPreviewLength :: forall a. (Num a) => a
723+ httpConfigBodyPreviewLength :: forall a. Num a => a
718 }
724 }
725+ deriving (Typeable)
719
726
720-- | The default value of 'HttpConfig'.
727-- | The default value of 'HttpConfig'.
721--
728--
@@ -803,27 +810,27 @@ instance (MonadHttp m, Monoid w) => MonadHttp (AccumT w m) where
803 getHttpConfig = lift getHttpConfig
810 getHttpConfig = lift getHttpConfig
804
811
805-- | @since 3.10.0
812-- | @since 3.10.0
806−instance (MonadHttp m) => MonadHttp (ContT r m) where
813+instance MonadHttp m => MonadHttp (ContT r m) where
807 handleHttpException = lift . handleHttpException
814 handleHttpException = lift . handleHttpException
808 getHttpConfig = lift getHttpConfig
815 getHttpConfig = lift getHttpConfig
809
816
810-- | @since 3.10.0
817-- | @since 3.10.0
811−instance (MonadHttp m) => MonadHttp (ExceptT e m) where
818+instance MonadHttp m => MonadHttp (ExceptT e m) where
812 handleHttpException = lift . handleHttpException
819 handleHttpException = lift . handleHttpException
813 getHttpConfig = lift getHttpConfig
820 getHttpConfig = lift getHttpConfig
814
821
815-- | @since 3.10.0
822-- | @since 3.10.0
816−instance (MonadHttp m) => MonadHttp (IdentityT m) where
823+instance MonadHttp m => MonadHttp (IdentityT m) where
817 handleHttpException = lift . handleHttpException
824 handleHttpException = lift . handleHttpException
818 getHttpConfig = lift getHttpConfig
825 getHttpConfig = lift getHttpConfig
819
826
820-- | @since 3.10.0
827-- | @since 3.10.0
821−instance (MonadHttp m) => MonadHttp (MaybeT m) where
828+instance MonadHttp m => MonadHttp (MaybeT m) where
822 handleHttpException = lift . handleHttpException
829 handleHttpException = lift . handleHttpException
823 getHttpConfig = lift getHttpConfig
830 getHttpConfig = lift getHttpConfig
824
831
825-- | @since 3.10.0
832-- | @since 3.10.0
826−instance (MonadHttp m) => MonadHttp (ReaderT r m) where
833+instance MonadHttp m => MonadHttp (ReaderT r m) where
827 handleHttpException = lift . handleHttpException
834 handleHttpException = lift . handleHttpException
828 getHttpConfig = lift getHttpConfig
835 getHttpConfig = lift getHttpConfig
829
836
@@ -843,17 +850,17 @@ instance (MonadHttp m, Monoid w) => MonadHttp (RWS.Strict.RWST r w s m) where
843 getHttpConfig = lift getHttpConfig
850 getHttpConfig = lift getHttpConfig
844
851
845-- | @since 3.10.0
852-- | @since 3.10.0
846−instance (MonadHttp m) => MonadHttp (SelectT r m) where
853+instance MonadHttp m => MonadHttp (SelectT r m) where
847 handleHttpException = lift . handleHttpException
854 handleHttpException = lift . handleHttpException
848 getHttpConfig = lift getHttpConfig
855 getHttpConfig = lift getHttpConfig
849
856
850-- | @since 3.10.0
857-- | @since 3.10.0
851−instance (MonadHttp m) => MonadHttp (State.Lazy.StateT s m) where
858+instance MonadHttp m => MonadHttp (State.Lazy.StateT s m) where
852 handleHttpException = lift . handleHttpException
859 handleHttpException = lift . handleHttpException
853 getHttpConfig = lift getHttpConfig
860 getHttpConfig = lift getHttpConfig
854
861
855-- | @since 3.10.0
862-- | @since 3.10.0
856−instance (MonadHttp m) => MonadHttp (State.Strict.StateT s m) where
863+instance MonadHttp m => MonadHttp (State.Strict.StateT s m) where
857 handleHttpException = lift . handleHttpException
864 handleHttpException = lift . handleHttpException
858 getHttpConfig = lift getHttpConfig
865 getHttpConfig = lift getHttpConfig
859
866
@@ -877,7 +884,7 @@ instance (MonadHttp m, Monoid w) => MonadHttp (Writer.Strict.WriterT w m) where
877--
884--
878-- @since 0.4.0
885-- @since 0.4.0
879runReq ::
886runReq ::
880− (MonadIO m) =>
887+ MonadIO m =>
881 -- | 'HttpConfig' to use
888 -- | 'HttpConfig' to use
882 HttpConfig ->
889 HttpConfig ->
883 -- | Computation to run
890 -- | Computation to run
@@ -982,7 +989,7 @@ class HttpMethod a where
982 -- | Return name of the method as a 'ByteString'.
989 -- | Return name of the method as a 'ByteString'.
983 httpMethodName :: Proxy a -> ByteString
990 httpMethodName :: Proxy a -> ByteString
984
991
985−instance (HttpMethod method) => RequestComponent (Tagged "method" method) where
992+instance HttpMethod method => RequestComponent (Tagged "method" method) where
986 getRequestMod _ = Endo $ \x ->
993 getRequestMod _ = Endo $ \x ->
987 x {L.method = httpMethodName (Proxy :: Proxy method)}
994 x {L.method = httpMethodName (Proxy :: Proxy method)}
988
995
@@ -1024,20 +1031,25 @@ instance (HttpMethod method) => RequestComponent (Tagged "method" method) where
1024-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
1031-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
1025data Url (scheme :: Scheme) = Url Scheme (NonEmpty Text)
1032data Url (scheme :: Scheme) = Url Scheme (NonEmpty Text)
1026 -- NOTE The second value is the path segments in reversed order.
1033 -- NOTE The second value is the path segments in reversed order.
1027− deriving (Eq, Ord, Show, Data, Generic)
1034+ deriving (Eq, Ord, Show, Data, Typeable, Generic)
1028
1035
1029type role Url nominal
1036type role Url nominal
1030
1037
1031-- With template-haskell >=2.15 and text >=1.2.4 Lift can be derived, however
1038-- With template-haskell >=2.15 and text >=1.2.4 Lift can be derived, however
1032-- the derived lift forgets the type of the scheme.
1039-- the derived lift forgets the type of the scheme.
1033−instance (Typeable scheme) => TH.Lift (Url scheme) where
1040+instance Typeable scheme => TH.Lift (Url scheme) where
1034 lift url =
1041 lift url =
1035 TH.dataToExpQ (fmap liftText . cast) url `TH.sigE` case url of
1042 TH.dataToExpQ (fmap liftText . cast) url `TH.sigE` case url of
1036 Url Http _ -> [t|Url 'Http|]
1043 Url Http _ -> [t|Url 'Http|]
1037 Url Https _ -> [t|Url 'Https|]
1044 Url Https _ -> [t|Url 'Https|]
1038 where
1045 where
1039 liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)
1046 liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t)
1047+
1048+#if MIN_VERSION_template_haskell(2,17,0)
1040 liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
1049 liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift
1050+#elif MIN_VERSION_template_haskell(2,16,0)
1051+ liftTyped = TH.unsafeTExpCoerce . TH.lift
1052+#endif
1041
1053
1042-- | Given host name, produce a 'Url' which has “http” as its scheme and
1054-- | Given host name, produce a 'Url' which has “http” as its scheme and
1043-- empty path. This also sets port to @80@.
1055-- empty path. This also sets port to @80@.
@@ -1053,7 +1065,7 @@ https = Url Https . pure
1053-- path segment can be of any type that is an instance of 'ToHttpApiData'.
1065-- path segment can be of any type that is an instance of 'ToHttpApiData'.
1054infixl 5 /~
1066infixl 5 /~
1055
1067
1056−(/~) :: (ToHttpApiData a) => Url scheme -> a -> Url scheme
1068+(/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme
1057Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
1069Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
1058
1070
1059-- | A type-constrained version of @('/~')@ to remove ambiguity in the cases
1071-- | A type-constrained version of @('/~')@ to remove ambiguity in the cases
@@ -1241,7 +1253,7 @@ instance HttpBody NoReqBody where
1241-- charset=utf-8\"@ value.
1253-- charset=utf-8\"@ value.
1242newtype ReqBodyJson a = ReqBodyJson a
1254newtype ReqBodyJson a = ReqBodyJson a
1243
1255
1244−instance (ToJSON a) => HttpBody (ReqBodyJson a) where
1256+instance ToJSON a => HttpBody (ReqBodyJson a) where
1245 getRequestBody (ReqBodyJson a) = L.RequestBodyLBS (A.encode a)
1257 getRequestBody (ReqBodyJson a) = L.RequestBodyLBS (A.encode a)
1246 getRequestContentType _ = pure "application/json; charset=utf-8"
1258 getRequestContentType _ = pure "application/json; charset=utf-8"
1247
1259
@@ -1340,7 +1352,7 @@ instance HttpBody ReqBodyMultipart where
1340-- | Create 'ReqBodyMultipart' request body from a collection of 'LM.Part's.
1352-- | Create 'ReqBodyMultipart' request body from a collection of 'LM.Part's.
1341--
1353--
1342-- @since 0.2.0
1354-- @since 0.2.0
1343−reqBodyMultipart :: (MonadIO m) => [LM.Part] -> m ReqBodyMultipart
1355+reqBodyMultipart :: MonadIO m => [LM.Part] -> m ReqBodyMultipart
1344reqBodyMultipart parts = liftIO $ do
1356reqBodyMultipart parts = liftIO $ do
1345 boundary <- LM.webkitBoundary
1357 boundary <- LM.webkitBoundary
1346 body <- LM.renderParts boundary parts
1358 body <- LM.renderParts boundary parts
@@ -1380,7 +1392,7 @@ type family
1380 TypeError
1392 TypeError
1381 ('Text "This HTTP method does not allow attaching a request body.")
1393 ('Text "This HTTP method does not allow attaching a request body.")
1382
1394
1383−instance (HttpBody body) => RequestComponent (Tagged "body" body) where
1395+instance HttpBody body => RequestComponent (Tagged "body" body) where
1384 getRequestMod (Tagged body) = Endo $ \x ->
1396 getRequestMod (Tagged body) = Endo $ \x ->
1385 x
1397 x
1386 { L.requestBody = getRequestBody body,
1398 { L.requestBody = getRequestBody body,
@@ -1450,7 +1462,7 @@ instance RequestComponent (Option scheme) where
1450
1462
1451-- | Finalize given 'L.Request' by applying a finalizer from the given
1463-- | Finalize given 'L.Request' by applying a finalizer from the given
1452-- 'Option' (if it has any).
1464-- 'Option' (if it has any).
1453−finalizeRequest :: (MonadIO m) => Option scheme -> L.Request -> m L.Request
1465+finalizeRequest :: MonadIO m => Option scheme -> L.Request -> m L.Request
1454finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
1466finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
1455
1467
1456----------------------------------------------------------------------------
1468----------------------------------------------------------------------------
@@ -1483,7 +1495,7 @@ name =: value = queryParam name (pure value)
1483-- This operator is defined in terms of 'queryParam':
1495-- This operator is defined in terms of 'queryParam':
1484--
1496--
1485-- > queryFlag name = queryParam name (Nothing :: Maybe ())
1497-- > queryFlag name = queryParam name (Nothing :: Maybe ())
1486−queryFlag :: (QueryParam param) => Text -> param
1498+queryFlag :: QueryParam param => Text -> param
1487queryFlag name = queryParam name (Nothing :: Maybe ())
1499queryFlag name = queryParam name (Nothing :: Maybe ())
1488
1500
1489-- | Construct query parameters from a 'ToForm' instance. This function
1501-- | Construct query parameters from a 'ToForm' instance. This function
@@ -1513,7 +1525,7 @@ class QueryParam param where
1513 -- 'Nothing', it won't be included at all (i.e. you create a flag this
1525 -- 'Nothing', it won't be included at all (i.e. you create a flag this
1514 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
1526 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
1515 -- method, because they are easier to read.
1527 -- method, because they are easier to read.
1516− queryParam :: (ToHttpApiData a) => Text -> Maybe a -> param
1528+ queryParam :: ToHttpApiData a => Text -> Maybe a -> param
1517
1529
1518 -- | Get the query parameter names and values set by 'queryParam'.
1530 -- | Get the query parameter names and values set by 'queryParam'.
1519 --
1531 --
@@ -1547,14 +1559,6 @@ attachHeader :: ByteString -> ByteString -> L.Request -> L.Request
1547attachHeader name value x =
1559attachHeader name value x =
1548 x {L.requestHeaders = (CI.mk name, value) : L.requestHeaders x}
1560 x {L.requestHeaders = (CI.mk name, value) : L.requestHeaders x}
1549
1561
1550−-- | Same as 'header', but with redacted values on print.
1551−--
1552−-- @since 3.13.0
1553−headerRedacted :: ByteString -> ByteString -> Option scheme
1554−headerRedacted name value = withRequest $ \x ->
1555− let y = attachHeader name value x
1556− in y {L.redactHeaders = CI.mk name `S.insert` L.redactHeaders y}
1557−
1558----------------------------------------------------------------------------
1562----------------------------------------------------------------------------
1559-- Request—Optional parameters—Cookies
1563-- Request—Optional parameters—Cookies
1560
1564
@@ -1762,7 +1766,7 @@ ignoreResponse = Proxy
1762newtype JsonResponse a = JsonResponse (L.Response a)
1766newtype JsonResponse a = JsonResponse (L.Response a)
1763 deriving (Show)
1767 deriving (Show)
1764
1768
1765−instance (FromJSON a) => HttpResponse (JsonResponse a) where
1769+instance FromJSON a => HttpResponse (JsonResponse a) where
1766 type HttpResponseBody (JsonResponse a) = a
1770 type HttpResponseBody (JsonResponse a) = a
1767 toVanillaResponse (JsonResponse r) = r
1771 toVanillaResponse (JsonResponse r) = r
1768 getHttpResponse r = do
1772 getHttpResponse r = do
@@ -1878,14 +1882,14 @@ brReadN br n = go 0 id id
1878
1882
1879-- | Get the response body.
1883-- | Get the response body.
1880responseBody ::
1884responseBody ::
1881− (HttpResponse response) =>
1885+ HttpResponse response =>
1882 response ->
1886 response ->
1883 HttpResponseBody response
1887 HttpResponseBody response
1884responseBody = L.responseBody . toVanillaResponse
1888responseBody = L.responseBody . toVanillaResponse
1885
1889
1886-- | Get the response status code.
1890-- | Get the response status code.
1887responseStatusCode ::
1891responseStatusCode ::
1888− (HttpResponse response) =>
1892+ HttpResponse response =>
1889 response ->
1893 response ->
1890 Int
1894 Int
1891responseStatusCode =
1895responseStatusCode =
@@ -1893,7 +1897,7 @@ responseStatusCode =
1893
1897
1894-- | Get the response status message.
1898-- | Get the response status message.
1895responseStatusMessage ::
1899responseStatusMessage ::
1896− (HttpResponse response) =>
1900+ HttpResponse response =>
1897 response ->
1901 response ->
1898 ByteString
1902 ByteString
1899responseStatusMessage =
1903responseStatusMessage =
@@ -1901,7 +1905,7 @@ responseStatusMessage =
1901
1905
1902-- | Lookup a particular header from a response.
1906-- | Lookup a particular header from a response.
1903responseHeader ::
1907responseHeader ::
1904− (HttpResponse response) =>
1908+ HttpResponse response =>
1905 -- | Response interpretation
1909 -- | Response interpretation
1906 response ->
1910 response ->
1907 -- | Header to lookup
1911 -- | Header to lookup
@@ -1913,7 +1917,7 @@ responseHeader r h =
1913
1917
1914-- | Get the response 'L.CookieJar'.
1918-- | Get the response 'L.CookieJar'.
1915responseCookieJar ::
1919responseCookieJar ::
1916− (HttpResponse response) =>
1920+ HttpResponse response =>
1917 response ->
1921 response ->
1918 L.CookieJar
1922 L.CookieJar
1919responseCookieJar = L.responseCookieJar . toVanillaResponse
1923responseCookieJar = L.responseCookieJar . toVanillaResponse
@@ -1967,16 +1971,6 @@ class HttpResponse response where
1967 acceptHeader :: Proxy response -> Maybe ByteString
1971 acceptHeader :: Proxy response -> Maybe ByteString
1968 acceptHeader Proxy = Nothing
1972 acceptHeader Proxy = Nothing
1969
1973
1970−-- | This instance has been added to make it easier to inspect 'L.Response'
1971−-- using Req's functions like 'responseStatusCode', 'responseStatusMessage',
1972−-- etc.
1973−--
1974−-- @since 3.12.0
1975−instance HttpResponse (L.Response ()) where
1976− type HttpResponseBody (L.Response ()) = ()
1977− toVanillaResponse = id
1978− getHttpResponse = return . void
1979−
1980----------------------------------------------------------------------------
1974----------------------------------------------------------------------------
1981-- Other
1975-- Other
1982
1976
@@ -2011,24 +2005,10 @@ data HttpException
2011 | -- | A wrapper with Aeson-produced 'String' describing why decoding
2005 | -- | A wrapper with Aeson-produced 'String' describing why decoding
2012 -- failed
2006 -- failed
2013 JsonHttpException String
2007 JsonHttpException String
2014− deriving (Show, Generic)
2008+ deriving (Show, Typeable, Generic)
2015
2009
2016instance Exception HttpException
2010instance Exception HttpException
2017
2011
2018−-- | Return 'Just' if the given 'HttpException' is wrapping a http-client's
2019−-- 'L.StatusCodeException'. Otherwise, return 'Nothing'.
2020−--
2021−-- @since 3.12.0
2022−isStatusCodeException :: HttpException -> Maybe (L.Response ())
2023−isStatusCodeException
2024− ( VanillaHttpException
2025− ( L.HttpExceptionRequest
2026− _
2027− (L.StatusCodeException r _)
2028− )
2029− ) = Just r
2030−isStatusCodeException _ = Nothing
2031−
2032-- | A simple type isomorphic to 'Bool' that we only have for better error
2012-- | A simple type isomorphic to 'Bool' that we only have for better error
2033-- messages. We use it as a kind and its data constructors as type-level
2013-- messages. We use it as a kind and its data constructors as type-level
2034-- tags.
2014-- tags.
@@ -2048,4 +2028,4 @@ data Scheme
2048 Http
2028 Http
2049 | -- | HTTPS
2029 | -- | HTTPS
2050 Https
2030 Https
2051− deriving (Eq, Ord, Show, Data, Generic, TH.Lift)
2031+ deriving (Eq, Ord, Show, Data, Typeable, Generic, TH.Lift)
README.md+1−1
@@ -4,7 +4,7 @@
4[![Hackage](https://img.shields.io/hackage/v/req.svg?style=flat)](https://hackage.haskell.org/package/req)
4[![Hackage](https://img.shields.io/hackage/v/req.svg?style=flat)](https://hackage.haskell.org/package/req)
5[![Stackage Nightly](http://stackage.org/package/req/badge/nightly)](http://stackage.org/nightly/package/req)
5[![Stackage Nightly](http://stackage.org/package/req/badge/nightly)](http://stackage.org/nightly/package/req)
6[![Stackage LTS](http://stackage.org/package/req/badge/lts)](http://stackage.org/lts/package/req)
6[![Stackage LTS](http://stackage.org/package/req/badge/lts)](http://stackage.org/lts/package/req)
7−[![CI](https://github.com/mrkkrp/req/actions/workflows/ci.yaml/badge.svg)](https://github.com/mrkkrp/req/actions/workflows/ci.yaml)
7+![CI](https://github.com/mrkkrp/req/workflows/CI/badge.svg?branch=master)
8
8
9* [Related packages](#related-packages)
9* [Related packages](#related-packages)
10* [Blog posts](#blog-posts)
10* [Blog posts](#blog-posts)
Setup.hsnew file+6
@@ -0,0 +1,6 @@
1+module Main (main) where
2+
3+import Distribution.Simple
4+
5+main :: IO ()
6+main = defaultMain
cabal.projectdeleted−4
@@ -1,4 +0,0 @@
1−packages: .
2−tests: True
3−benchmarks: True
4−constraints: req +dev
httpbin-tests/Network/HTTP/ReqSpec.hs+42−86
@@ -8,25 +8,24 @@
8module Network.HTTP.ReqSpec (spec) where
8module Network.HTTP.ReqSpec (spec) where
9
9
10import Control.Exception
10import Control.Exception
11−import Control.Monad (forM_)
11+import Control.Monad.Reader
12import Control.Monad.Trans.Control
12import Control.Monad.Trans.Control
13import Data.Aeson (ToJSON (..), Value (..), object, (.=))
13import Data.Aeson (ToJSON (..), Value (..), object, (.=))
14−import Data.Aeson qualified as A
14+import qualified Data.Aeson as A
15−import Data.Aeson.KeyMap qualified as Aeson.KeyMap
15+import qualified Data.Aeson.KeyMap as Aeson.KeyMap
16−import Data.ByteString qualified as B
16+import qualified Data.ByteString as B
17−import Data.ByteString.Lazy qualified as BL
17+import qualified Data.ByteString.Lazy as BL
18import Data.Functor.Identity (runIdentity)
18import Data.Functor.Identity (runIdentity)
19import Data.Maybe (fromJust)
19import Data.Maybe (fromJust)
20import Data.Proxy
20import Data.Proxy
21import Data.Text (Text)
21import Data.Text (Text)
22−import Data.Text qualified as T
22+import qualified Data.Text as T
23−import Data.Text.Encoding qualified as T
23+import qualified Data.Text.Encoding as T
24−import Data.Text.IO qualified as TIO
24+import qualified Data.Text.IO as TIO
25−import Network.HTTP.Client qualified as L
25+import qualified Network.HTTP.Client as L
26−import Network.HTTP.Client.MultipartFormData qualified as LM
26+import qualified Network.HTTP.Client.MultipartFormData as LM
27−import Network.HTTP.Req hiding (req)
27+import Network.HTTP.Req
28−import Network.HTTP.Req qualified as Req
29−import Network.HTTP.Types qualified as Y
28+import qualified Network.HTTP.Types as Y
30import Test.Hspec
29import Test.Hspec
31import Test.QuickCheck
30import Test.QuickCheck
32
31
@@ -50,11 +49,6 @@ spec = do
50 blindlyThrowing (req GET httpbin NoReqBody ignoreResponse mempty)
49 blindlyThrowing (req GET httpbin NoReqBody ignoreResponse mempty)
51 `shouldThrow` anyException
50 `shouldThrow` anyException
52
51
53− describe "isStatusCodeException" $
54− it "extracts non-2xx response" $
55− req GET (httpbin /: "foo") NoReqBody ignoreResponse mempty
56− `shouldThrow` selector404ByStatusCodeException
57−
58 describe "receiving user-agent header back" $
52 describe "receiving user-agent header back" $
59 it "works" $ do
53 it "works" $ do
60 r <-
54 r <-
@@ -85,7 +79,8 @@ spec = do
85 .= object
79 .= object
86 [ "Accept-Encoding" .= ("gzip" :: Text),
80 [ "Accept-Encoding" .= ("gzip" :: Text),
87 "Foo" .= ("bar" :: Text),
81 "Foo" .= ("bar" :: Text),
88− "Baz" .= ("quux" :: Text)
82+ "Baz" .= ("quux" :: Text),
83+ "Host" .= ("httpbin.org" :: Text)
89 ]
84 ]
90 ]
85 ]
91 responseStatusCode r `shouldBe` 200
86 responseStatusCode r `shouldBe` 200
@@ -97,10 +92,11 @@ spec = do
97 (stripFunnyHeaders . stripOrigin) (responseBody r)
92 (stripFunnyHeaders . stripOrigin) (responseBody r)
98 `shouldBe` object
93 `shouldBe` object
99 [ "args" .= emptyObject,
94 [ "args" .= emptyObject,
100− "url" .= ("http://localhost:1234/get" :: Text),
95+ "url" .= ("https://httpbin.org/get" :: Text),
101 "headers"
96 "headers"
102 .= object
97 .= object
103− [ "Accept-Encoding" .= ("gzip" :: Text)
98+ [ "Accept-Encoding" .= ("gzip" :: Text),
99+ "Host" .= ("httpbin.org" :: Text)
104 ]
100 ]
105 ]
101 ]
106 responseHeader r "Content-Type" `shouldBe` return "application/json"
102 responseHeader r "Content-Type" `shouldBe` return "application/json"
@@ -117,11 +113,12 @@ spec = do
117 [ "args" .= emptyObject,
113 [ "args" .= emptyObject,
118 "json" .= text,
114 "json" .= text,
119 "data" .= reflected,
115 "data" .= reflected,
120− "url" .= ("http://localhost:1234/post" :: Text),
116+ "url" .= ("https://httpbin.org/post" :: Text),
121 "headers"
117 "headers"
122 .= object
118 .= object
123 [ "Content-Type" .= ("application/json; charset=utf-8" :: Text),
119 [ "Content-Type" .= ("application/json; charset=utf-8" :: Text),
124 "Accept-Encoding" .= ("gzip" :: Text),
120 "Accept-Encoding" .= ("gzip" :: Text),
121+ "Host" .= ("httpbin.org" :: Text),
125 "Content-Length" .= show (T.length reflected)
122 "Content-Length" .= show (T.length reflected)
126 ],
123 ],
127 "files" .= emptyObject,
124 "files" .= emptyObject,
@@ -145,11 +142,12 @@ spec = do
145 [ "args" .= emptyObject,
142 [ "args" .= emptyObject,
146 "json" .= Null,
143 "json" .= Null,
147 "data" .= ("" :: Text),
144 "data" .= ("" :: Text),
148− "url" .= ("http://localhost:1234/post" :: Text),
145+ "url" .= ("https://httpbin.org/post" :: Text),
149 "headers"
146 "headers"
150 .= object
147 .= object
151 [ "Content-Type" .= T.decodeUtf8 contentType,
148 [ "Content-Type" .= T.decodeUtf8 contentType,
152 "Accept-Encoding" .= ("gzip" :: Text),
149 "Accept-Encoding" .= ("gzip" :: Text),
150+ "Host" .= ("httpbin.org" :: Text),
153 "Content-Length" .= ("242" :: Text)
151 "Content-Length" .= ("242" :: Text)
154 ],
152 ],
155 "files" .= emptyObject,
153 "files" .= emptyObject,
@@ -174,10 +172,11 @@ spec = do
174 [ "args" .= emptyObject,
172 [ "args" .= emptyObject,
175 "json" .= Null,
173 "json" .= Null,
176 "data" .= contents,
174 "data" .= contents,
177− "url" .= ("http://localhost:1234/patch" :: Text),
175+ "url" .= ("https://httpbin.org/patch" :: Text),
178 "headers"
176 "headers"
179 .= object
177 .= object
180 [ "Accept-Encoding" .= ("gzip" :: Text),
178 [ "Accept-Encoding" .= ("gzip" :: Text),
179+ "Host" .= ("httpbin.org" :: Text),
181 "Content-Length" .= show (T.length contents)
180 "Content-Length" .= show (T.length contents)
182 ],
181 ],
183 "files" .= emptyObject,
182 "files" .= emptyObject,
@@ -199,11 +198,12 @@ spec = do
199 [ "args" .= emptyObject,
198 [ "args" .= emptyObject,
200 "json" .= Null,
199 "json" .= Null,
201 "data" .= ("" :: Text),
200 "data" .= ("" :: Text),
202− "url" .= ("http://localhost:1234/put" :: Text),
201+ "url" .= ("https://httpbin.org/put" :: Text),
203 "headers"
202 "headers"
204 .= object
203 .= object
205 [ "Content-Type" .= ("application/x-www-form-urlencoded" :: Text),
204 [ "Content-Type" .= ("application/x-www-form-urlencoded" :: Text),
206 "Accept-Encoding" .= ("gzip" :: Text),
205 "Accept-Encoding" .= ("gzip" :: Text),
206+ "Host" .= ("httpbin.org" :: Text),
207 "Content-Length" .= ("18" :: Text)
207 "Content-Length" .= ("18" :: Text)
208 ],
208 ],
209 "files" .= emptyObject,
209 "files" .= emptyObject,
@@ -301,7 +301,7 @@ spec = do
301 (httpbin /: "basic-auth" /~ user /~ password)
301 (httpbin /: "basic-auth" /~ user /~ password)
302 NoReqBody
302 NoReqBody
303 ignoreResponse
303 ignoreResponse
304− (basicAuthUnsafe (T.encodeUtf8 user) (T.encodeUtf8 password))
304+ (basicAuth (T.encodeUtf8 user) (T.encodeUtf8 password))
305 responseStatusCode r `shouldBe` 200
305 responseStatusCode r `shouldBe` 200
306 responseStatusMessage r `shouldBe` "OK"
306 responseStatusMessage r `shouldBe` "OK"
307
307
@@ -401,28 +401,8 @@ blindlyThrowing = runReq defaultHttpConfig {httpConfigCheckResponse = doit}
401 doit _ _ = error "Oops!"
401 doit _ _ = error "Oops!"
402
402
403-- | 'Url' representing <https://httpbin.org>.
403-- | 'Url' representing <https://httpbin.org>.
404−httpbin :: Url 'Http
404+httpbin :: Url 'Https
405−httpbin = http "localhost"
405+httpbin = https "httpbin.org"
406−
407−req ::
408− ( MonadHttp m,
409− HttpMethod method,
410− HttpBody body,
411− HttpResponse response,
412− HttpBodyAllowed (AllowsBody method) (ProvidesBody body)
413− ) =>
414− method ->
415− Url scheme ->
416− body ->
417− Proxy response ->
418− Option scheme ->
419− m response
420−req method url body responseProxy options =
421− Req.req method url body responseProxy (options <> defaultOptions)
422−
423−-- | Options to apply by default.
424−defaultOptions :: Option scheme
425−defaultOptions = port 1234
426
406
427-- | Remove “origin” field from JSON value. Origin may change, we don't want
407-- | Remove “origin” field from JSON value. Origin may change, we don't want
428-- to depend on that.
408-- to depend on that.
@@ -432,36 +412,19 @@ stripOrigin value = value
432
412
433-- | Remove funny headers that might break the tests.
413-- | Remove funny headers that might break the tests.
434stripFunnyHeaders :: Value -> Value
414stripFunnyHeaders :: Value -> Value
435−stripFunnyHeaders = \case
415+stripFunnyHeaders (Object m) =
436− Object m ->
437− Object
438− ( runIdentity
439− ( Aeson.KeyMap.alterF
440− (pure . fmap stripFunnyHeaders')
441− "headers"
442− m
443− )
444− )
445− value -> value
446−
447−-- | Similar to 'stripFunnyHeaders', but acts directly on the argument
448−-- without trying to access its "headers" field.
449−stripFunnyHeaders' :: Value -> Value
450−stripFunnyHeaders' = \case
451− Object p ->
452− Object $
453− Aeson.KeyMap.filterWithKey
416+ let f (Object p) = Object $ Aeson.KeyMap.filterWithKey (\k _ -> k `elem` hs) p
454− (\k _ -> k `elem` whitelistedHeaders)
455− p
456− value -> value
417+ f value = value
457− where
418+ hs =
458− whitelistedHeaders =
459− [ "Content-Type",
419+ [ "Content-Type",
460− "Accept-Encoding",
420+ "Accept-Encoding",
421+ "Host",
461− "Content-Length",
422+ "Content-Length",
462− "Foo",
423+ "Foo",
463− "Baz"
424+ "Baz"
464− ]
425+ ]
426+ in Object (runIdentity (Aeson.KeyMap.alterF (pure . fmap f) "headers" m))
427+stripFunnyHeaders value = value
465
428
466-- | This is a complete test case that makes use of <https://httpbin.org> to
429-- | This is a complete test case that makes use of <https://httpbin.org> to
467-- get various response status codes.
430-- get various response status codes.
@@ -491,19 +454,12 @@ selector404
491 L.responseStatus response == Y.status404 && not (B.null chunk)
454 L.responseStatus response == Y.status404 && not (B.null chunk)
492selector404 _ = False
455selector404 _ = False
493
456
494−-- | Same as 'selector404' except that it uses 'isStatusCodeException'.
495−selector404ByStatusCodeException :: HttpException -> Bool
496−selector404ByStatusCodeException e =
497− case isStatusCodeException e of
498− Nothing -> False
499− Just r -> responseStatusCode r == 404
500−
501-- | The empty JSON 'Object'.
457-- | The empty JSON 'Object'.
502emptyObject :: Value
458emptyObject :: Value
503emptyObject = Object Aeson.KeyMap.empty
459emptyObject = Object Aeson.KeyMap.empty
504
460
505-- | Get a rendered JSON value as 'Text'.
461-- | Get a rendered JSON value as 'Text'.
506−reflectJSON :: (ToJSON a) => a -> Text
462+reflectJSON :: ToJSON a => a -> Text
507reflectJSON = T.decodeUtf8 . BL.toStrict . A.encode
463reflectJSON = T.decodeUtf8 . BL.toStrict . A.encode
508
464
509-- | Clarify to the type checker that the inner computation is in the 'IO'
465-- | Clarify to the type checker that the inner computation is in the 'IO'
pure-tests/Network/HTTP/ReqSpec.hs+18−18
@@ -13,41 +13,41 @@
13
13
14module Network.HTTP.ReqSpec (spec) where
14module Network.HTTP.ReqSpec (spec) where
15
15
16−import Blaze.ByteString.Builder qualified as BB
16+import qualified Blaze.ByteString.Builder as BB
17import Control.Exception (throwIO)
17import Control.Exception (throwIO)
18import Control.Monad
18import Control.Monad
19import Control.Retry
19import Control.Retry
20import Data.Aeson (ToJSON (..))
20import Data.Aeson (ToJSON (..))
21−import Data.Aeson qualified as A
21+import qualified Data.Aeson as A
22import Data.ByteString (ByteString)
22import Data.ByteString (ByteString)
23−import Data.ByteString qualified as B
23+import qualified Data.ByteString as B
24−import Data.ByteString.Char8 qualified as B8
24+import qualified Data.ByteString.Char8 as B8
25−import Data.ByteString.Lazy qualified as BL
25+import qualified Data.ByteString.Lazy as BL
26−import Data.CaseInsensitive qualified as CI
26+import qualified Data.CaseInsensitive as CI
27import Data.Either (isRight)
27import Data.Either (isRight)
28−import Data.List.NonEmpty qualified as NE
28+import qualified Data.List.NonEmpty as NE
29import Data.Maybe (fromJust, fromMaybe, isJust, isNothing)
29import Data.Maybe (fromJust, fromMaybe, isJust, isNothing)
30import Data.Proxy
30import Data.Proxy
31import Data.Text (Text)
31import Data.Text (Text)
32−import Data.Text qualified as T
32+import qualified Data.Text as T
33−import Data.Text.Encoding qualified as T
33+import qualified Data.Text.Encoding as T
34import Data.Time
34import Data.Time
35import Data.Typeable (Typeable, eqT)
35import Data.Typeable (Typeable, eqT)
36import GHC.Exts (IsList (..))
36import GHC.Exts (IsList (..))
37import GHC.Generics
37import GHC.Generics
38−import Language.Haskell.TH qualified as TH
38+import qualified Language.Haskell.TH as TH
39−import Language.Haskell.TH.Quote qualified as TH
39+import qualified Language.Haskell.TH.Quote as TH
40−import Network.HTTP.Client qualified as L
40+import qualified Network.HTTP.Client as L
41import Network.HTTP.Req
41import Network.HTTP.Req
42−import Network.HTTP.Types qualified as Y
42+import qualified Network.HTTP.Types as Y
43−import Network.HTTP.Types.Header qualified as Y
43+import qualified Network.HTTP.Types.Header as Y
44import Test.Hspec
44import Test.Hspec
45import Test.Hspec.Core.Spec (SpecM)
45import Test.Hspec.Core.Spec (SpecM)
46import Test.QuickCheck
46import Test.QuickCheck
47import Text.URI (URI)
47import Text.URI (URI)
48−import Text.URI qualified as URI
48+import qualified Text.URI as URI
49−import Text.URI.QQ qualified as QQ
49+import qualified Text.URI.QQ as QQ
50−import Web.FormUrlEncoded qualified as F
50+import qualified Web.FormUrlEncoded as F
51
51
52spec :: Spec
52spec :: Spec
53spec = do
53spec = do
@@ -413,7 +413,7 @@ spec = do
413 -- 'Https, Option _) type checks, so we can catch if the type of scheme
413 -- 'Https, Option _) type checks, so we can catch if the type of scheme
414 -- is unspecified.
414 -- is unspecified.
415 let testTypeOfQuoterResult ::
415 let testTypeOfQuoterResult ::
416− forall a s. (Typeable a) => (a, Option s) -> Bool
416+ forall a s. Typeable a => (a, Option s) -> Bool
417 testTypeOfQuoterResult _ = isJust $ eqT @a @(Url 'Https)
417 testTypeOfQuoterResult _ = isJust $ eqT @a @(Url 'Https)
418 in property $ testTypeOfQuoterResult [urlQ|https://example.org/|]
418 in property $ testTypeOfQuoterResult [urlQ|https://example.org/|]
419 it "doesn't work for invalid urls" $
419 it "doesn't work for invalid urls" $
req.cabal+43−43
@@ -1,11 +1,11 @@
1cabal-version: 2.4
1cabal-version: 2.4
2name: req
2name: req
3−version: 3.13.4
3+version: 3.10.0
4license: BSD-3-Clause
4license: BSD-3-Clause
5license-file: LICENSE.md
5license-file: LICENSE.md
6maintainer: Mark Karpov <markkarpov92@gmail.com>
6maintainer: Mark Karpov <markkarpov92@gmail.com>
7author: Mark Karpov <markkarpov92@gmail.com>
7author: Mark Karpov <markkarpov92@gmail.com>
8−tested-with: ghc ==9.6.3 ghc ==9.8.2 ghc ==9.10.1
8+tested-with: ghc ==8.10.7 ghc ==9.0.2 ghc ==9.2.1
9homepage: https://github.com/mrkkrp/req
9homepage: https://github.com/mrkkrp/req
10bug-reports: https://github.com/mrkkrp/req/issues
10bug-reports: https://github.com/mrkkrp/req/issues
11synopsis: HTTP client library
11synopsis: HTTP client library
@@ -31,70 +31,71 @@ flag dev
31
31
32library
32library
33 exposed-modules: Network.HTTP.Req
33 exposed-modules: Network.HTTP.Req
34− default-language: GHC2021
34+ default-language: Haskell2010
35 build-depends:
35 build-depends:
36 aeson >=0.9 && <3,
36 aeson >=0.9 && <3,
37 authenticate-oauth >=1.5 && <1.8,
37 authenticate-oauth >=1.5 && <1.8,
38− base >=4.15 && <5,
38+ base >=4.13 && <5.0,
39 blaze-builder >=0.3 && <0.5,
39 blaze-builder >=0.3 && <0.5,
40− bytestring >=0.10.8 && <0.13,
40+ bytestring >=0.10.8 && <0.12,
41 case-insensitive >=0.2 && <1.3,
41 case-insensitive >=0.2 && <1.3,
42− containers >=0.5 && <0.8,
43− crypton-connection >=0.4.2 && <0.5,
42+ connection >=0.2.2 && <0.4,
44− data-default-class >=0.2.0.0,
45 exceptions >=0.6 && <0.11,
43 exceptions >=0.6 && <0.11,
46− http-api-data >=0.2 && <0.7,
44+ http-api-data >=0.2 && <0.5,
47− http-client >=0.7.13.1 && <0.8,
45+ http-client >=0.7 && <0.8,
48 http-client-tls >=0.3.2 && <0.4,
46 http-client-tls >=0.3.2 && <0.4,
49− http-types >=0.8 && <10,
47+ http-types >=0.8 && <10.0,
50 modern-uri >=0.3 && <0.4,
48 modern-uri >=0.3 && <0.4,
51 monad-control >=1.0 && <1.1,
49 monad-control >=1.0 && <1.1,
52 mtl >=2.0 && <3.0,
50 mtl >=2.0 && <3.0,
53 retry >=0.8 && <0.10,
51 retry >=0.8 && <0.10,
54− template-haskell >=2.19 && <2.23,
52+ template-haskell >=2.14 && <2.19,
55− text >=0.2 && <2.2,
53+ text >=0.2 && <2.1,
54+ time >=1.2 && <1.13,
56− transformers >=0.5.3.0 && <0.7,
55+ transformers >=0.5.3.0 && <0.6,
57 transformers-base,
56 transformers-base,
58 unliftio-core >=0.1.1 && <0.3
57 unliftio-core >=0.1.1 && <0.3
59
58
60 if flag(dev)
59 if flag(dev)
61− ghc-options:
60+ ghc-options: -O0 -Wall -Werror
62− -Wall -Werror -Wpartial-fields -Wunused-packages
63− -Wno-unused-imports
64
61
65 else
62 else
66 ghc-options: -O2 -Wall
63 ghc-options: -O2 -Wall
67
64
65+ if flag(dev)
66+ ghc-options:
67+ -Wcompat -Wincomplete-record-updates -Wincomplete-uni-patterns
68+ -Wnoncanonical-monad-instances
69+
68test-suite pure-tests
70test-suite pure-tests
69 type: exitcode-stdio-1.0
71 type: exitcode-stdio-1.0
70 main-is: Spec.hs
72 main-is: Spec.hs
71− build-tool-depends: hspec-discover:hspec-discover >=2 && <3
73+ build-tool-depends: hspec-discover:hspec-discover >=2.0 && <3.0
72 hs-source-dirs: pure-tests
74 hs-source-dirs: pure-tests
73 other-modules: Network.HTTP.ReqSpec
75 other-modules: Network.HTTP.ReqSpec
74− default-language: GHC2021
76+ default-language: Haskell2010
75 build-depends:
77 build-depends:
76− QuickCheck >=2.7 && <3,
78+ QuickCheck >=2.7 && <3.0,
77 aeson >=0.9 && <3,
79 aeson >=0.9 && <3,
78− base >=4.15 && <5.0,
80+ base >=4.13 && <5.0,
79 blaze-builder >=0.3 && <0.5,
81 blaze-builder >=0.3 && <0.5,
80− bytestring >=0.10.8 && <0.13,
82+ bytestring >=0.10.8 && <0.12,
81 case-insensitive >=0.2 && <1.3,
83 case-insensitive >=0.2 && <1.3,
82− hspec >=2.0 && <3,
84+ hspec >=2.0 && <3.0,
83− hspec-core >=2.0 && <3,
85+ hspec-core >=2.0 && <3.0,
84− http-api-data >=0.2 && <0.7,
86+ http-api-data >=0.2 && <0.5,
85 http-client >=0.7 && <0.8,
87 http-client >=0.7 && <0.8,
86− http-types >=0.8 && <10,
88+ http-types >=0.8 && <10.0,
87 modern-uri >=0.3 && <0.4,
89 modern-uri >=0.3 && <0.4,
90+ mtl >=2.0 && <3.0,
88 req,
91 req,
89 retry >=0.8 && <0.10,
92 retry >=0.8 && <0.10,
90− template-haskell >=2.19 && <2.23,
93+ template-haskell >=2.14 && <2.19,
91− text >=0.2 && <2.2,
94+ text >=0.2 && <2.1,
92− time >=1.2 && <1.15
95+ time >=1.2 && <1.13
93
96
94 if flag(dev)
97 if flag(dev)
95− ghc-options:
98+ ghc-options: -O0 -Wall -Werror
96− -Wall -Werror -Wredundant-constraints -Wpartial-fields
97− -Wunused-packages
98
99
99 else
100 else
100 ghc-options: -O2 -Wall
101 ghc-options: -O2 -Wall
@@ -102,26 +103,25 @@ test-suite pure-tests
102test-suite httpbin-tests
103test-suite httpbin-tests
103 type: exitcode-stdio-1.0
104 type: exitcode-stdio-1.0
104 main-is: Spec.hs
105 main-is: Spec.hs
105− build-tool-depends: hspec-discover:hspec-discover >=2 && <3
106+ build-tool-depends: hspec-discover:hspec-discover >=2.0 && <3.0
106 hs-source-dirs: httpbin-tests
107 hs-source-dirs: httpbin-tests
107 other-modules: Network.HTTP.ReqSpec
108 other-modules: Network.HTTP.ReqSpec
108− default-language: GHC2021
109+ default-language: Haskell2010
109 build-depends:
110 build-depends:
110− QuickCheck >=2.7 && <3,
111+ QuickCheck >=2.7 && <3.0,
111 aeson >=2 && <3,
112 aeson >=2 && <3,
112− base >=4.15 && <5,
113+ base >=4.13 && <5.0,
113− bytestring >=0.10.8 && <0.13,
114+ bytestring >=0.10.8 && <0.12,
114 hspec >=2.0 && <3.0,
115 hspec >=2.0 && <3.0,
115 http-client >=0.7 && <0.8,
116 http-client >=0.7 && <0.8,
116− http-types >=0.8 && <10,
117+ http-types >=0.8 && <10.0,
117 monad-control >=1.0 && <1.1,
118 monad-control >=1.0 && <1.1,
119+ mtl >=2.0 && <3.0,
118 req,
120 req,
119− text >=0.2 && <2.2
121+ text >=0.2 && <2.1
120
122
121 if flag(dev)
123 if flag(dev)
122− ghc-options:
124+ ghc-options: -O0 -Wall -Werror
123− -Wall -Werror -Wredundant-constraints -Wpartial-fields
124− -Wunused-packages
125
125
126 else
126 else
127− buildable: False
127+ ghc-options: -O2 -Wall