Go语言 request
go get github.com/imroc/req
req
Go语言人性化HTTP请求库
特性
- 轻量级
- 简单
- 容易操作JSON和XML
- 容易调试和日志记录
- 容易上传和下载文件
- 容易管理Cookie
- 容易设置代理
- 容易设置超时
- 容易自定义HTTP客户端
安装
go get github.com/imroc/req
概要
req
基于标准库 net/http
实现了一个友好的API.
Req
和 Resp
是两个最重要的结构体, 你可以把 Req
看作客户端, 把Resp
看作存放请求及其响应的容器,它们都提供许多简洁方便的API,让你可以很轻松做很多很多事情。
func (r *Req) Post(url string, v ...interface{}) (*Resp, error)
大多情况下,发起请求只有url是必选参数,其它都可选,比如请求头、请求参数、文件或请求体等。
包中含一个默认的 Req
对象, 它所有的公有方法都被req
包对应的公有方法包装了,所以大多数情况下,你直接可以吧req
包看作一个Req
对象来使用。
// 创建Req对象来发起请求
r := req.New()
r.Get(url)
// 直接使用req包发起请求
req.Get(url)
你可以使用 req.New()
方法来创建 *Req
作为一个单独的客户端
例子
基础用法
设置请求头
设置请求参数
设置请求体
调试
输出格式
ToJSON & ToXML
获取 *http.Response
上传
下载
Cookie
设置超时
设置代理
自定义 http.Client
基础用法
header := req.Header{
"Accept": "application/json",
"Authorization": "Basic YWRtaW46YWRtaW4=",
}
param := req.Param{
"name": "imroc",
"cmd": "add",
}
// 只有url必选,其它参数都是可选
r, err = req.Post("http://foo.bar/api", header, param)
if err != nil {
log.Fatal(err)
}
r.ToJSON(&foo) // 响应体转成对象
log.Printf("%+v", r) // 打印详细信息
设置请求头
使用 req.Header
(它实际上是一个 map[string]string
)
authHeader := req.Header{
"Accept": "application/json",
"Authorization": "Basic YWRtaW46YWRtaW4=",
}
req.Get("https://www.baidu.com", authHeader, req.Header{"User-Agent": "V1.1"})
使用 http.Header
header := make(http.Header)
header.Set("Accept", "application/json")
req.Get("https://www.baidu.com", header)
设置请求参数
Use req.Param
(它实际上是一个 map[string]interface{}
)
param := req.Param{
"id": "imroc",
"pwd": "roc",
}
req.Get("http://foo.bar/api", param) // http://foo.bar/api?id=imroc&pwd=roc
req.Post(url, param) // 请求体 => id=imroc&pwd=roc
使用 req.QueryParam
强制将请求参数拼在url后面 (它实际上也是一个 map[string]interface{}
)
req.Post("http://foo.bar/api", req.Param{"name": "roc", "age": "22"}, req.QueryParam{"access_token": "fedledGF9Hg9ehTU"})
/*
POST /api?access_token=fedledGF9Hg9ehTU HTTP/1.1
Host: foo.bar
User-Agent: Go-http-client/1.1
Content-Length: 15
Content-Type: application/x-www-form-urlencoded;charset=UTF-8
Accept-Encoding: gzip
age=22&name=roc
*/
设置请求体
Put string
, []byte
and io.Reader
as body directly.
req.Post(url, "id=roc&cmd=query")
将对象作为JSON或XML请求体(自动添加 Content-Type
请求头)
req.Post(url, req.BodyJSON(&foo))
req.Post(url, req.BodyXML(&bar))
调试
将全局变量 req.Debug
设置为true
,将会把所有请求的详细信息打印在标准输出。
req.Debug = true
req.Post("http://localhost/test" "hi")
输出格式
您可以使用指定类型的输出格式在日志文件中记录请求和响应的信息。例如,在开发阶段使用%+v
格式,可以让你观察请求和响应的细节信息。 在生产阶段使用%v
或%-v
输出格式,只记录所需要的信息。
%+v
或 %+s
详细输出
r, _ := req.Post(url, header, param)
log.Printf("%+v", r) // 输出格式和Debug开启时的格式一样
%v
或 %s
简单输出(默认格式)
r, _ := req.Get(url, param)
log.Printf("%v\n", r) // GET http://foo.bar/api?name=roc&cmd=add {"code":"0","msg":"success"}
log.Prinln(r) // 和上面一样
%-v
或 %-s
简单输出并保持所有内容在一行内(请求体或响应体可能包含多行,这种格式会将所有换行、回车替换成" "
, 这在会让你在查日志的时候非常有用)
Flag
你可以调用 SetFlags
控制输出内容,决定哪些部分能够被输出。
const (
LreqHead = 1 << iota // 输出请求首部(包含请求行和请求头)
LreqBody // 输出请求体
LrespHead // 输出响应首部(包含响应行和响应头)
LrespBody // 输出响应体
Lcost // 输出请求所消耗掉时长
LstdFlags = LreqHead | LreqBody | LrespHead | LrespBody
)
req.SetFlags(req.LreqHead | req.LreqBody | req.LrespHead)
监控请求耗时
req.SetFlags(req.LstdFlags | req.Lcost) // 输出格式显示请求耗时
r,_ := req.Get(url)
log.Println(r) // http://foo.bar/api 3.260802ms {"code":0 "msg":"success"}
if r.Cost() > 3 * time.Second { // 检查耗时
log.Println("WARN: slow request:", r)
}
ToJSON & ToXML
r, _ := req.Get(url)
r.ToJSON(&foo)
r, _ = req.Post(url, req.BodyXML(&bar))
r.ToXML(&baz)
获取 *http.Response
// func (r *Req) Response() *http.Response
r, _ := req.Get(url)
resp := r.Response()
fmt.Println(resp.StatusCode)
上传
使用 req.File
匹配文件
req.Post(url, req.File("imroc.png"), req.File("/Users/roc/Pictures/*.png"))
使用 req.FileUpload
细粒度控制上传
file, _ := os.Open("imroc.png")
req.Post(url, req.FileUpload{
File: file,
FieldName: "file", // FieldName 是表单字段名
FileName: "avatar.png", // Filename 是要上传的文件的名称,我们使用它来猜测mimetype,并将其上传到服务器上
})
使用req.UploadProgress
监听上传进度
progress := func(current, total int64) {
fmt.Println(float32(current)/float32(total)*100, "%")
}
req.Post(url, req.File("/Users/roc/Pictures/*.png"), req.UploadProgress(progress))
fmt.Println("upload complete")
下载
r, _ := req.Get(url)
r.ToFile("imroc.png")
使用req.DownloadProgress
监听下载进度
progress := func(current, total int64) {
fmt.Println(float32(current)/float32(total)*100, "%")
}
r, _ := req.Get(url, req.DownloadProgress(progress))
r.ToFile("hello.mp4")
fmt.Println("download complete")
Cookie
默认情况下,底层的 *http.Client
会自动管理你的cookie(如果服务器给你发了cookie,之后的请求它会自动带上cookie请求头给服务器), 你可以调用这个方法取消自动管理:
req.EnableCookie(false)
你还可以在发送请求的时候自己传入 *http.Cookie
cookie := new(http.Cookie)
// ......
req.Get(url, cookie)
设置超时
req.SetTimeout(50 * time.Second)
设置代理
默认情况下,如果系统环境变量有 http_proxy
或 https_proxy
,req会讲对应的地址作为对应协议的代理,你也可以自定义设置代理,或者将其置为nil
,即取消代理。
req.SetProxy(func(r *http.Request) (*url.URL, error) {
if strings.Contains(r.URL.Hostname(), "google") {
return url.Parse("http://my.vpn.com:23456")
}
return nil, nil
})
设置简单代理(将所有请求都转发到指定代理url地址上)
req.SetProxyUrl("http://my.proxy.com:23456")
自定义HTTP客户端
使用 SetClient
改变底层的 *http.Client
req.SetClient(client)
给某个请求制定特定的 *http.Client
client := &http.Client{Timeout: 30 * time.Second}
req.Get(url, client)
改变底层 *http.Client
的某些属性
req.Client().Jar, _ = cookiejar.New(nil)
trans, _ := req.Client().Transport.(*http.Transport)
trans.MaxIdleConns = 20
trans.TLSHandshakeTimeout = 20 * time.Second
trans.DisableKeepAlives = true
trans.TLSClientConfig = &tls.Config{InsecureSkipVerify: true}