on master help sign in
Improve the documentation
commit1d7763f197e609a1a370f3a2e40fa84808c38f11 authormrkkrp <markkarpov92@gmail.com> dateThu 25 May 2017, 15:46 (9 years ago) parent58603b2
2 files changed+140−133
Network/HTTP/Req.hs+97−89 README.md+43−44
Network/HTTP/Req.hs+97−89
@@ -38,8 +38,8 @@
3838-- methods like 'GET' or 'OPTIONS', and the amount of implicit assumptions
3939-- is minimized by making the user specify his\/her intentions in an
4040-- explicit form (for example, it's not possible to avoid specifying the
41−-- body or method of a request). Authentication methods that assume TLS
42−-- force the user to use TLS at the type level. The library also carefully
41+-- body or method of a request). Authentication methods that assume HTTPS
42+-- force the user to use HTTPS at the type level. The library also carefully
4343-- hides underlying types from the lower-level @http-client@ package because
4444-- those types are not safe enough (for example 'L.Request' is an instance
4545-- of 'Data.String.IsString' and, if it's malformed, it will blow up at
@@ -76,12 +76,11 @@
7676-- === Lightweight, no risk solution
7777--
7878-- The library uses the following mature packages under the hood to
79−-- guarantee you the best experience that doesn't have any bugs or other
80−-- funny business:
79+-- guarantee you the best experience:
8180--
82−-- * <https://hackage.haskell.org/package/http-client> — low level HTTP
81+-- * <https://hackage.haskell.org/package/http-client>—low level HTTP
8382-- client used everywhere in Haskell.
84−-- * <https://hackage.haskell.org/package/http-client-tls> — TLS (HTTPS)
83+-- * <https://hackage.haskell.org/package/http-client-tls>—TLS (HTTPS)
8584-- support for @http-client@.
8685--
8786-- It's important to note that since we leverage well-known libraries that
@@ -226,6 +225,7 @@ import Data.List.NonEmpty (NonEmpty (..))
226225import Data.Maybe (fromMaybe)
227226import Data.Proxy
228227import Data.Semigroup hiding (Option, option)
228+import Data.Text (Text)
229229import Data.Typeable (Typeable)
230230import GHC.Generics
231231import GHC.TypeLits
@@ -237,7 +237,6 @@ import qualified Data.ByteString as B
237237import qualified Data.ByteString.Lazy as BL
238238import qualified Data.CaseInsensitive as CI
239239import qualified Data.List.NonEmpty as NE
240−import qualified Data.Text as T
241240import qualified Data.Text.Encoding as T
242241import qualified Network.Connection as NC
243242import qualified Network.HTTP.Client as L
@@ -277,22 +276,26 @@ import GHC.Exts (Constraint)
277276-- tutorial has a section about HTTP bodies, but usage is very
278277-- straightforward and should be clear from the examples below.
279278--
280−-- @response@ is a type hint how to make and interpret response of HTTP
281−-- request, out-of-the-box it can be the following: 'ignoreResponse',
282−-- 'jsonResponse', 'bsResponse' (to get strict 'ByteString'), 'lbsResponse'
283−-- (to get lazy 'BL.ByteString'), and 'returnRequest' (makes no request,
284−-- just returns response, used for testing).
279+-- @response@ is a type hint how to make and interpret response of an HTTP
280+-- request. Out-of-the-box it can be the following:
281+--
282+-- * 'ignoreResponse'
283+-- * 'jsonResponse'
284+-- * 'bsResponse' (to get a strict 'ByteString')
285+-- * 'lbsResponse' (to get a lazy 'BL.ByteString')
286+-- * 'returnRequest' (makes no request, but returns the constructed
287+-- request itself, used for testing).
285288--
286289-- Finally @options@ is a 'Monoid' that holds a composite 'Option' for all
287−-- other optional things like query parameters, headers, non-standard port
288−-- number, etc. There are quite a few things you can put there, see
290+-- other optional settings like query parameters, headers, non-standard port
291+-- number, etc. There are quite a few things you can put there, see the
289292-- corresponding section in the documentation. If you don't need anything at
290293-- all, pass 'mempty'.
291294--
292295-- __Note__ that if you use 'req' to do all your requests, connection
293296-- sharing and reuse is done for you automatically.
294297--
295−-- See the examples below to get on the speed very quickly.
298+-- See the examples below to get on the speed quickly.
296299--
297300-- ==== __Examples__
298301--
@@ -390,7 +393,7 @@ req
390393 , HttpResponse response
391394 , HttpBodyAllowed (AllowsBody method) (ProvidesBody body) )
392395 => method -- ^ HTTP method
393− -> Url scheme -- ^ 'Url' — location of resource
396+ -> Url scheme -- ^ 'Url'—location of resource
394397 -> body -- ^ Body of the request
395398 -> Proxy response -- ^ A hint how to interpret response
396399 -> Option scheme -- ^ Collection of optional parameters
@@ -403,11 +406,11 @@ req method url body Proxy options = do
403406 nubHeaders = Endo $ \x ->
404407 x { L.requestHeaders = nubBy ((==) `on` fst) (L.requestHeaders x) }
405408 request' = flip appEndo L.defaultRequest $
406− -- NOTE Order of 'mappend's matters, here method is overwritten first
407− -- and 'options' take effect last. In particular, this means that
408− -- 'options' can overwrite things set by other request components,
409− -- which is useful for setting port number, "Content-Type" header,
410− -- etc.
409+ -- NOTE The order of 'mappend's matters, here method is overwritten
410+ -- first and 'options' take effect last. In particular, this means
411+ -- that 'options' can overwrite things set by other request
412+ -- components, which is useful for setting port number,
413+ -- "Content-Type" header, etc.
411414 nubHeaders <>
412415 getRequestMod options <>
413416 getRequestMod config <>
@@ -426,10 +429,10 @@ req method url body Proxy options = do
426429--
427430-- A note about safety, in case 'unsafePerformIO' looks suspicious to you.
428431-- The value of 'globalManager' is named and lives on top level. This means
429−-- it will be shared, i.e. computed only once on first use of manager. From
430−-- that moment on the 'IORef' will be just reused — exactly the behavior we
431−-- want here in order to maximize connection sharing. GHC could spoil the
432−-- plan by inlining the definition, hence the @NOINLINE@ pragma.
432+-- it will be shared, i.e. computed only once on the first use of the
433+-- manager. From that moment on the 'IORef' will be just reused—exactly the
434+-- behavior we want here in order to maximize connection sharing. GHC could
435+-- spoil the plan by inlining the definition, hence the @NOINLINE@ pragma.
433436
434437globalManager :: IORef L.Manager
435438globalManager = unsafePerformIO $ do
@@ -456,6 +459,8 @@ withReqManager m = liftIO (readIORef globalManager) >>= m
456459--
457460-- When writing a library, keep your API polymorphic in terms of
458461-- 'MonadHttp', only define instance of 'MonadHttp' in final application.
462+-- Another option is to use @newtype@ wrapped monad stack and define
463+-- 'MonadHttp' for it.
459464
460465-- | A type class for monads that support performing HTTP requests.
461466-- Typically, you only need to define the 'handleHttpException' method
@@ -528,12 +533,12 @@ instance RequestComponent HttpConfig where
528533 , LI.checkResponse = httpConfigCheckResponse }
529534
530535----------------------------------------------------------------------------
531−-- Request — Method
536+-- Request—Method
532537
533538-- $method
534539--
535540-- The package supports all methods as defined by RFC 2616, and 'PATCH'
536−-- which is defined by RFC 5789 — that should be enough to talk to RESTful
541+-- which is defined by RFC 5789—that should be enough to talk to RESTful
537542-- APIs. In some cases, however, you may want to add more methods (e.g. you
538543-- work with WebDAV <https://en.wikipedia.org/wiki/WebDAV>); no need to
539544-- compromise on type safety and hack, it only takes a couple of seconds to
@@ -572,7 +577,7 @@ instance HttpMethod PUT where
572577 httpMethodName Proxy = Y.methodPut
573578
574579-- | 'DELETE' method. This data type does not allow having request body with
575−-- 'DELETE' requests, as it should be, however some APIs may expect 'DELETE'
580+-- 'DELETE' requests, as it should be. However some APIs may expect 'DELETE'
576581-- requests to have bodies, in that case define your own variation of
577582-- 'DELETE' method and allow it to have a body.
578583
@@ -625,10 +630,10 @@ instance HttpMethod PATCH where
625630
626631class HttpMethod a where
627632
628− -- | Type function 'AllowsBody' returns type of kind 'CanHaveBody' which
633+ -- | Type function 'AllowsBody' returns a type of kind 'CanHaveBody' which
629634 -- tells the rest of the library whether the method can have a body or
630− -- not. We use the special type 'CanHaveBody' “lifted” into kind instead
631− -- of 'Bool' to get more user-friendly compiler messages.
635+ -- not. We use the special type 'CanHaveBody' “lifted” to kind level
636+ -- instead of 'Bool' to get more user-friendly compiler messages.
632637
633638 type AllowsBody a :: CanHaveBody
634639
@@ -641,7 +646,7 @@ instance HttpMethod method => RequestComponent (Womb "method" method) where
641646 x { L.method = httpMethodName (Proxy :: Proxy method) }
642647
643648----------------------------------------------------------------------------
644−-- Request — URL
649+-- Request—URL
645650
646651-- $url
647652--
@@ -650,7 +655,7 @@ instance HttpMethod method => RequestComponent (Womb "method" method) where
650655
651656-- | Request's 'Url'. Start constructing your 'Url' with 'http' or 'https'
652657-- specifying the scheme and host at the same time. Then use the @('/~')@
653−-- and @('/:')@ operators to grow path one piece at a time. Every single
658+-- and @('/:')@ operators to grow the path one piece at a time. Every single
654659-- piece of path will be url(percent)-encoded, so using @('/~')@ and
655660-- @('/:')@ is the only way to have forward slashes between path segments.
656661-- This approach makes working with dynamic path segments easy and safe. See
@@ -677,20 +682,20 @@ instance HttpMethod method => RequestComponent (Womb "method" method) where
677682-- > https "юникод.рф"
678683-- > -- https://%D1%8E%D0%BD%D0%B8%D0%BA%D0%BE%D0%B4.%D1%80%D1%84
679684
680−data Url (scheme :: Scheme) = Url Scheme (NonEmpty T.Text)
681− -- NOTE The second value is path segments in reversed order.
685+data Url (scheme :: Scheme) = Url Scheme (NonEmpty Text)
686+ -- NOTE The second value is the path segments in reversed order.
682687 deriving (Eq, Ord, Show, Data, Typeable, Generic)
683688
684689-- | Given host name, produce a 'Url' which have “http” as its scheme and
685690-- empty path. This also sets port to @80@.
686691
687−http :: T.Text -> Url 'Http
692+http :: Text -> Url 'Http
688693http = Url Http . pure
689694
690695-- | Given host name, produce a 'Url' which have “https” as its scheme and
691696-- empty path. This also sets port to @443@.
692697
693−https :: T.Text -> Url 'Https
698+https :: Text -> Url 'Https
694699https = Url Https . pure
695700
696701-- | Grow given 'Url' appending a single path segment to it. Note that the
@@ -700,11 +705,11 @@ infixl 5 /~
700705(/~) :: ToHttpApiData a => Url scheme -> a -> Url scheme
701706Url secure path /~ segment = Url secure (NE.cons (toUrlPiece segment) path)
702707
703−-- | Type-constrained version of @('/~')@ to remove ambiguity in cases when
704−-- next URL piece is a 'Text' literal.
708+-- | Type-constrained version of @('/~')@ to remove ambiguity in the cases
709+-- when next URL piece is a 'Text' literal.
705710
706711infixl 5 /:
707−(/:) :: Url scheme -> T.Text -> Url scheme
712+(/:) :: Url scheme -> Text -> Url scheme
708713(/:) = (/~)
709714
710715-- | The 'parseUrlHttp' function provides an alternative method to get 'Url'
@@ -735,7 +740,7 @@ parseUrlHttps url' = do
735740-- | Get host\/collection of path pieces and possibly query parameters
736741-- already converted to 'Option'. This function is not public.
737742
738−parseUrlHelper :: ByteString -> Maybe (NonEmpty T.Text, Option scheme)
743+parseUrlHelper :: ByteString -> Maybe (NonEmpty Text, Option scheme)
739744parseUrlHelper url = do
740745 let (path', query') = B.break (== 0x3f) url
741746 query = mconcat (uncurry queryParam <$> Y.parseQueryText query')
@@ -756,13 +761,13 @@ instance RequestComponent (Url scheme) where
756761 (BL.toStrict . BB.toLazyByteString . Y.encodePathSegments) path }
757762
758763----------------------------------------------------------------------------
759−-- Request — Body
764+-- Request—Body
760765
761766-- $body
762767--
763768-- A number of options for request bodies are available. The @Content-Type@
764−-- header is set for you automatically according to body option you use
765−-- (it's always specified in documentation for given body option). To add
769+-- header is set for you automatically according to the body option you use
770+-- (it's always specified in documentation for a given body option). To add
766771-- your own way to represent request body, see 'HttpBody'.
767772
768773-- | This data type represents empty body of an HTTP request. This is the
@@ -776,7 +781,7 @@ data NoReqBody = NoReqBody
776781instance HttpBody NoReqBody where
777782 getRequestBody NoReqBody = L.RequestBodyBS B.empty
778783
779−-- | This body option allows to use a JSON object as request body — probably
784+-- | This body option allows to use a JSON object as request body—probably
780785-- the most popular format right now. Just wrap a data type that is an
781786-- instance of 'ToJSON' type class and you are done: it will be converted to
782787-- JSON and inserted as request body.
@@ -839,7 +844,7 @@ instance HttpBody ReqBodyUrlEnc where
839844-- | An opaque monoidal value that allows to collect URL-encoded parameters
840845-- to be wrapped in 'ReqBodyUrlEnc'.
841846
842−newtype FormUrlEncodedParam = FormUrlEncodedParam [(T.Text, Maybe T.Text)]
847+newtype FormUrlEncodedParam = FormUrlEncodedParam [(Text, Maybe Text)]
843848 deriving (Semigroup, Monoid)
844849
845850instance QueryParam FormUrlEncodedParam where
@@ -894,7 +899,7 @@ reqBodyMultipart parts = liftIO $ do
894899 body <- LM.renderParts boundary parts
895900 return (ReqBodyMultipart boundary body)
896901
897−-- | A type class for things that can be interpreted as HTTP
902+-- | A type class for things that can be interpreted as an HTTP
898903-- 'L.RequestBody'.
899904
900905class HttpBody body where
@@ -921,8 +926,8 @@ type family ProvidesBody body :: CanHaveBody where
921926 ProvidesBody body = 'CanHaveBody
922927
923928-- | This type function allows any HTTP body if method says it
924−-- 'CanHaveBody'. When method says it should have 'NoBody', the only body
925−-- option to use is 'NoReqBody'.
929+-- 'CanHaveBody'. When the method says it should have 'NoBody', the only
930+-- body option to use is 'NoReqBody'.
926931--
927932-- __Note__: users of GHC 8.0.1 and later will see a slightly more friendly
928933-- error message when method does not allow a body and body is provided.
@@ -948,7 +953,7 @@ instance HttpBody body => RequestComponent (Womb "body" body) where
948953 (Y.hContentType, contentType) : old }
949954
950955----------------------------------------------------------------------------
951−-- Request — Optional parameters
956+-- Request—Optional parameters
952957
953958-- $optional-parameters
954959--
@@ -966,9 +971,10 @@ data Option (scheme :: Scheme) =
966971 Option (Endo (Y.QueryText, L.Request)) (Maybe (L.Request -> IO L.Request))
967972 -- NOTE 'QueryText' is just [(Text, Maybe Text)], we keep it along with
968973 -- Request to avoid appending to existing query string in request every
969− -- time new parameter is added. Additional Maybe (Endo Request) is a
970− -- finalizer that will be applied after all other transformations. This is
971− -- for authentication methods that sign requests based on data in Request.
974+ -- time new parameter is added. Additional Maybe (L.Request -> IO
975+ -- L.Request) is a finalizer that will be applied after all other
976+ -- transformations. This is for authentication methods that sign requests
977+ -- based on data in Request.
972978
973979instance Semigroup (Option scheme) where
974980 Option er0 mr0 <> Option er1 mr1 = Option
@@ -979,7 +985,7 @@ instance Monoid (Option scheme) where
979985 mappend = (<>)
980986
981987-- | A helper to create an 'Option' that modifies only collection of query
982−-- parameters. This helper is not a part of public API.
988+-- parameters. This helper is not a part of the public API.
983989
984990withQueryParams :: (Y.QueryText -> Y.QueryText) -> Option scheme
985991withQueryParams f = Option (Endo (first f)) Nothing
@@ -991,7 +997,7 @@ withRequest :: (L.Request -> L.Request) -> Option scheme
991997withRequest f = Option (Endo (second f)) Nothing
992998
993999-- | A helper to create an 'Option' that adds a finalizer (request
994−-- endomorphism that is run after all other modifications).
1000+-- transformation that is applied after all other modifications).
9951001
9961002asFinalizer :: (L.Request -> IO L.Request) -> Option scheme
9971003asFinalizer = Option mempty . pure
@@ -1002,20 +1008,20 @@ instance RequestComponent (Option scheme) where
10021008 query = Y.renderQuery True (Y.queryTextToQuery qparams)
10031009 in x' { L.queryString = query }
10041010
1005−-- | Finalize given 'L.Request' by applying a finalizer from given 'Option'
1006−-- (if it has any).
1011+-- | Finalize given 'L.Request' by applying a finalizer from the given
1012+-- 'Option' (if it has any).
10071013
10081014finalizeRequest :: MonadIO m => Option scheme -> L.Request -> m L.Request
10091015finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
10101016
10111017----------------------------------------------------------------------------
1012−-- Request — Optional parameters — Query Parameters
1018+-- Request—Optional parameters—Query Parameters
10131019
10141020-- $query-parameters
10151021--
10161022-- This section describes a polymorphic interface that can be used to
1017−-- construct query parameters (of type 'Option') and form URL-encoded bodies
1018−-- (of type 'FormUrlEncodedParam').
1023+-- construct query parameters (of the type 'Option') and form URL-encoded
1024+-- bodies (of the type 'FormUrlEncodedParam').
10191025
10201026-- | This operator builds a query parameter that will be included in URL of
10211027-- your request after question sign @?@. This is the same syntax you use
@@ -1026,22 +1032,23 @@ finalizeRequest (Option _ mfinalizer) = liftIO . fromMaybe pure mfinalizer
10261032-- > name =: value = queryParam name (pure value)
10271033
10281034infix 7 =:
1029−(=:) :: (QueryParam param, ToHttpApiData a) => T.Text -> a -> param
1035+(=:) :: (QueryParam param, ToHttpApiData a) => Text -> a -> param
10301036name =: value = queryParam name (pure value)
10311037
10321038-- | Construct a flag, that is, valueless query parameter. For example, in
1033−-- the following URL @a@ is a flag, @b@ is a query parameter with a value:
1039+-- the following URL @a@ is a flag, while @b@ is a query parameter with a
1040+-- value:
10341041--
10351042-- > https://httpbin.org/foo/bar?a&b=10
10361043--
10371044-- This operator is defined in terms of 'queryParam':
10381045--
1039−-- > queryFlag name = queryParam name Nothing
1046+-- > queryFlag name = queryParam name (Nothing :: Maybe ())
10401047
1041−queryFlag :: QueryParam param => T.Text -> param
1048+queryFlag :: QueryParam param => Text -> param
10421049queryFlag name = queryParam name (Nothing :: Maybe ())
10431050
1044−-- | A type class for query-parameter-like things. The reason to have
1051+-- | A type class for query-parameter-like things. The reason to have an
10451052-- overloaded 'queryParam' is to be able to use it as an 'Option' and as a
10461053-- 'FormUrlEncodedParam' when constructing form URL encoded request bodies.
10471054-- Having the same syntax for these cases seems natural and user-friendly.
@@ -1053,14 +1060,14 @@ class QueryParam param where
10531060 -- way). It's recommended to use @('=:')@ and 'queryFlag' instead of this
10541061 -- method, because they are easier to read.
10551062
1056− queryParam :: ToHttpApiData a => T.Text -> Maybe a -> param
1063+ queryParam :: ToHttpApiData a => Text -> Maybe a -> param
10571064
10581065instance QueryParam (Option scheme) where
10591066 queryParam name mvalue =
10601067 withQueryParams ((:) (name, toQueryParam <$> mvalue))
10611068
10621069----------------------------------------------------------------------------
1063−-- Request — Optional parameters — Headers
1070+-- Request—Optional parameters—Headers
10641071
10651072-- | Create an 'Option' that adds a header. Note that if you 'mappend' two
10661073-- headers with the same names the leftmost header will win. This means, in
@@ -1081,11 +1088,11 @@ attachHeader name value x =
10811088 x { L.requestHeaders = (CI.mk name, value) : L.requestHeaders x }
10821089
10831090----------------------------------------------------------------------------
1084−-- Request — Optional parameters — Cookies
1091+-- Request—Optional parameters—Cookies
10851092
10861093-- $cookies
10871094--
1088−-- Support for cookies is quite minimalistic at the moment, its' possible to
1095+-- Support for cookies is quite minimalistic at the moment. It's possible to
10891096-- specify which cookies to send using 'cookieJar' and inspect 'L.Response'
10901097-- to extract 'L.CookieJar' from it (see 'responseCookieJar').
10911098
@@ -1097,7 +1104,7 @@ cookieJar jar = withRequest $ \x ->
10971104 x { L.cookieJar = Just jar }
10981105
10991106----------------------------------------------------------------------------
1100−-- Request — Optional parameters — Authentication
1107+-- Request—Optional parameters—Authentication
11011108
11021109-- $authentication
11031110--
@@ -1106,7 +1113,8 @@ cookieJar jar = withRequest $ \x ->
11061113-- to manual construction of headers because it ensures that you only use
11071114-- one authentication method at a time (they overwrite each other) and
11081115-- provides additional type safety that prevents leaking of credentials in
1109−-- cases when authentication relies on TLS for encrypting sensitive data.
1116+-- the cases when authentication relies on HTTPS for encrypting sensitive
1117+-- data.
11101118
11111119-- | The 'Option' adds basic authentication.
11121120--
@@ -1169,7 +1177,7 @@ oAuth2Token token = asFinalizer
11691177 (pure . attachHeader "Authorization" ("token " <> token))
11701178
11711179----------------------------------------------------------------------------
1172−-- Request — Optional parameters — Other
1180+-- Request—Optional parameters—Other
11731181
11741182-- | Specify the port to connect to explicitly. Normally, 'Url' you use
11751183-- determines the default port: @80@ for HTTP and @443@ for HTTPS. This
@@ -1196,8 +1204,8 @@ decompress
11961204decompress f = withRequest $ \x ->
11971205 x { L.decompress = f }
11981206
1199−-- | Specify number of microseconds to wait for response. The default value
1200−-- is 30 seconds.
1207+-- | Specify the number of microseconds to wait for response. The default
1208+-- value is 30 seconds.
12011209
12021210responseTimeout
12031211 :: Int -- ^ Number of microseconds to wait
@@ -1205,7 +1213,7 @@ responseTimeout
12051213responseTimeout n = withRequest $ \x ->
12061214 x { L.responseTimeout = LI.ResponseTimeoutMicro n }
12071215
1208−-- | HTTP version to send to server, the default is HTTP 1.1.
1216+-- | HTTP version to send to the server, the default is HTTP 1.1.
12091217
12101218httpVersion
12111219 :: Int -- ^ Major version number
@@ -1236,7 +1244,7 @@ ignoreResponse = Proxy
12361244-- | Make a request and interpret body of response as JSON. The
12371245-- 'handleHttpException' method of 'MonadHttp' instance corresponding to
12381246-- monad in which you use 'req' will determine what to do in the case when
1239−-- parsing fails ('JsonHttpException' constructor will be used).
1247+-- parsing fails (the 'JsonHttpException' constructor will be used).
12401248
12411249newtype JsonResponse a = JsonResponse (L.Response a)
12421250
@@ -1290,8 +1298,8 @@ instance HttpResponse LbsResponse where
12901298lbsResponse :: Proxy LbsResponse
12911299lbsResponse = Proxy
12921300
1293−-- | This interpretation does not result in any call at all, but you can use
1294−-- the 'responseRequest' function to extract 'L.Request' that 'req' has
1301+-- | This interpretation does not result in any request at all, but you can
1302+-- use the 'responseRequest' function to extract 'L.Request' that 'req' has
12951303-- prepared. This is useful primarily for testing.
12961304--
12971305-- Note that when you use this interpretation inspecting response will
@@ -1314,7 +1322,7 @@ returnRequest = Proxy
13141322----------------------------------------------------------------------------
13151323-- Inspecting a response
13161324
1317−-- | Get response body.
1325+-- | Get the response body.
13181326
13191327responseBody
13201328 :: HttpResponse response
@@ -1322,7 +1330,7 @@ responseBody
13221330 -> HttpResponseBody response
13231331responseBody = L.responseBody . toVanillaResponse
13241332
1325−-- | Get response status code.
1333+-- | Get the response status code.
13261334
13271335responseStatusCode
13281336 :: HttpResponse response
@@ -1331,7 +1339,7 @@ responseStatusCode
13311339responseStatusCode =
13321340 Y.statusCode . L.responseStatus . toVanillaResponse
13331341
1334−-- | Get response status message.
1342+-- | Get the response status message.
13351343
13361344responseStatusMessage
13371345 :: HttpResponse response
@@ -1340,7 +1348,7 @@ responseStatusMessage
13401348responseStatusMessage =
13411349 Y.statusMessage . L.responseStatus . toVanillaResponse
13421350
1343−-- | Look a particular header from a response.
1351+-- | Lookup a particular header from a response.
13441352
13451353responseHeader
13461354 :: HttpResponse response
@@ -1350,7 +1358,7 @@ responseHeader
13501358responseHeader r h =
13511359 (lookup (CI.mk h) . L.responseHeaders . toVanillaResponse) r
13521360
1353−-- | Get response 'L.CookieJar'.
1361+-- | Get the response 'L.CookieJar'.
13541362
13551363responseCookieJar
13561364 :: HttpResponse response
@@ -1364,7 +1372,7 @@ responseRequest :: ReturnRequest -> L.Request
13641372responseRequest (ReturnRequest request) = request
13651373
13661374----------------------------------------------------------------------------
1367−-- Response — defining your own interpretation
1375+-- Response—Defining your own interpretation
13681376
13691377-- $new-response-interpretation
13701378--
@@ -1376,17 +1384,17 @@ responseRequest (ReturnRequest request) = request
13761384
13771385class HttpResponse response where
13781386
1379− -- | The associated type is the type of body that can be extracted from a
1387+ -- | The associated type is the type of body that can be extracted from an
13801388 -- instance of 'HttpResponse'.
13811389
13821390 type HttpResponseBody response :: *
13831391
1384− -- | The method describes how to get underlying 'L.Response' record.
1392+ -- | The method describes how to get the underlying 'L.Response' record.
13851393
13861394 toVanillaResponse :: response -> L.Response (HttpResponseBody response)
13871395
13881396 -- | This method describes how to make an HTTP request given 'L.Request'
1389− -- (prepared by the rest of the library) and 'L.Manager'.
1397+ -- (prepared by the library) and 'L.Manager'.
13901398
13911399 getHttpResponse :: L.Request -> L.Manager -> IO response
13921400
@@ -1439,11 +1447,11 @@ data CanHaveBody
14391447 = CanHaveBody -- ^ Indeed can have a body
14401448 | NoBody -- ^ Should not have a body
14411449
1442−-- | A type-level tag that specifies URL scheme used (and thus if TLS is
1450+-- | A type-level tag that specifies URL scheme used (and thus if HTTPS is
14431451-- enabled). This is used to force TLS requirement for some authentication
14441452-- 'Option's.
14451453
14461454data Scheme
1447− = Http -- ^ HTTP, no TLS
1455+ = Http -- ^ HTTP
14481456 | Https -- ^ HTTPS
14491457 deriving (Eq, Ord, Show, Data, Typeable, Generic)
README.md+43−44
@@ -60,13 +60,13 @@ manager with different settings, but it requires a bit more typing.
6060classes of errors. For example, we have correct-by-construction URLs, it's
6161guaranteed that the user does not send the request body when using methods
6262like GET or OPTIONS, and the amount of implicit assumptions is minimized by
63−making the user specify his/her intentions in and explicit form (for
64−example, it's not possible to avoid specifying the body or method of a
65−request). Authentication methods that assume TLS force the user to use TLS
66−at the type level. The library also carefully hides underlying types from
67−the lower-level `http-client` package because those types are not safe
68−enough (for example `Request` is an instance of `IsString` and, if it's
69−malformed, it will blow up at run-time).
63+making the user specify his/her intentions in an explicit form (for example,
64+it's not possible to avoid specifying the body or method of a request).
65+Authentication methods that assume HTTPS force the user to use HTTPS at the
66+type level. The library also carefully hides underlying types from the
67+lower-level `http-client` package because those types are not safe enough
68+(for example `Request` is an instance of `IsString` and, if it's malformed,
69+it will blow up at run-time).
7070
7171“Expandable” refers to the ability to create new components for dealing with
7272HTTP without having to resort to ugly hacking. For example, it's possible to
@@ -88,18 +88,18 @@ the library cuts boilerplate down considerably, and helps you write concise,
8888easy to read, and maintainable code.
8989
9090The library uses the following mature packages under the hood to guarantee
91−you the best experience that doesn't have any bugs or other funny business:
91+you the best experience:
9292
93−* [`http-client`](https://hackage.haskell.org/package/http-client) — low
94− level HTTP client used everywhere in Haskell.
93+* [`http-client`](https://hackage.haskell.org/package/http-client)—low level
94+ HTTP client used everywhere in Haskell.
9595
96−* [`http-client-tls`](https://hackage.haskell.org/package/http-client-tls) —
97− TLS (HTTPS) support for `http-client`.
96+* [`http-client-tls`](https://hackage.haskell.org/package/http-client-tls)—TLS
97+ (HTTPS) support for `http-client`.
9898
9999It's important to note that since we leverage well-known libraries that the
100100whole Haskell ecosystem uses, there is no risk in using Req. The machinery
101−for performing requests is the same as `http-conduit` and Wreq. The only
102−difference is the API.
101+for performing requests is the same as with `http-conduit` and Wreq. The
102+only difference is the API.
103103
104104## Motivation and Req vs other libraries
105105
@@ -117,7 +117,7 @@ have no issues with the libraries except that they are too low-level for my
117117taste. Indeed, even the docs say that they are low-level and “intended as a
118118base layer for more user-friendly packages”. This is exactly how I use them
119119in Req, as base level. Req is nothing but a different API to `http-client`,
120−so it only works because of hard work put into `http-client`.
120+so it only works because of the hard work put into `http-client`.
121121
122122`http-conduit` definitely has its place. For one thing it allows you to
123123stream request and response bodies in constant memory, what other library
@@ -125,19 +125,19 @@ allows you to do that? On the other hand if you take a look at
125125`Network.HTTP.Simple`, then although it's said that it's a “higher level
126126API”, it's mostly the same as vanilla `http-client` in spirit/approach and
127127just adds `conduit`-powered functions to perform requests and allows to use
128−global implicit `Manager` (super-cool idea, BTW, Req does the same). If I
129−tried to frame what exactly I don't like about `http-conduit` in words, then
130−it would be “the way requests are constructed”. You set, set, set instead of
131−*being forced* to declare necessary bits and *being allowed* to declare
132−optional bits in a way that their combination is certainly valid. And you
133−parse request from a string without the protection of TH that otherwise
134−saves the day as in Yesod.
128+global implicit `Manager` (Req does the same). If I tried to frame what
129+exactly I don't like about `http-conduit` in words, then it would be “the
130+way requests are constructed”. You set, set, set instead of *being forced*
131+to declare necessary bits and *being allowed* to declare optional bits in a
132+way that their combination is certainly valid. And you parse request from a
133+string without the protection of TH that otherwise saves the day as in
134+Yesod.
135135
136136Then there is Wreq.
137137`wreq`
138138[doesn't see much development lately](https://github.com/bos/wreq/issues/93).
139−`wreq` is by itself a weird library, IMO. You have functions per method —
140−not very good, as there may be new methods, like PATCH which is not new but
139+`wreq` is by itself a weird library, IMO. You have functions per method—not
140+very good, as there may be new methods, like PATCH which is not new but
141141still missing (well you have `customMethod`, but what is the point of having
142142per-method functions if you have a more general way to use any method? you
143143should be able to just insert methods in the “argument slot” of
@@ -150,14 +150,12 @@ take the gift of automatic connection re-use `Manager` from `http-client`
150150provides, he invents the whole new thing of “sessions”. Only inside a
151151session your connections will be shared and re-used. However with the
152152session stuff you have yet another set of per-method functions like `get`
153−and `getWith` — these are different ones, to be used with sessions! Now if
154−you have multi-threaded app, here is a surprise for you: you can't share
153+and `getWith`—these are different ones, to be used with sessions! Now if you
154+have a multi-threaded app, here is a surprise for you: you can't share
155155connections between threads as connections are shared only inside
156156`withSession` friend and “session will no longer be valid after that
157−function returns”. Disclaimer: I don't use Wreq, see below. If something in
158−this paragraph is not correct, please let me know and I'll remove it. Also
159−there are valid uses for sessions, but the point is that they are too
160−inconvenient for common tasks.
157+function returns”. There are valid uses for sessions, but the point is that
158+they are just too inconvenient for common tasks.
161159
162160It's funny that one client I worked for had to have his own little wrapper
163161around `http-client` just because he could not possibly use `wreq` and
@@ -172,26 +170,27 @@ just one of them, good luck passing lots of `Nothing`s.
172170
173171## Unsolved problems
174172
175−AWS request signing is problematic because request body can be in form of
176−action to execute (and all that “popper” stuff for streaming), not just
177−`ByteString` and so getting its digest (hash) is not trivial without running
178−the action and consuming body in its entirety before the request in made. In
179−Wreq the author chose to just use `error` when body is not a (strict or
180−lazy) `ByteString`. Maybe it's OK for Wreq, but I don't consider this proper
181−solution for Req as we support full variety of body options. For example
182−what if I want to upload 1 Gb file to S3? I want to stream it in constant
183−memory but at the same time I need to calculate its hash before I start
184−streaming. One solution to the problem seems to be in taking the hash
185−explicitly (as an argument of hypothetical `awsAuth`) and making it
186−responsibility of library user to calculate the hash correctly. I don't like
173+AWS request signing is problematic because request body can be in the form
174+of an action to execute (and all that “popper” stuff for streaming), not
175+just a `ByteString` and so getting its digest (hash) is not trivial without
176+running the action and consuming body in its entirety before the request in
177+made. In Wreq the author chose to just use `error` when body is not a
178+(strict or lazy) `ByteString`. Maybe it's OK for Wreq, but I don't consider
179+this a proper solution for Req as we support full variety of body options.
180+For example what if I want to upload 1 Gb file to S3? I want to stream it in
181+constant memory but at the same time I need to calculate its hash before I
182+start streaming. One solution to the problem seems to be in taking the hash
183+explicitly (as an argument of the hypothetical `awsAuth`) and making it a
184+responsibility of the user to calculate the hash correctly. I don't like
187185this because it's not user-friendly. So the question stays open, for now
188−there is no AWS signing functionality provided out-of-the-box.
186+there is no AWS signing functionality provided out-of-the-box. The best
187+solution for talking to AWS is the `amazonka` package so far.
189188
190189## Related packages
191190
192191The following packages are designed to be used with Req:
193192
194−* [`req-conduit`](https://hackage.haskell.org/package/req-conduit) — support
193+* [`req-conduit`](https://hackage.haskell.org/package/req-conduit)—support
195194 for streaming request and response bodies in constant memory.
196195
197196If you happen to have written a package that adds new features to Req,