添加链接
link管理
链接快照平台
  • 输入网页链接,自动生成快照
  • 标签化管理网页链接
相关文章推荐
阳刚的小马驹  ·  Apple ...·  1 年前    · 
纯真的炒饭  ·  Netflix ...·  1 年前    · 
Centos Debian ElasticSearch Git HBase HTTP Java Jupyter Linux Lua Mac Minio MongoDB MyBatis MySQL Nginx NodeJS ORM Python Redis Scala Spring Boot Sqlalchemy Sqlite WEB Wrk boto3 ffmpeg frida golang jupyterlab lxml mitmproxy nvm proxy puppeteer pyenv pyppeteer python service tesseract vim xpath 基础知识 大数据 工具 数据库 文件存储 爬虫 生活 编程工具

安装

1
go get -u github.com/go-resty/resty/v2

基本请求

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
func main() {
// Create a Resty Client
client := resty.New()

resp, err := client.R().
EnableTrace().
Get("https://httpbin.org/get")
// Post()
// Put()
// Patch()
// Head()
// Option()
// Delete()

// Explore response object
fmt.Println("Response Info:")
fmt.Println(" Error :", err)
fmt.Println(" Status Code:", resp.StatusCode()) // 状态码,如 200;
fmt.Println(" Status :", resp.Status()) // 状态码和状态信息,如 200 OK;
fmt.Println(" Proto :", resp.Proto()) // 协议,如 HTTP/1.1;
fmt.Println(" Time :", resp.Time()) // 从发送请求到收到响应的时间;
fmt.Println(" Received At:", resp.ReceivedAt()) // 接收到响应的时刻;
fmt.Println(" Size :", resp.Size()) // 响应大小;
fmt.Println(" Headers :", resp.Header()) // 响应首部信息,以http.Header类型返回,即map[string][]string;
fmt.Println(" Cookies :", resp.Cookies()) // 服务器通过Set-Cookie首部设置的 cookie 信息。
fmt.Println(" Body :\n", resp)
fmt.Println()

// Explore trace info
fmt.Println("Request Trace Info:")
ti := resp.Request.TraceInfo()
fmt.Println(" DNSLookup :", ti.DNSLookup) // DNS 查询时间,如果提供的是一个域名而非 `IP`,就需要向 `DNS` 系统查询对应 `IP` 才能进行后续操作;
fmt.Println(" ConnTime :", ti.ConnTime) // 获取一个连接的耗时,可能从连接池获取,也可能新建;
fmt.Println(" TCPConnTime :", ti.TCPConnTime) // `TCP` 连接耗时,从 `DNS` 查询结束到 `TCP` 连接建立;
fmt.Println(" TLSHandshake :", ti.TLSHandshake) // `TLS` 握手耗时;
fmt.Println(" ServerTime :", ti.ServerTime) // 服务器处理耗时,计算从连接建立到客户端收到第一个字节的时间间隔;
fmt.Println(" ResponseTime :", ti.ResponseTime) // 响应耗时,从接收到第一个响应字节,到接收到完整响应之间的时间间隔;
fmt.Println(" TotalTime :", ti.TotalTime) // 整个流程的耗时;
fmt.Println(" IsConnReused :", ti.IsConnReused) // `TCP` 连接是否复用了;
fmt.Println(" IsConnWasIdle :", ti.IsConnWasIdle) // 连接是否是从空闲的连接池获取的;
fmt.Println(" ConnIdleTime :", ti.ConnIdleTime) // 连接空闲时间;
fmt.Println(" RequestAttempt:", ti.RequestAttempt) // 请求执行流程中的请求次数,包括重试次数;
fmt.Println(" RemoteAddr :", ti.RemoteAddr.String()) // 远程的服务地址,`IP:PORT`格式。
}

通用

设置请求参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func main() {
client := resty.New()

resp, err := client.R().
SetQueryParams(map[string]string{
"page_no": "1",
"limit": "20",
"sort":"name",
"order": "asc",
"random":strconv.FormatInt(time.Now().Unix(), 10),
}).
// .SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more").
SetHeader("Accept", "application/json"). // 设置请求头
SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F").
Get("/search_result")

// 请求路径中传参
client.R().
SetPathParams(map[string]string{
"user": "ifan",
}).
Get("/users/{user}/details")
}

绑定返回信息

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
func main() {
type JsonData struct {
Name string
Latest string
}

type Datas struct {
Results []*JsonData
}

client := resty.New()

datas := &Datas{}
client.R().SetResult(datas).
ForceContentType("application/json"). // 设置接受的返回数据类型
Get("json_data_url")
fmt.Printf("%d data len \n", len(datas.Results))

for _, data := range datas.Results {
fmt.Printf("name:%s latest:%s\n", data.Name, data.Latest)
break
}
}

