We're planting a tree for every job application! Click here to learn more

Introduction Tutorial to Wreq Package

aravind gopal mallapureddy

6 Oct 2021

•

3 min read

Introduction Tutorial to Wreq Package
  • Haskell

wreq-tut

Tutorial for wreq an haskell client library.

Lens

Lens are used to set/get to/from the data. we are not going to deep dive into the lens, we will see the simple functions required to use wReq library in getting things done. view (^.), set (.~) are the basic functions to get and set the values

>>> view _2 (1,"hello")
"hello"

>>> (1, "hello") ^. _2
"hello"

>>> set _2 "hello" (1, 2)
(1, "hello")

>>> (1, 2) & _2 .~ "hello"
(1, "hello")

wreq

wreq is a http client library to make the API calls easily using the potential of lens to modify or access Request and Response.

Required imports:

-- ^ wreq package
import Newton.Wreq
-- ^ Accessors
import Control.Lens

Simple Get Request

Here we will show how to do a simple get request and log the response by using lens.

resp <- get "http://httpbin.org/get"
resp ^. responseBody

RespBody:
{
  "args": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    "User-Agent": "haskell wreq-0.5.3.3",
    "X-Amzn-Trace-Id": "Root=1-6134aa81-40d492483b5824960758c3df"
  },
  "origin": "103.46.237.84",
  "url": "http://httpbin.org/get"
}

You can pass the query params using getWith

functions to look at:
>>> param :: Text -> Lens' Options [Text]
>>> defaults :: Options


{-# LANGUAGE OverloadedStrings #-} -- param uses Text

let opts = defaults & param "foo" .~ ["bar", "quux"]
getWith opts "http://httpbin.org/get"

RespBody:
{
  "args": {
    "foo": [
      "bar",
      "quux"
    ]
  },
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    "User-Agent": "haskell wreq-0.5.3.3",
    "X-Amzn-Trace-Id": "Root=1-6134ac87-19afc20e5e6459581d285d83"
  },
  "origin": "103.46.237.84",
  "url": "http://httpbin.org/get?foo=bar&foo=quux"
}

Post Request

Post request can be done using post function, where all the types to be passed as request body should have instance of Postable class. In the below example we will create a type and derive ToJSON instance from aeson package and converts it to Value to satisfy Postable constraint.

data ExRequest = ExRequest
  { num :: Int
  , str :: String
  }
  deriving (Generic, ToJSON) -- Add DeriveGeneric Extension

let req = ExRequest 1 "one"
resp <- post "http://httpbin.org/post" (toJSON req)
return $ resp ^. responseBody

RespBody:
{
  "args": {},
  "data": "{\"num\":1,\"str\":\"one\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Content-Length": "21",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "haskell wreq-0.5.3.3",
    "X-Amzn-Trace-Id": "Root=1-61363369-5a961a4b6bc037814506e1fc"
  },
  "json": {
    "num": 1,
    "str": "one"
  },
  "origin": "122.186.67.78",
  "url": "http://httpbin.org/post"
}

As seen above, we can pass the query params using the postWith

let opts = defaults & param "foo" .~ ["bar", "quux"]
let req = ExRequest 1 "one"
resp <- postWith opts "http://httpbin.org/post" (toJSON req)
return $ resp ^. responseBody

RespBody:
{
  "args": {
    "foo": [
      "bar",
      "quux"
    ]
  },
  "data": "{\"num\":1,\"str\":\"one\"}",
  "files": {},
  "form": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Content-Length": "21",
    "Content-Type": "application/json",
    "Host": "httpbin.org",
    "User-Agent": "haskell wreq-0.5.3.3",
    "X-Amzn-Trace-Id": "Root=1-6136348d-15571a6307d9638425d6a5f5"
  },
  "json": {
    "num": 1,
    "str": "one"
  },
  "origin": "122.186.67.78",
  "url": "http://httpbin.org/post?foo=bar&foo=quux"
}

Headers

Post/Get uses the Options to send the Headers for each API.

let opts = defaults & header "Accept" .~ ["*/*"]
getWith opts "http://httpbin.org/get"


RespBody:
{
  "args": {},
  "headers": {
    "Accept-Encoding": "gzip",
    "Host": "httpbin.org",
    "User-Agent": "haskell wreq-0.5.3.3",
    "X-Amzn-Trace-Id": "Root=1-613635a7-127a7291650e57244cf8512f"
  },
  "origin": "122.186.67.78",
  "url": "http://httpbin.org/get"
}

