req 3.9.0 → 3.9.1
raw patch · 6 files changed
+122/−255 lines, 6 filesdep ~authenticate-oauthdep ~basedep ~http-client
Dependency ranges changed: authenticate-oauth, base, http-client, retry, template-haskell, time
Files
- CHANGELOG.md +4/−0
- Network/HTTP/Req.hs +73/−97
- README.md +24/−118
- httpbin-tests/Network/HTTP/ReqSpec.hs +4/−10
- pure-tests/Network/HTTP/ReqSpec.hs +2/−11
- req.cabal +15/−19
CHANGELOG.md view
@@ -1,3 +1,7 @@+## Req 3.9.1++* Builds with GHC 9.0.+ ## Req 3.9.0 * The `useHttpURI` and `useHttpsURI` functions now preserve trailing
Network/HTTP/Req.hs view
@@ -30,61 +30,40 @@ -- -- The documentation below is structured in such a way that the most -- important information is presented first: you learn how to do HTTP--- requests, how to embed them in any monad you have, and then it gives you+-- requests, how to embed them in the monad you have, and then it gives you -- details about less-common things you may want to know about. The -- documentation is written with sufficient coverage of details and -- examples, and it's designed to be a complete tutorial on its own. ----- /(A modest intro goes here, click on 'req' to start making requests.)/--- -- === About the library ----- Req is an easy-to-use, type-safe, expandable, high-level HTTP client--- library that just works without any fooling around.------ What does the phrase “easy-to-use” mean? It means that the library is--- designed to be beginner-friendly so it's simple to add to your monad--- stack, intuitive to work with, well-documented, and does not get in your--- way. Doing HTTP requests is a common task and Haskell library for this--- should be very approachable and clear to beginners, thus certain--- compromises were made. For example, one cannot currently modify--- 'L.ManagerSettings' of the default manager because the library always--- uses the same implicit global manager for simplicity and maximal--- connection sharing. There is a way to use your own manager with different--- settings, but it requires a bit more typing.+-- Req is an HTTP client library that attempts to be easy-to-use, type-safe,+-- and expandable. ----- “Type-safe” means that the library is protective and eliminates certain--- classes of errors. For example, we have correct-by-construction 'Url's,--- it's guaranteed that the user does not send the request body when using--- methods like 'GET' or 'OPTIONS', and the amount of implicit assumptions--- is minimized by making the user specify his\/her intentions in an--- explicit form (for example, it's not possible to avoid specifying the--- body or method of request). Authentication methods that assume HTTPS--- force the user to use HTTPS at the type level. The library also carefully--- hides underlying types from the lower-level @http-client@ package because--- those types are not safe enough (for example 'L.Request' is an instance--- of 'Data.String.IsString' and, if it's malformed, it will blow up at--- run-time).+-- “Easy-to-use” means that the library is designed to be beginner-friendly+-- so it's simple to add to your monad stack, intuitive to work with,+-- well-documented, and does not get in your way. Doing HTTP requests is a+-- common task and a Haskell library for this should be approachable and+-- clear to beginners, thus certain compromises were made. For example, one+-- cannot currently modify 'L.ManagerSettings' of the default manager+-- because the library always uses the same implicit global manager for+-- simplicity and maximal connection sharing. There is a way to use your own+-- manager with different settings, but it requires more typing. ----- “Expandable” refers to the ability of the library to be expanded without--- having to resort to ugly hacking. For example, it's possible to define--- your own HTTP methods, create new ways to construct the body of a--- request, create new authorization options, perform a request in a--- different way, and create your own methods to parse and represent a--- response. As the user extends the library to satisfy his\/her special--- needs, the new solutions will work just like the built-ins. However, all--- of the common cases are also covered by the library out-of-the-box.+-- “Type-safe” means that the library tries to eliminate certain classes of+-- errors. For example, we have correct-by-construction URLs; it is+-- guaranteed that the user does not send the request body when using+-- methods like GET or OPTIONS, and the amount of implicit assumptions is+-- minimized by making the user specify their intentions in an explicit+-- form. For example, it's not possible to avoid specifying the body or the+-- method of a request. Authentication methods that assume HTTPS force the+-- user to use HTTPS at the type level. ----- “High-level” means that there are less details to worry about. The--- library is a result of my experiences as a Haskell consultant. Working--- for several clients, who had very different projects, showed me that the--- library should adapt easily to any particular style of writing Haskell--- applications. For example, some people prefer throwing exceptions, while--- others are concerned with purity. Just define 'handleHttpException'--- accordingly when making your monad instance of 'MonadHttp' and it will--- play together seamlessly. Finally, the library cuts down boilerplate--- considerably, and helps you write concise, easy to read, and maintainable--- code.+-- “Expandable” refers to the ability to create new components without+-- having to resort to hacking. For example, it's possible to define your+-- own HTTP methods, create new ways to construct the body of a request,+-- create new authorization options, perform a request in a different way,+-- and create your own methods to parse a response. -- -- === Using with other libraries --@@ -303,7 +282,7 @@ -- -- @body@ is a body option such as 'NoReqBody' or 'ReqBodyJson'. The -- tutorial has a section about HTTP bodies, but usage is very--- straightforward and should be clear from the examples below.+-- straightforward and should be clear from the examples. -- -- @response@ is a type hint how to make and interpret response of an HTTP -- request. Out-of-the-box it can be the following:@@ -588,9 +567,9 @@ nubHeaders <> getRequestMod options <> getRequestMod config- <> getRequestMod (Womb body :: Womb "body" body)+ <> getRequestMod (Tagged body :: Tagged "body" body) <> getRequestMod url- <> getRequestMod (Womb method :: Womb "method" method)+ <> getRequestMod (Tagged method :: Tagged "method" method) request <- finalizeRequest options request' withReqManager (m request) @@ -600,10 +579,10 @@ withReqManager :: MonadIO m => (L.Manager -> m a) -> m a withReqManager m = liftIO (readIORef globalManager) >>= m --- | Global 'L.Manager' that 'req' uses. Here we just go with the default--- settings, so users don't need to deal with this manager stuff at all, but--- when we create a request, instance 'HttpConfig' can affect the default--- settings via 'getHttpConfig'.+-- | The global 'L.Manager' that 'req' uses. Here we just go with the+-- default settings, so users don't need to deal with this manager stuff at+-- all, but when we create a request, instance 'HttpConfig' can affect the+-- default settings via 'getHttpConfig'. -- -- A note about safety, in case 'unsafePerformIO' looks suspicious to you. -- The value of 'globalManager' is named and lives on top level. This means@@ -634,8 +613,8 @@ -- When writing a library, keep your API polymorphic in terms of -- 'MonadHttp', only define instance of 'MonadHttp' in final application. -- Another option is to use a @newtype@-wrapped monad stack and define--- 'MonadHttp' for it. As of version /0.4.0/, the 'Req' monad that follows--- this strategy is provided out-of-the-box (see below).+-- 'MonadHttp' for it. As of the version /0.4.0/, the 'Req' monad that+-- follows this strategy is provided out-of-the-box (see below). -- | A type class for monads that support performing HTTP requests. -- Typically, you only need to define the 'handleHttpException' method@@ -648,17 +627,16 @@ -- 'Control.Monad.Except.throwError'. handleHttpException :: HttpException -> m a - -- | Return 'HttpConfig' to be used when performing HTTP requests. Default- -- implementation returns its 'def' value, which is described in the- -- documentation for the type. Common usage pattern with manually defined- -- 'getHttpConfig' is to return some hard-coded value, or a value+ -- | Return the 'HttpConfig' to be used when performing HTTP requests.+ -- Default implementation returns its 'def' value, which is described in+ -- the documentation for the type. Common usage pattern with manually+ -- defined 'getHttpConfig' is to return some hard-coded value, or a value -- extracted from 'Control.Monad.Reader.MonadReader' if a more flexible -- approach to configuration is desirable. getHttpConfig :: m HttpConfig getHttpConfig = return defaultHttpConfig --- | 'HttpConfig' contains general and default settings to be used when--- making HTTP requests.+-- | 'HttpConfig' contains settings to be used when making HTTP requests. data HttpConfig = HttpConfig { -- | Proxy to use. By default values of @HTTP_PROXY@ and @HTTPS_PROXY@ -- environment variables are respected, this setting overwrites them.@@ -729,7 +707,7 @@ } deriving (Typeable) --- | Default value of 'HttpConfig'.+-- | The default value of 'HttpConfig'. -- -- @since 2.0.0 defaultHttpConfig :: HttpConfig@@ -773,7 +751,7 @@ LI.requestManagerOverride = httpConfigAltManager } --- | A monad that allows to run 'req' in any 'IO'-enabled monad without+-- | A monad that allows us to run 'req' in any 'IO'-enabled monad without -- having to define new instances. -- -- @since 0.4.0@@ -810,7 +788,7 @@ getHttpConfig = Req ask -- | Run a computation in the 'Req' monad with the given 'HttpConfig'. In--- case of exceptional situation an 'HttpException' will be thrown.+-- the case of an exceptional situation an 'HttpException' will be thrown. -- -- @since 0.4.0 runReq ::@@ -919,7 +897,7 @@ -- | Return name of the method as a 'ByteString'. httpMethodName :: Proxy a -> ByteString -instance HttpMethod method => RequestComponent (Womb "method" method) where+instance HttpMethod method => RequestComponent (Tagged "method" method) where getRequestMod _ = Endo $ \x -> x {L.method = httpMethodName (Proxy :: Proxy method)} @@ -966,7 +944,7 @@ type role Url nominal -- With template-haskell >=2.15 and text >=1.2.4 Lift can be derived, however--- the derived lift forgets the type of scheme.+-- the derived lift forgets the type of the scheme. instance Typeable scheme => TH.Lift (Url scheme) where lift url = TH.dataToExpQ (fmap liftText . cast) url `TH.sigE` case url of@@ -975,8 +953,10 @@ where liftText t = TH.AppE (TH.VarE 'T.pack) <$> TH.lift (T.unpack t) -#if MIN_VERSION_template_haskell(2,16,0)- liftTyped url = TH.TExp <$> TH.lift url+#if MIN_VERSION_template_haskell(2,17,0)+ liftTyped = TH.Code . TH.unsafeTExpCoerce . TH.lift+#elif MIN_VERSION_template_haskell(2,16,0)+ liftTyped = TH.unsafeTExpCoerce . TH.lift #endif -- | Given host name, produce a 'Url' which has “http” as its scheme and@@ -989,14 +969,14 @@ https :: Text -> Url 'Https https = Url Https . pure --- | Grow given 'Url' appending a single path segment to it. Note that the+-- | Grow a given 'Url' appending a single path segment to it. Note that the -- path segment can be of any type that is an instance of 'ToHttpApiData'. infixl 5 /~ (/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path) --- | Type-constrained version of @('/~')@ to remove ambiguity in the cases+-- | A type-constrained version of @('/~')@ to remove ambiguity in the cases -- when next URL piece is a 'Data.Text.Text' literal. infixl 5 /: @@ -1172,10 +1152,10 @@ instance HttpBody NoReqBody where getRequestBody NoReqBody = L.RequestBodyBS B.empty --- | This body option allows to use a JSON object as request body—probably--- the most popular format right now. Just wrap a data type that is an--- instance of 'ToJSON' type class and you are done: it will be converted to--- JSON and inserted as request body.+-- | This body option allows us to use a JSON object as the request+-- body—probably the most popular format right now. Just wrap a data type+-- that is an instance of 'ToJSON' type class and you are done: it will be+-- converted to JSON and inserted as request body. -- -- This body option sets the @Content-Type@ header to @\"application/json; -- charset=utf-8\"@ value.@@ -1186,7 +1166,7 @@ getRequestContentType _ = pure "application/json; charset=utf-8" -- | This body option streams request body from a file. It is expected that--- the file size does not change during the streaming.+-- the file size does not change during streaming. -- -- Using of this body option does not set the @Content-Type@ header. newtype ReqBodyFile = ReqBodyFile FilePath@@ -1211,12 +1191,11 @@ instance HttpBody ReqBodyLbs where getRequestBody (ReqBodyLbs bs) = L.RequestBodyLBS bs --- | Form URL-encoded body. This can hold a collection of parameters which--- are encoded similarly to query parameters at the end of query string,--- with the only difference that they are stored in request body. The--- similarity is reflected in the API as well, as you can use the same--- combinators you would use to add query parameters: @('=:')@ and--- 'queryFlag'.+-- | URL-encoded body. This can hold a collection of parameters which are+-- encoded similarly to query parameters at the end of query string, with+-- the only difference that they are stored in request body. The similarity+-- is reflected in the API as well, as you can use the same combinators you+-- would use to add query parameters: @('=:')@ and 'queryFlag'. -- -- This body option sets the @Content-Type@ header to -- @\"application/x-www-form-urlencoded\"@ value.@@ -1302,9 +1281,6 @@ -- | This type function allows any HTTP body if method says it -- 'CanHaveBody'. When the method says it should have 'NoBody', the only -- body option to use is 'NoReqBody'.------ __Note__: users of GHC 8.0.1 and later will see a slightly more friendly--- error message when method does not allow a body and body is provided. type family HttpBodyAllowed (allowsBody :: CanHaveBody)@@ -1317,8 +1293,8 @@ TypeError ('Text "This HTTP method does not allow attaching a request body.") -instance HttpBody body => RequestComponent (Womb "body" body) where- getRequestMod (Womb body) = Endo $ \x ->+instance HttpBody body => RequestComponent (Tagged "body" body) where+ getRequestMod (Tagged body) = Endo $ \x -> x { L.requestBody = getRequestBody body, L.requestHeaders =@@ -1347,8 +1323,8 @@ = Option (Endo (Y.QueryText, L.Request)) (Maybe (L.Request -> IO L.Request)) -- NOTE 'QueryText' is just [(Text, Maybe Text)], we keep it along with--- Request to avoid appending to existing query string in request every--- time new parameter is added. Additional Maybe (L.Request -> IO+-- Request to avoid appending to an existing query string in request every+-- time new parameter is added. The additional Maybe (L.Request -> IO -- L.Request) is a finalizer that will be applied after all other -- transformations. This is for authentication methods that sign requests -- based on data in Request.@@ -1405,7 +1381,7 @@ (=:) :: (QueryParam param, ToHttpApiData a) => Text -> a -> param name =: value = queryParam name (pure value) --- | Construct a flag, that is, valueless query parameter. For example, in+-- | Construct a flag, that is, a valueless query parameter. For example, in -- the following URL @\"a\"@ is a flag, while @\"b\"@ is a query parameter -- with a value: --@@ -1595,7 +1571,7 @@ -- | Specify the port to connect to explicitly. Normally, 'Url' you use -- determines the default port: @80@ for HTTP and @443@ for HTTPS. This--- 'Option' allows to choose an arbitrary port overwriting the defaults.+-- 'Option' allows us to choose an arbitrary port overwriting the defaults. port :: Int -> Option scheme port n = withRequest $ \x -> x {L.port = n}@@ -1610,8 +1586,8 @@ -- -- > decompress (const True) decompress ::- -- | Predicate that is given MIME type, it- -- returns 'True' when content should be decompressed on the fly.+ -- | Predicate that is given MIME type, it returns 'True' when content+ -- should be decompressed on the fly. (ByteString -> Bool) -> Option scheme decompress f = withRequest $ \x ->@@ -1713,7 +1689,7 @@ ---------------------------------------------------------------------------- -- Helpers for response interpretations --- | Fetch beginning of response and return it together with new+-- | Fetch beginning of the response and return it together with a new -- @'L.Response' 'L.BodyReader'@ that can be passed to 'getHttpResponse' and -- such. grabPreview ::@@ -1825,9 +1801,9 @@ -- To create a new response interpretation you just need to make your data -- type an instance of the 'HttpResponse' type class. --- | A type class for response interpretations. It allows to describe how to--- consume response from a @'L.Response' 'L.BodyReader'@ and produce the--- final result that is to be returned to the user.+-- | A type class for response interpretations. It allows us to describe how+-- to consume the response from a @'L.Response' 'L.BodyReader'@ and produce+-- the final result that is to be returned to the user. class HttpResponse response where -- | The associated type is the type of body that can be extracted from an -- instance of 'HttpResponse'.@@ -1891,7 +1867,7 @@ -- method@ and @'HttpBody' body => 'RequestComponent' body@ when it decides -- which instance to use (i.e. the constraints are taken into account later, -- when instance is already chosen).-newtype Womb (tag :: Symbol) a = Womb a+newtype Tagged (tag :: Symbol) a = Tagged a -- | Exceptions that this library throws. data HttpException
README.md view
@@ -43,49 +43,33 @@ liftIO $ print (responseBody r :: Value) ``` -Req is an easy-to-use, type-safe, expandable, high-level HTTP client library-that just works without any fooling around.+Req is an HTTP client library that attempts to be easy-to-use, type-safe,+and expandable. -What does the phrase “easy-to-use” mean? It means that the library is-designed to be beginner-friendly so it's simple to add to your monad stack,-intuitive to work with, well-documented, and does not get in your way. Doing-HTTP requests is a common task and Haskell library for this should be very-approachable and clear to beginners, thus certain compromises were made. For-example, one cannot currently modify `ManagerSettings` of the default-manager because the library always uses the same implicit global manager for-simplicity and maximal connection sharing. There is a way to use your own-manager with different settings, but it requires a bit more typing.+“Easy-to-use” means that the library is designed to be beginner-friendly so+it's simple to add to your monad stack, intuitive to work with,+well-documented, and does not get in your way. Doing HTTP requests is a+common task and a Haskell library for this should be approachable and clear+to beginners, thus certain compromises were made. For example, one cannot+currently modify `ManagerSettings` of the default manager because the+library always uses the same implicit global manager for simplicity and+maximal connection sharing. There is a way to use your own manager with+different settings, but it requires more typing. -“Type-safe” means that the library is protective and eliminates certain-classes of errors. For example, we have correct-by-construction URLs, it's-guaranteed that the user does not send the request body when using methods-like GET or OPTIONS, and the amount of implicit assumptions is minimized by-making the user specify his/her intentions in an explicit form (for example,-it's not possible to avoid specifying the body or method of request).+“Type-safe” means that the library tries to eliminate certain classes of+errors. For example, we have correct-by-construction URLs; it is guaranteed+that the user does not send the request body when using methods like GET or+OPTIONS, and the amount of implicit assumptions is minimized by making the+user specify their intentions in an explicit form. For example, it's not+possible to avoid specifying the body or the method of a request. Authentication methods that assume HTTPS force the user to use HTTPS at the-type level. The library also carefully hides underlying types from the-lower-level `http-client` package because those types are not safe enough-(for example `Request` is an instance of `IsString` and, if it's malformed,-it will blow up at run-time).--“Expandable” refers to the ability to create new components for dealing with-HTTP without having to resort to ugly hacking. For example, it's possible to-define your own HTTP methods, create new ways to construct the body of a-request, create new authorization options, perform a request in a different-way, and create your own methods to parse and represent a response. As the-user extends the library to satisfy his/her special needs, the new solutions-will work just like the built-ins. However, all of the common cases are also-covered by the library out-of-the-box.+type level. -“High-level” means that there are less details to worry about. The library-is a result of my experiences as a Haskell consultant. Working for several-clients, who had very different projects, showed me that the library should-adapt easily to any particular style of writing Haskell applications. For-example, some people prefer throwing exceptions, while others are concerned-with purity. Just define `handleHttpException` accordingly when making your-monad instance of `MonadHttp` and it will play together seamlessly. Finally,-the library cuts down boilerplate considerably, and helps you write concise,-easy to read, and maintainable code.+“Expandable” refers to the ability to create new components without having+to resort to hacking. For example, it's possible to define your own HTTP+methods, create new ways to construct the body of a request, create new+authorization options, perform a request in a different way, and create your+own methods to parse a response. The library uses the following mature packages under the hood to guarantee you the best experience:@@ -95,88 +79,10 @@ * [`http-client-tls`](https://hackage.haskell.org/package/http-client-tls)—TLS (HTTPS) support for `http-client`. -It's important to note that since we leverage well-known libraries that the+It is important to note that since we leverage well-known libraries that the whole Haskell ecosystem uses, there is no risk in using Req. The machinery for performing requests is the same as with `http-conduit` and Wreq. The only difference is the API.--## Motivation and Req vs other libraries--*This section is my opinion and it contains criticisms of other well-known-libraries. If you're a user/fan of one of these libraries, please remember-not to react aggressively and respect the fact that I may have different-views on API design from yours.*--I have spent time to write the library because sending HTTP requests is a-common need, but there is no high-level library for that in Haskell that I-could use with pleasure. I'll explain why.--First of all, there is `http-client` and `http-client-tls`. They just work.-I have no issues with the libraries except that they are too low-level for-my taste. Indeed, even the docs say that they are low-level and “intended as-a base layer for more user-friendly packages”. This is exactly how I use-them in Req, as base level. Req is nothing but a different API to-`http-client`, so it only works because of the hard work put into-`http-client`.--`http-conduit` definitely has its place. For one thing it allows you to-stream request and response bodies in constant memory, what other library-allows you to do that? On the other hand if you take a look at-`Network.HTTP.Simple`, then although it's said that it's a “higher level-API”, it's mostly the same as vanilla `http-client` in spirit/approach and-just adds `conduit`-powered functions to perform requests and allows to use-global implicit `Manager` (Req does the same). If I tried to frame what-exactly I don't like about `http-conduit` in words, then it would be “the-way requests are constructed”. You *set* parameters instead of *being-forced* to declare necessary bits and *being allowed* to declare optional-bits in a way that their combination is valid. Also, with `http-conduit` you-parse request from a string without the protection of TH that otherwise-saves the day as in Yesod.--Then there is Wreq. `wreq` [doesn't see much development-lately](https://github.com/bos/wreq/issues/93). `wreq` is by itself a weird-library, IMO. You have functions per method—not very good, as there may be-new methods, like PATCH which is not new but still missing (well, you have-`customMethod`, but what is the point of having per-method functions if you-have a more general way to use any method? you should be able to just insert-methods in the “argument slot” of `customMethod` and end up with a more-general solution). Now, every method function has a companion that takes-`Options` (like you have `get` and `getWith`). Why the duplication? Where is-generality and flexibility? This is not all though, because you cannot-really use `get` you see in the main module, because you want to have-connection sharing. Wreq's author does not take the gift of automatic-connection re-use `Manager` from `http-client` provides, he invents the-whole new thing of “sessions”. Only inside a session your connections will-be shared and re-used. However with the session stuff you have yet another-set of per-method functions like `get` and `getWith`—these are different-ones, to be used with sessions! Now if you have a multi-threaded app, here-is a surprise for you: you can't share connections between threads as-connections are shared only inside of the `withSession` friend and “session-will no longer be valid after that function returns”. There are valid uses-for sessions, but the point is that they are just too inconvenient for-common tasks.--I used `servant-client` a couple of times but the amount of boilerplate it-requires is frightening. If you have several query parameters, and you use-just one of them, you'll have to pass lots of `Nothing`s.--## Unsolved problems--AWS request signing is problematic because request body can be in the form-of an action to execute (and all that “popper” stuff for streaming), not-just a `ByteString` and so getting its digest (hash) is not trivial without-running the action and consuming body in its entirety before the request in-made. In Wreq the author chose to just use `error` when body is not a-(strict or lazy) `ByteString`. Maybe it's OK for Wreq, but I don't consider-this a proper solution for Req as we support full variety of body options.-For example, what if I want to upload 1 Gb file to S3? I want to stream it-in constant memory but at the same time I need to calculate its hash before-I start streaming. One solution to the problem seems to be in taking the-hash explicitly (as an argument of the hypothetical `awsAuth`) and making it-a responsibility of the user to calculate the hash correctly. I don't like-this because it's not user-friendly. So the question stays open, for now-there is no AWS signing functionality provided out-of-the-box. The best-solution for talking to AWS is the `amazonka` package so far. ## Related packages
httpbin-tests/Network/HTTP/ReqSpec.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE FlexibleInstances #-} {-# LANGUAGE OverloadedStrings #-}@@ -27,10 +26,6 @@ import Test.Hspec import Test.QuickCheck -#if !MIN_VERSION_base(4,13,0)-import Data.Semigroup ((<>))-#endif- spec :: Spec spec = do describe "exception throwing on non-2xx status codes" $@@ -394,14 +389,13 @@ ---------------------------------------------------------------------------- -- Helpers --- | Run request with such settings that it does not signal error on adverse--- response status codes.+-- | Run a request with such settings that it does not signal errors. prepareForShit :: Req a -> IO a prepareForShit = runReq defaultHttpConfig {httpConfigCheckResponse = noNoise} where noNoise _ _ _ = Nothing --- | Run request with such settings that it throws on any response.+-- | Run a request with such settings that it throws on any response. blindlyThrowing :: Req a -> IO a blindlyThrowing = runReq defaultHttpConfig {httpConfigCheckResponse = doit} where@@ -461,11 +455,11 @@ L.responseStatus response == Y.status404 && not (B.null chunk) selector404 _ = False --- | Empty JSON 'Object'.+-- | The empty JSON 'Object'. emptyObject :: Value emptyObject = Object HM.empty --- | Get rendered JSON value as 'Text'.+-- | Get a rendered JSON value as 'Text'. reflectJSON :: ToJSON a => a -> Text reflectJSON = T.decodeUtf8 . BL.toStrict . A.encode
pure-tests/Network/HTTP/ReqSpec.hs view
@@ -1,4 +1,3 @@-{-# LANGUAGE CPP #-} {-# LANGUAGE DataKinds #-} {-# LANGUAGE DeriveGeneric #-} {-# LANGUAGE FlexibleInstances #-}@@ -48,10 +47,6 @@ import qualified Text.URI as URI import qualified Text.URI.QQ as QQ -#if !MIN_VERSION_base(4,13,0)-import Data.Semigroup ((<>))-#endif- spec :: Spec spec = do describe "config" $@@ -266,11 +261,7 @@ it "cookie jar is set without modifications" $ property $ \cjar -> do request <- req_ GET url NoReqBody (cookieJar cjar)-#if MIN_VERSION_http_client(0,7,0) L.cookieJar request `shouldSatisfy` (maybe False (L.equalCookieJar cjar))-#else- L.cookieJar request `shouldBe` Just cjar-#endif describe "basicAuth" $ do it "sets Authorization header to correct value" $ property $ \username password -> do@@ -562,14 +553,14 @@ maybe def (fromIntegral) $ either (const Nothing) Just (URI.uriAuthority uri) >>= URI.authPort --- | Get path from 'URI'.+-- | Get the path from a 'URI'. uriPath :: URI -> ByteString uriPath uri = fromMaybe "" $ do (trailingSlash, xs) <- URI.uriPath uri let pref = (encodePathPieces . fmap URI.unRText . NE.toList) xs return $ if trailingSlash then pref <> "/" else pref --- | Get query string from 'URI'.+-- | Get the query string from a 'URI'. uriQuery :: URI -> ByteString uriQuery uri = do let liftQueryParam = \case
req.cabal view
@@ -1,19 +1,15 @@ cabal-version: 1.18 name: req-version: 3.9.0+version: 3.9.1 license: BSD3 license-file: LICENSE.md maintainer: Mark Karpov <markkarpov92@gmail.com> author: Mark Karpov <markkarpov92@gmail.com>-tested-with: ghc ==8.6.5 ghc ==8.8.4 ghc ==8.10.3+tested-with: ghc ==8.8.4 ghc ==8.10.4 ghc ==9.0.1 homepage: https://github.com/mrkkrp/req bug-reports: https://github.com/mrkkrp/req/issues-synopsis:- Easy-to-use, type-safe, expandable, high-level HTTP client library--description:- Easy-to-use, type-safe, expandable, high-level HTTP client library.-+synopsis: HTTP client library+description: HTTP client library. category: Network, Web build-type: Simple data-files:@@ -39,25 +35,25 @@ build-depends: aeson >=0.9 && <1.6, authenticate-oauth >=1.5 && <1.7,- base >=4.12 && <5.0,+ base >=4.13 && <5.0, blaze-builder >=0.3 && <0.5, bytestring >=0.10.8 && <0.12, case-insensitive >=0.2 && <1.3, connection >=0.2.2 && <0.4, exceptions >=0.6 && <0.11, http-api-data >=0.2 && <0.5,- http-client >=0.5 && <0.8,+ http-client >=0.7 && <0.8, http-client-tls >=0.3.2 && <0.4, http-types >=0.8 && <10.0, modern-uri >=0.3 && <0.4, monad-control >=1.0 && <1.1, mtl >=2.0 && <3.0, retry >=0.8 && <0.9,- template-haskell >=2.14 && <2.17,+ template-haskell >=2.14 && <2.18, text >=0.2 && <1.3, time >=1.2 && <1.10, transformers >=0.4 && <0.6,- transformers-base -any,+ transformers-base, unliftio-core >=0.1.1 && <0.3 if flag(dev)@@ -81,19 +77,19 @@ build-depends: QuickCheck >=2.7 && <3.0, aeson >=0.9 && <1.6,- base >=4.12 && <5.0,+ base >=4.13 && <5.0, blaze-builder >=0.3 && <0.5, bytestring >=0.10.8 && <0.12, case-insensitive >=0.2 && <1.3, hspec >=2.0 && <3.0, hspec-core >=2.0 && <3.0,- http-client >=0.5 && <0.8,+ http-client >=0.7 && <0.8, http-types >=0.8 && <10.0, modern-uri >=0.3 && <0.4, mtl >=2.0 && <3.0,- req -any,+ req, retry >=0.8 && <0.9,- template-haskell >=2.14 && <2.17,+ template-haskell >=2.14 && <2.18, text >=0.2 && <1.3, time >=1.2 && <1.10 @@ -113,14 +109,14 @@ build-depends: QuickCheck >=2.7 && <3.0, aeson >=0.9 && <1.6,- base >=4.12 && <5.0,+ base >=4.13 && <5.0, bytestring >=0.10.8 && <0.12, hspec >=2.0 && <3.0,- http-client >=0.5 && <0.8,+ http-client >=0.7 && <0.8, http-types >=0.8 && <10.0, monad-control >=1.0 && <1.1, mtl >=2.0 && <3.0,- req -any,+ req, text >=0.2 && <1.3, unordered-containers >=0.2.5 && <0.3