req
req 是一个好用,类型安全,可扩展,上层的HTTP客户端的库。
$ cabal install req
Installed req-1.1.0
Prelude> :m +Network.HTTP.Req
Prelude Network.HTTP.Req>
官方示例
{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Control.Monad
import Control.Monad.IO.Class
import Data.Aeson
import Data.Default.Class
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
main1 :: IO ()
main1 = runReq def $ do
let n :: Int
n = 5
bs <- req GET (https "httpbin.org" /: "bytes" /~ n) NoReqBody bsResponse mempty
liftIO $ B.putStrLn (responseBody bs)
main2 :: IO ()
main2 = runReq def $ 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)
data MyData = MyData
{ size :: Int
, color :: Text
} deriving (Show, Generic)
instance ToJSON MyData
instance FromJSON MyData
main3 :: IO ()
main3 = runReq def $ do
let myData = MyData
{ size = 6
, color = "Green" }
v <- req POST (https "httpbin.org" /: "post") (ReqBodyJson myData) jsonResponse mempty
liftIO $ print (responseBody v :: Value)
main4 :: IO ()
main4 = runReq def $ do
let params =
"foo" =: ("bar" :: Text) <>
queryFlag "baz"
response <- req POST (https "httpbin.org" /: "post") (ReqBodyUrlEnc params) jsonResponse mempty
liftIO $ print (responseBody response :: Value)
main5 :: IO ()
main5 = runReq def $ 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'.
let (url, options) = fromJust (parseUrlHttps "https://httpbin.org/get?foo=bar")
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)
*Main> main1
?+???
*Main> main2
J??Y?
*Main> main3
Object (fromList [("origin",String "xx.xxx.xxx.xx"),("args",Object (fromList [])),("json",Object (fromList [("color",String "Green"),("size",Number 6.0)])),("data",String "{\"color\":\"Green\",\"size\":6}"),("url",String "https://httpbin.org/post"),("headers",Object (fromList [("Content-Type",String "application/json; charset=utf-8"),("Accept-Encoding",String "gzip"),("Connection",String "close"),("Host",String "httpbin.org"),("Content-Length",String "26")])),("files",Object (fromList [])),("form",Object (fromList []))])
*Main> main4
Object (fromList [("origin",String "xx.xxx.xxx.xx"),("args",Object (fromList [])),("json",Null),("data",String ""),("url",String "https://httpbin.org/post"),("headers",Object (fromList [("Content-Type",String "application/x-www-form-urlencoded"),("Accept-Encoding",String "gzip"),("Connection",String "close"),("Host",String "httpbin.org"),("Content-Length",String "11")])),("files",Object (fromList [])),("form",Object (fromList [("foo",String "bar"),("baz",String "")]))])
*Main> main5
Object (fromList [("origin",String "xx.xxx.xxx.xx"),("args",Object (fromList [("to",String "67"),("from",String "15"),("foo",String "bar")])),("url",String "https://httpbin.org/get?from=15&to=67&foo=bar"),("headers",Object (fromList [("Authorization",String "Basic dXNlcm5hbWU6cGFzc3dvcmQ="),("Accept-Encoding",String "gzip"),("Connection",String "close"),("Host",String "httpbin.org")]))])
API
req
:: ( MonadHttp m
, HttpMethod method
, HttpBody body
, HttpResponse response
, HttpBodyAllowed (AllowsBody method) (ProvidesBody body) )
=> method -- ^ HTTP method
-> Url scheme -- ^ 'Url'—location of resource
-> body -- ^ Body of the request
-> Proxy response -- ^ A hint how to interpret response
-> Option scheme -- ^ Collection of optional parameters
-> m response -- ^ Response
req method url body Proxy options
req 函数实现 Http 请求。
req 函数共有5个参数
method
GET POST PUT DELETE 之类的 HTTP 方法-
Url scheme
Url 地址,由以下3部分组合而成- http 或 https
- 域名
- /: + 字符串 或者 /~ + 对象
https "httpbin.org" /: "encoding" /: "utf8"
-- https://httpbin.org/encoding/utf8
https "httpbin.org" /: "bytes" /~ (10 :: Int)
-- https://httpbin.org/bytes/10 body
NoReqBody 没有请求体。
ReqBodyJson object 有JSON请求体。(自动将 object 转换成 JSON)Proxy response
bsResponse 应答是 ByteString。
jsonResponse 应答是 JSON。(自动将 object 转换成 JSON)Option scheme
mempty 没有查询参数。
a := 1 <> b := 2 有两个查询参数。m response
最后返回应答类型处于 Monad m 之中。
Monad m 是 MonadHttp 的实例。在指定 ReqBodyJson 以及 jsonResponse 时,需要 Data.Aeson 来定义对象与 JSON 之间的转换。
runReq :: MonadIO m
=> HttpConfig -- ^ 'HttpConfig' to use
-> Req a -- ^ Computation to run
-> m a
runReq config (Req m) = liftIO (runReaderT m config)
runReq 函数将 req Monad 中的计算结果取出来。
runReq 函数共有2个参数
- config
Http 配置选项,包括代理服务器,重试次数等。
Data.Default.Class.def 提供了默认选项。
缺省情况下代理服务器的设置从 HTTP_PROXY 和 HTTPS_PROXY 两个环境变量中读取。 - Req m
req Monad,包括 req 函数的调用。 - m a
返回值处在 Monad m 之中。
示例2
{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Control.Monad
import Control.Monad.IO.Class
import Data.Aeson
import Data.Default.Class
import Data.Text (Text)
import GHC.Generics
import Network.HTTP.Req
import qualified Data.ByteString.Char8 as B
showPostAsString :: Int -> IO ()
showPostAsString n = runReq def $ do
bs <- req GET (https "jsonplaceholder.typicode.com" /: "posts" /~ n) NoReqBody bsResponse mempty
liftIO $ B.putStrLn (responseBody bs)
data Post = Post
{ userId :: Int
, id :: Int
, title :: Text
, body :: Text
} deriving (Show, Generic)
instance ToJSON Post
instance FromJSON Post
showPostAsJson :: Int -> IO ()
showPostAsJson n = runReq def $ do
v <- req GET (https "jsonplaceholder.typicode.com" /: "posts" /~ n) NoReqBody jsonResponse mempty
liftIO $ print (responseBody v :: Post)
showPosts :: Int -> IO ()
showPosts n = runReq def $ do
v <- req GET (https "jsonplaceholder.typicode.com" /: "posts") NoReqBody jsonResponse mempty
liftIO $ mapM_ print $ take n (responseBody v :: [Post])
createPost :: IO ()
createPost = runReq def $ do
let myPost = Post {
userId = 101,
Main.id = 102,
title = "test title",
body = "test body"
}
v <- req POST (https "jsonplaceholder.typicode.com" /: "posts") (ReqBodyJson myPost) jsonResponse mempty
liftIO $ print (responseBody v :: Post)
updatePost :: Int -> IO ()
updatePost n = runReq def $ do
let myPost = Post {
userId = 101,
Main.id = 0, -- unused
title = "test title",
body = "test body"
}
v <- req PUT (https "jsonplaceholder.typicode.com" /: "posts" /~ n) (ReqBodyJson myPost) jsonResponse mempty
liftIO $ print (responseBody v :: Post)
deletePost :: Int -> IO ()
deletePost n = runReq def $ do
v <- req DELETE (https "jsonplaceholder.typicode.com" /: "posts" /~ n) NoReqBody jsonResponse mempty
liftIO $ print (responseBody v :: Value)
*Main> showPostAsString 1
{
"userId": 1,
"id": 1,
"title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
"body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"
}
*Main> showPostAsJson 1
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
*Main> showPosts 2
Post {userId = 1, id = 1, title = "sunt aut facere repellat provident occaecati excepturi optio reprehenderit", body = "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum rerum est autem sunt rem eveniet architecto"}
Post {userId = 1, id = 2, title = "qui est esse", body = "est rerum tempore vitae\nsequi sint nihil reprehenderit dolor beatae ea dolores neque\nfugiat blanditiis voluptate porro vel nihil molestiae ut reiciendis\nqui aperiam non debitis possimus qui neque nisi nulla"}
*Main> createPost
Post {userId = 101, id = 102, title = "test title", body = "test body"}
*Main> updatePost 1
Post {userId = 101, id = 1, title = "test title", body = "test body"}
*Main> deletePost 1
Object (fromList [])
Haskell语言学习笔记(80)req的更多相关文章
-
Haskell语言学习笔记(88)语言扩展(1)
ExistentialQuantification {-# LANGUAGE ExistentialQuantification #-} 存在类型专用的语言扩展 Haskell语言学习笔记(73)Ex ...
-
Haskell语言学习笔记(79)lambda演算
lambda演算 根据*,lambda演算(英语:lambda calculus,λ-calculus)是一套从数学逻辑中发展,以变量绑定和替换的规则,来研究函数如何抽象化定义.函数如何被应用以 ...
-
Haskell语言学习笔记(69)Yesod
Yesod Yesod 是一个使用 Haskell 语言的 Web 框架. 安装 Yesod 首先更新 Haskell Platform 到最新版 (Yesod 依赖的库非常多,版本不一致的话很容易安 ...
-
Haskell语言学习笔记(20)IORef, STRef
IORef 一个在IO monad中使用变量的类型. 函数 参数 功能 newIORef 值 新建带初值的引用 readIORef 引用 读取引用的值 writeIORef 引用和值 设置引用的值 m ...
-
Haskell语言学习笔记(39)Category
Category class Category cat where id :: cat a a (.) :: cat b c -> cat a b -> cat a c instance ...
-
Haskell语言学习笔记(72)Free Monad
安装 free 包 $ cabal install free Installed free-5.0.2 Free Monad data Free f a = Pure a | Free (f (Fre ...
-
Haskell语言学习笔记(49)ByteString Text
Data.ByteString String 是 [Char] 的同义词,在使用上存在List的惰性所带来的性能问题. 在处理大型二进制文件时,可以使用 ByteString 来代替 String. ...
-
Haskell语言学习笔记(44)Lens(2)
自定义 Lens 和 Isos -- Some of the examples in this chapter require a few GHC extensions: -- TemplateHas ...
-
Haskell语言学习笔记(38)Lens(1)
Lens Lens是一个接近语言级别的库,使用它可以方便的读取,设置,修改一个大的数据结构中某一部分的值. view, over, set Prelude> :m +Control.Lens P ...
随机推荐
-
图解Android - 如何看Android的UML 图?
如何看UML图? UML能给我们带来什么? 这是本文要寻找的答案.UML图有很多类型,我们这里只讨论最重要也最常用的两种 - 类图和时序图. 1. 类图 通过类图,我们可以很容易的了解代码架构,理清模 ...
-
转!!Java JTable 根据表格内容 自动调整表格列宽
//根据表格内容 自动调整列宽http://blog.sina.com.cn/s/blog_5e54d6140100s1d3.html
-
JS常见排序算法
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
-
手机安全卫士开发系列(2)——splash界面
一.Android中的MVC (1)activity主要用来页面的展示 (2)engine包:获取数据和展示数据(包含数据适配器) (3)domain包:存放数据实体 第一种包结构组织关系: 第二种包 ...
-
使用VS2003 发送Email
使用VS2003发送Email与之后VS2005版本及以上VS版本不一样,记录一下, 需要引用using System.Web.Mail; public void SendEmail() { try ...
-
Java入门(6)——集合、基本数据类型和引用数据类型的相互转换
集合: 1.HashMap ----> 类 概述: 通过key可以找到value, key就是键, values就是值. 俗称键值对. 特点: 无序的 值可以重复 键不可以重复的 如 ...
-
Linux下搭建svn服务端
安装 使用yum安装非常简单: yum -y install subversion (压缩包安装比这麻烦的多) Tortoise本是window下客户端工具,但也可以建仓库,作为服务端.Linux只有 ...
-
kubernetes系列05—kubectl应用快速入门
本文收录在容器技术学习系列文章总目录 1.使用kubectl 1.1 介绍 kubectl用于运行Kubernetes集群命令的管理工具. 1.2 语法 kubectl [command] [TYPE ...
-
node 中 安装 yarn
Yarn是Facebook最近发布的一款依赖包安装工具.Yarn是一个新的快速安全可信赖的可以替代NPM的依赖管理工具 快速安装 //在NPM 中安装npm install -g yarn MacOS ...
-
2017-2018-2 20165206 实验三 《敏捷开发与XP实践》实验报告
2017-2018-2 20165206 实验三 <敏捷开发与XP实践>实验报告 一.实验报告封面 课程:Java程序设计 班级:1652班 姓名:韩啸 学号:20165206 指导教师: ...