go 网络请求包 resty

阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6

简介

resty是 Go 语言的一个 HTTP client 库。resty功能十分强大特性丰富并提供了简单易用的 API。
详情请到 官方文档地址https://github.com/go-resty/resty

  • 安装
// step1: 打开 go.mod文件 ==================================
// 加入一下 引用
require github.com/go-resty/resty/v2 v2.7.0

// step2: 打开main.go文件 ==================================
package main

import (
	"fmt"
    // 加入 指定版本的 引用 
	"github.com/go-resty/resty/v2"
)

func main() {
	client := resty.New()
	resp, err := client.R().Get("https://httpbin.org/get")
	fmt.Println("  Status     :", resp.Status())
}

// step3: 下载包 ==================================
go mod tidy

一般使用

客户端

调用一个resty.New() 创建一个client对象客户端

  • 开启 debug 模式
    每次请求可以 查看 请求报文响应报文 的详细信息。
client := resty.New()

// Enable debug mode
client.SetDebug(true)
  • 禁用 https 证书检查
client.SetTLSClientConfig(&tls.Config{ InsecureSkipVerify: true })
  • 请求超时设置
client.SetTimeout(1 * time.Minute)
  • URL公共部分抽离
client := resty.New()
client.SetBaseURL("https://whero.com")
resp, err := client.R().Get("/s/user")

请求方法

Get

调用client对象的R() 方法创建一个请求对象

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

resp, err := client.R().
      SetQueryParams(map[string]string{
          "age": "13",
          "name": "tom",
      }).Get("/search_result")
  • Params
client.R().
  SetPathParams(map[string]string{
    "age": "12",
    "name": "tom",
  }).
  Get("/users/{age}/{name}")

  • 请求体
client := resty.New()

// 让get请求携带请求体参数需要额外配置
client.SetAllowGetMethodPayload(true)

resp, err := client.R().
      SetBody(`{"username":"testuser", "password":"testpass"}`).
      Get("/search_result")

Post

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

// POST JSON string
resp, err := client.R().
      SetHeader("Content-Type", "application/json").
      // 请求体   
      SetBody(`{"username":"testuser", "password":"testpass"}`).
      Post("https:")

// POST []byte array
      SetBody([]byte(`{"username":"testuser", "password":"testpass"}`))

// POST Struct, default is JSON content type. No need to set one
      SetBody(User{Username: "testuser", Password: "testpass"}).

// POST Map, default is JSON content type. No need to set one
      SetBody(map[string]interface{}{"username": "testuser", "password": "testpass"}).
  • form-data
resp, err := client.R().
	SetFormData(map[string]string{
		"access_token": "BC594900-518B-4F7E-AC75-BD37F019E08F",
	}).
	Post("")
  • x-www-form-urlencoded

Put

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

// Request goes as JSON content type
// No need to set auth token, error, if you have client level settings
resp, err := client.R().
      SetBody(Article{
        Title: "go-resty",
      }).
      Put("")

Delete

resp, err := client.R().
      Delete("")

响应体

  • 响应数据
  resp, _ := client.R().Get("https://baidu.com")


  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
  for key, value := range resp.Header() {
    fmt.Println(key, "=", value)
  }
  fmt.Println("Cookies:", resp.Cookies()) // 服务器通过Set-Cookie首部设置的 cookie 信息。
  for i, cookie := range resp.Cookies() {
    fmt.Printf("cookie%d: name:%s value:%s\n", i, cookie.Name, cookie.Value)
  }
  • 自动 Unmarshal
    返回结构化的数据如 JSON/XML 格式等。resty可以自动将响应数据 Unmarshal 到对应的结构体对象中。
type Man struct {
  Name  string
  Age   int64
}

func main() {
  client := resty.New()
  tom := &Man{}
  client.R().SetResult(tom). // 通过 SetResult 方法 将数据反射到 结构体 上。
    Get("")
}

一般请求下resty会根据响应中的Content-Type来推断数据格式。但是有时候响应中无Content-Type首部或与内容格式不一致
我们可以通过调用请求对象的 ForceContentType() 强制 让resty按照 特定的格式 来 解析响应

