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)