req -is:module

HTTP client library HTTP client library.
Make an HTTP request. The function takes 5 arguments, 4 of which specify required parameters and the final Option argument is a collection of optional parameters. Let's go through all the arguments first: req method url body response options. method is an HTTP method such as GET or POST. The documentation has a dedicated section about HTTP methods below. url is a Url that describes location of resource you want to interact with. 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. response is a type hint how to make and interpret response of an HTTP request. Out-of-the-box it can be the following: Finally, options is a Monoid that holds a composite Option for all other optional settings like query parameters, headers, non-standard port number, etc. There are quite a few things you can put there, see the corresponding section in the documentation. If you don't need anything at all, pass mempty. Note that if you use req to do all your requests, connection sharing and reuse is done for you automatically. See the examples below to get on the speed quickly.

Examples

First, this is a piece of boilerplate that should be in place before you try the examples:
{-# LANGUAGE DeriveGeneric     #-}
{-# LANGUAGE OverloadedStrings #-}

module Main (main) where

import Control.Monad
import Control.Monad.IO.Class
import Data.Aeson
import Data.Maybe (fromJust)
import Data.Monoid ((<>))
import Data.Text (Text)
import GHC.Generics
import Network.HTTP.Req
import qualified Data.ByteString.Char8 as B
import qualified Text.URI as URI
We will be making requests against the https://httpbin.org service. Make a GET request, grab 5 random bytes:
main :: IO ()
main = runReq defaultHttpConfig $ do
let n :: Int
n = 5
bs <- req GET (https "httpbin.org" /: "bytes" /~ n) NoReqBody bsResponse mempty
liftIO $ B.putStrLn (responseBody bs)
The same, but now we use a query parameter named "seed" to control seed of the generator:
main :: IO ()
main = runReq defaultHttpConfig $ do
let n, seed :: Int
n    = 5
seed = 100
bs <- req GET (https "httpbin.org" /: "bytes" /~ n) NoReqBody bsResponse $
"seed" =: seed
liftIO $ B.putStrLn (responseBody bs)
POST JSON data and get some info about the POST request:
data MyData = MyData
{ size  :: Int
, color :: Text
} deriving (Show, Generic)

instance ToJSON MyData
instance FromJSON MyData

main :: IO ()
main = runReq defaultHttpConfig $ do
let myData = MyData
{ size  = 6
, color = "Green" }
v <- req POST (https "httpbin.org" /: "post") (ReqBodyJson myData) jsonResponse mempty
liftIO $ print (responseBody v :: Value)
Sending URL-encoded body:
main :: IO ()
main = runReq defaultHttpConfig $ do
let params =
"foo" =: ("bar" :: Text) <>
queryFlag "baz"
response <- req POST (https "httpbin.org" /: "post") (ReqBodyUrlEnc params) jsonResponse mempty
liftIO $ print (responseBody response :: Value)
Using various optional parameters and URL that is not known in advance:
main :: IO ()
main = runReq defaultHttpConfig $ do
-- This is an example of what to do when URL is given dynamically. Of
-- course in a real application you may not want to use 'fromJust'.
uri <- URI.mkURI "https://httpbin.org/get?foo=bar"
let (url, options) = fromJust (useHttpsURI uri)
response <- req GET url NoReqBody jsonResponse $
"from" =: (15 :: Int)           <>
"to"   =: (67 :: Int)           <>
basicAuth "username" "password" <>
options                         <> -- contains the ?foo=bar part
port 443 -- here you can put any port of course
liftIO $ print (responseBody response :: Value)
Extract required value from the given key.
A request that is ready to be submitted.
A monad that allows us to run req in any IO-enabled monad without having to define new instances.
Full description of an endpoint in your API, generated by listFromAPI. It should give you all the information needed to generate foreign language bindings. Every field containing ftype will use the foreign type mapping specified via HasForeignType (see its docstring on how to set that up). See https://docs.servant.dev/en/stable/tutorial/ApiType.html for accessible documentation of the possible content of an endpoint.
TableRecordField for a required field
An HTTP request
The parts of the path, when split on /, and the query.
Request a heap census on the next context switch. The census can be requested whether or not the heap profiling timer is running. Note: This won't do anything unless you also specify a profiling mode on the command line using the normal RTS options.
Request Entity Too Large 413
Request Header Fields Too Large 431 (RFC 6585)
Request Timeout 408
Request-URI Too Long 414
Requested Range Not Satisfiable 416
Strongly quote the string we pass to compgen. We need to do this so bash doesn't expand out any ~ or other chars we want to complete on, or emit an end of line error when seeking the close to the quote.
Request body to be sent to the server. Since 0.1.0
Convert a URI into a Request. This can fail if the given URI is not absolute, or if the URI scheme is not "http" or "https". In these cases the function will throw an error via MonadThrow. This function defaults some of the values in Request, such as setting method to GET and requestHeaders to []. A Request created by this function won't cause exceptions on non-2XX response status codes.
Same as requestFromURI, but if the conversion would fail, throws an impure exception.
Custom HTTP request headers The Content-Length and Transfer-Encoding headers are set automatically by this module, and shall not be added to requestHeaders. If not provided by the user, Host will automatically be set based on the host and port fields. Moreover, the Accept-Encoding header is set implicitly to gzip for convenience by default. This behaviour can be overridden if needed, by setting the header explicitly to a different value. In order to omit the Accept-Header altogether, set it to the empty string "". If you need an empty Accept-Header (i.e. requesting the identity encoding), set it to a non-empty white-space string, e.g. " ". See RFC 2616 section 14.3 for details about the semantics of the Accept-Header field. If you request a content-encoding not supported by this module, you will have to decode it yourself (see also the decompress field). Note: Multiple header fields with the same field-name will result in multiple header fields being sent and therefore it's the responsibility of the client code to ensure that the rules from RFC 2616 section 4.2 are honoured. Since 0.1.0