client.R().
  SetResult(tom).
  ForceContentType("application/json").
  Get("")

请求头

  • 设置一般首部
client.R().
	SetHeader("Content-Type", "application/json").
	SetHeader("aaa", "bbb").
  	Get("")


client.SetHeaders(map[string]string{
        "Content-Type": "application/json",
        "aaa": "bbb",
      })
  • Content-Length首部resty自动计算
client.R().
  SetBody(User{Name:"dj"}).
  SetContentLength(true).
  Get("")

上下文件

上传文件

  • 通过 io.Reader
file1, _ = ioutil.ReadFile("./static/aaa.png")
file2, _ = ioutil.ReadFile("./static/bbb.png")

client := resty.New()

client.R().
  SetFileReader("file_one", file1).
  SetFileReader("file_two", file2).
  SetFormData(map[string]string{
    "name": "tom",
    "age": "11",
  })
  Post("")
  • 通过 文件路径
client := resty.New()

client.R().
  SetFile("file_one", "./static/aaa.png").
  SetFile("file_two", "./static/bbb.png").
  SetFiles(map[string]string{
    "file1": "./static/aaa.png",
    "file2": "./static/bbb.png",
  }).
  SetFormData(map[string]string{
    "name": "tom",
    "age": "11",
  })
  Post("")

下载文件

client := resty.New()
// 如果该目录 不存在 则会 自动创建
client.SetOutDirectory("/home/hero")

// 使用相对路径 相对SetOutDirectory 设置的路径
client.R().
  SetOutput("static/aaa.png").
  Get("")

// 也可以使用绝对路径
client.R().
  SetOutput("/home/hero/static/aaa.png").
  Get("")

高级应用

中间件

Resty 提供了和Gin类似的中间件特性。 OnBeforeRequest 和 OnAfterResponse 回调方法可以在请求之前和响应之后加入自定义逻辑。参数包含了 resty.Client 和当前请求的 resty.Request 对象。成功时返回 nil 失败时返回 error 对象。

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
})

请求重试

由于 网络抖动 带来的接口稳定性的问题 Resty 提供了重试功能来解决。SetRetryCount 设置重试次数 SetRetryWaitTimeSetRetryMaxWaitTime 设置等待时间。 SetRetryAfter 是一个重试后的回调方法。除此之外还可以调用 AddRetryCondition 设置重试的条件。

client := resty.New()

client.
    SetRetryCount(3).
    SetRetryWaitTime(5 * time.Second).
    SetRetryMaxWaitTime(20 * time.Second).
    SetRetryAfter(func(client *resty.Client, resp *resty.Response) (time.Duration, error) {
        return 0, errors.New("quota exceeded")
    })

client.AddRetryCondition(
    func(r *resty.Response) (bool, error) {
        return r.StatusCode() == http.StatusTooManyRequests
    },
)

代理

Resty 提供了 SetProxy 方法为请求添加代理还可以调用 RemoveProxy 移除代理。

client := resty.New()
client.SetProxy("http://proxyserver:1234")
client.RemoveProxy()

debug模式

Go1.7 引入了HTTP trace可以在HTTP客户端请求过程中收集一些更细粒度的信息httptrace包 提供了HTTP trace的支持收集的信息可用于调试延迟问题服务监控编写自适应系统等。httptrace包提供了许多钩子在HTTP往返期间收集各种事件的信息包括连接的创建、复用、DNS解析查询、写入请求和读取响应。

resty提供的一个辅助功能trace, 就是基于 httptrace包。我们在请求对象上调用EnableTrace()方法启用 trace。启用 trace 可以记录请求的每一步的耗时和其他信息。

resp, err :=client.R().EnableTrace().Get("https://baidu.com")

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格式。
阿里云国内75折 回扣 微信号:monov8
阿里云国际,腾讯云国际,低至75折。AWS 93折 免费开户实名账号 代冲值 优惠多多 微信号:monov8 飞机:@monov6
标签: go