Like this you can pass differnt headers using the lens set and defautls. Will see example using Auth header.

Auth header using username, password.

let opts = defaults & auth ?~ basicAuth "user" "pass"
getWith opts "https://httpbin.org/basic-auth/user/pass"

Auth headers using Bearer Token.

  -- generated this bearer with curl /v1/token at: https://instantwebtools.net/secured-fake-rest-api
let opts = defaults & auth ?~ oauth2Bearer "eyJraWQiOiJQZjNoZlFEYVdYM0dMekJ2ZHk3MkhzVExRWUhKbk45dldFQm1LLUItUFJvIiwiYWxnIjoiUlMyNTYifQ.eyJ2ZXIiOjEsImp0aSI6IkFULnJjbHppTGR3QUtRdUQ1X3R2Smk1ZnpKQ3BTLXV2WWFiQVE4d0pUb01YRnMub2FyY2p1czlucDJVdHE0MUY0eDYiLCJpc3MiOiJodHRwczovL2Rldi00NTc5MzEub2t0YS5jb20vb2F1dGgyL2F1c2hkNGM5NVF0RkhzZld0NHg2IiwiYXVkIjoiYXBpIiwiaWF0IjoxNjMwOTU3NzAwLCJleHAiOjE2MzA5NjEzMDAsImNpZCI6IjBvYWhkaGprdXRhR2NJSzJNNHg2IiwidWlkIjoiMDB1aGVuaDFwVkRNZzJ1ZXg0eDYiLCJzY3AiOlsib2ZmbGluZV9hY2Nlc3MiXSwic3ViIjoiYXBpLXVzZXI0QGl3dC5uZXQifQ.EXwgGLVIpHvDObOyP5Xud_ayZW5Y3UuA7evDGVGog8EEFgr0nYw51WQLsrwbWjA9SYb-94822yn9gaJt74hVksAL9XKpfzTS1wIMgIKZjQCTh3XOX5167H5BHkHpkaATNTd4G4wjpWfTjClEKwpmGEMEeIAKQ-vTZgGCU5H5ABLNNpcrwDBLvWddLNSny1zABXdXDx1N4OYj8vglv7T27LljUjPwAZNy-fFF3s24fzf0EyPK7A9WngyYS1o_Ry_1PjaFIeIG0G3LjTtgoX8Kcan_CZrIpV6K8m619Ll-Jzon03aDJj8LNm8npcRhgemNDUUAHavUdb1pAvqquaIzhQ"
resp <- getWith opts "https://api.instantwebtools.net/v2/airlines"
return $ resp ^. responseBody

RespBody:
{
  "id": 10070,
  "name": "Srii Lankan Airways",
  "country": "Sri Lanka",
  "logo": "https://upload.wikimedia.org/wikipedia/en/thumb/9/9b/Qatar_Airways_Logo.svg/sri_lanka.png",
  "slogan": "From Sri Lanka",
  "head_quaters": "Katunayake, Sri Lanka",
  "website": "www.srilankaairways.com",
  "established": "1990"
}

You can try other ways of Auth using the primitivies as Above

SSL

ssl support is enabled usings the opts.

-- we set to the manager with openssl settings in Options and use these to build the connect using `With`.

let opts = defaults & manager .~ Left (opensslManagerSettings context)
withOpenSSL $
  getWith opts "https://httpbin.org/get"

Proxy

set the proxy config in the options and use these to build the connec with With

>>> httpProxy hostName Port and returns Proxy


let opts = defaults & proxy ?~ httpProxy "localhost" 8000
getWith opts "http://httpbin.org/get"

Did you like this article?

aravind gopal mallapureddy

Learn, Share and Create

See other articles by aravind

Related jobs

See all

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Title

The company

  • Remote

Related articles

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

JavaScript Functional Style Made Simple

JavaScript Functional Style Made Simple

Daniel Boros

•

12 Sep 2021

WorksHub

CareersCompaniesSitemapFunctional WorksBlockchain WorksJavaScript WorksAI WorksGolang WorksJava WorksPython WorksRemote Works
hello@works-hub.com

Ground Floor, Verse Building, 18 Brunswick Place, London, N1 6DZ

108 E 16th Street, New York, NY 10003

Subscribe to our newsletter

Join over 111,000 others and get access to exclusive content, job opportunities and more!

© 2024 WorksHub

Privacy PolicyDeveloped by WorksHub