设置Body参数

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
func main() {
// 字符串形式
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(`{"username":"testuser", "password":"testpass"}`).
.Post("url")

resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody([]byte(`{"username":"testuser", "password":"testpass"}`)).
Post("url")

// 使用结构体
resp, err := client.R().
SetBody(User{Username: "testuser", Password: "testpass"}).
Post("url")
// 上传文件
fileBytes, _ := ioutil.ReadFile("/Users/jeeva/mydocument.pdf")

resp, err := client.R().
SetBody(fileBytes).
SetContentLength(true). // 自动计算请求体长度
SetError(&DropboxError{}). // 设置错误返回的解析内容
Post("url")
}

上传多个文件

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
func main() {
profileImgBytes, _ := ioutil.ReadFile("/Users/jeeva/test-img.png")
notesBytes, _ := ioutil.ReadFile("/Users/jeeva/text-file.txt")

// Create a Resty Client
client := resty.New()

resp, err := client.R().
SetFileReader("profile_img", "test-img.png", bytes.NewReader(profileImgBytes)).
SetFileReader("notes", "text-file.txt", bytes.NewReader(notesBytes)).
SetFormData(map[string]string{
"first_name": "Jeevanandam",
"last_name": "M",
}).
Post("http://myapp.com/upload")
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
func main() {
// Create a Resty Client
client := resty.New()

// Single file scenario
resp, err := client.R().
SetFile("profile_img", "/Users/jeeva/test-img.png").
Post("http://myapp.com/upload")

// Multiple files scenario
resp, err := client.R().
SetFiles(map[string]string{
"profile_img": "/Users/jeeva/test-img.png",
"notes": "/Users/jeeva/text-file.txt",
}).
Post("http://myapp.com/upload")

// Multipart of form fields and files
resp, err := client.R().
SetFiles(map[string]string{
"profile_img": "/Users/jeeva/test-img.png",
"notes": "/Users/jeeva/text-file.txt",
}).
SetFormData(map[string]string{
"first_name": "Jeevanandam",
"last_name": "M",
"zip_code": "00001",
"city": "my city",
"access_token": "C6A79608-782F-4ED0-A11D-BD82FAD829CD",
}).
Post("http://myapp.com/profile")
}

设置回调方法

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
func main(){
client := resty.New()

// 请求前
client.OnBeforeRequest(func(c *resty.Client, req *resty.Request) error {

return nil
})

// 响应后
client.OnAfterResponse(func(c *resty.Client, resp *resty.Response) error {

return nil
})

// 发生错误时
client.OnError(func(req *resty.Request, err error) {
if v, ok := err.(*resty.ResponseError); ok {

}
})
}

重定向策略

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
func main(){
client := resty.New()

// Assign Client Redirect Policy. Create one as per you need
client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(15))

// Wanna multiple policies such as redirect count, domain name check, etc
client.SetRedirectPolicy(resty.FlexibleRedirectPolicy(20),
resty.DomainCheckRedirectPolicy("host1.com", "host2.org", "host3.net"))

// 自定义
// Using raw func into resty.SetRedirectPolicy
client.SetRedirectPolicy(resty.RedirectPolicyFunc(func(req *http.Request, via []*http.Request) error {
// Implement your logic here

// return nil for continue redirect otherwise return error to stop/prevent redirect
return nil
}))

//---------------------------------------------------

// Using struct create more flexible redirect policy
type CustomRedirectPolicy struct {
// variables goes here
}

func (c *CustomRedirectPolicy) Apply(req *http.Request, via []*http.Request) error {
// Implement your logic here

// return nil for continue redirect otherwise return error to stop/prevent redirect
return nil
}

// Registering in resty
client.SetRedirectPolicy(CustomRedirectPolicy{/* initialize variables */})
}

自定义证书

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
func main() {
// Create a Resty Client
client := resty.New()

// Custom Root certificates, just supply .pem file.
// you can add one or more root certificates, its get appended
client.SetRootCertificate("/path/to/root/pemFile1.pem")
client.SetRootCertificate("/path/to/root/pemFile2.pem")
// ... and so on!

// Adding Client Certificates, you add one or more certificates
// Sample for creating certificate object
// Parsing public/private key pair from a pair of files. The files must contain PEM encoded data.
cert1, err := tls.LoadX509KeyPair("certs/client.pem", "certs/client.key")
if err != nil {
log.Fatalf("ERROR client certificate: %s", err)
}
// ...

// You add one or more certificates
client.SetCertificates(cert1, cert2, cert3)

// Custom Root certificates from string
// You can pass you certificates throught env variables as strings
// you can add one or more root certificates, its get appended
client.SetRootCertificateFromString("-----BEGIN CERTIFICATE-----content-----END CERTIFICATE-----")
client.SetRootCertificateFromString("-----BEGIN CERTIFICATE-----content-----END CERTIFICATE-----")
// ... and so on!

// Adding Client Certificates, you add one or more certificates
// Sample for creating certificate object
// Parsing public/private key pair from a pair of files. The files must contain PEM encoded data.
cert1, err := tls.X509KeyPair([]byte("-----BEGIN CERTIFICATE-----content-----END CERTIFICATE-----"), []byte("-----BEGIN CERTIFICATE-----content-----END CERTIFICATE-----"))
if err != nil {
log.Fatalf("ERROR client certificate: %s", err)
}
// ...

// You add one or more certificates
client.SetCertificates(cert1, cert2, cert3)
}

自定义代理

1
2
3
4
5
6
7
8
9
10
11
func main() {
// Create a Resty Client
client := resty.New()

// Setting a Proxy URL and Port
// 验证呢?
client.SetProxy("http://proxyserver:8888")

// 移除代理
client.RemoveProxy()
}

重试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
func main() {
// Create a Resty Client
client := resty.New()

// Retries are configured per client
client.
// Set retry count to non zero to enable retries
SetRetryCount(3).
// You can override initial retry wait time.
// Default is 100 milliseconds.
SetRetryWaitTime(5 * time.Second).
// MaxWaitTime can be overridden as well.
// Default is 2 seconds.
SetRetryMaxWaitTime(20 * time.Second).
// SetRetryAfter sets callback to calculate wait time between retries.
// Default (nil) implies exponential backoff with jitter
SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
return 0, errors.New("quota exceeded")
})
// 自定义重试策略
client.AddRetryCondition(
// RetryConditionFunc type is for retry condition function
// input: non-nil Response OR request execution error
func(r *resty.Response, err error) bool {
return r.StatusCode() == http.StatusTooManyRequests
},
)
}

Allow GET request with Payload

1
2
3
4
5
6
7
8
func main() {
// Create a Resty Client
client := resty.New()

// Allow GET request with Payload. This is disabled by default.
client.SetAllowGetMethodPayload(true)

}

其他的一些参数设置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
func main() {
client := resty.New()

// Unique settings at Client level
//--------------------------------
// Debug 模式
client.SetDebug(true)

// 设置自定义证书 Refer: http://golang.org/pkg/crypto/tls/#example_Dial
client.SetTLSClientConfig(&tls.Config{ RootCAs: roots })

// 禁用安全检查
client.SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true })

// 设置链接超时
client.SetTimeout(1 * time.Minute)


// You can override all below settings and options at request level if you want to
//--------------------------------------------------------------------------------
// 设置请求的根地址,后面的请求中可以使用相对路径
client.SetHostURL("http://httpbin.org")

// 设置所有请求的请求头
client.SetHeader("Accept", "application/json")
client.SetHeaders(map[string]string{
"Content-Type": "application/json",
"User-Agent": "My custom User Agent String",
})

// 设置所有请求的Cookie
client.SetCookie(&http.Cookie{
Name:"go-resty",
Value:"This is cookie value",
Path: "/",
Domain: "sample.com",
MaxAge: 36000,
HttpOnly: true,
Secure: false,
})
client.SetCookies(cookies)

// 设置所有请求的 query parameters
client.SetQueryParam("user_id", "00001")
client.SetQueryParams(map[string]string{ // sample of those who use this manner
"api_key": "api-key-here",
"api_secert": "api-secert",
})
client.R().SetQueryString("productId=232&template=fresh-sample&cat=resty&source=google&kw=buy a lot more")

// 所有请求的Form data,POST and PUT
client.SetFormData(map[string]string{
"access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F",
})

// Basic Auth for all request
client.SetBasicAuth("myuser", "mypass")

// Bearer Auth Token for all request
client.SetAuthToken("BC594900518B4F7EAC75BD37F019E08FBC594900518B4F7EAC75BD37F019E08F")

// 自动设置请求体的长度
client.SetContentLength(true)

// 设置所有请求的异常处理
client.SetError(&Error{}) // or resty.SetError(Error{})
}

Unix Socket

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
func main(){
unixSocket := "/var/run/my_socket.sock"

// Create a Go's http.Transport so we can set it in resty.
transport := http.Transport{
Dial: func(_, _ string) (net.Conn, error) {
return net.Dial("unix", unixSocket)
},
}

// Create a Resty Client
client := resty.New()

// Set the previous transport that we created, set the scheme of the communication to the
// socket and set the unixSocket as the HostURL.
client.SetTransport(&transport).SetScheme("http").SetHostURL(unixSocket)

// No need to write the host's URL on the request, just the path.
client.R().Get("/index.html")
}

模拟发送请求

1
2
3
4
5
6
7
func main() {
// Create a Resty Client
client := resty.New()

// Get the underlying HTTP Client and set it to Mock
httpmock.ActivateNonDefault(client.GetClient())
}