在现代 Web 开发中,HTTP 请求和响应是日常工作中不可避免的组成部分。虽然 Go 语言的标准库 net/http
已经提供了功能强大的 HTTP 客户端,但在处理复杂场景时,往往需要编写很多重复的代码来处理请求、响应、错误、重试等。
幸运的是,go-resty/resty
这个库提供了一个强大且简洁的解决方案,使得编写 HTTP 请求变得更加方便、直观。本文将详细介绍 Resty 的使用场景,并演示如何构建一个全面的 HTTP 客户端。
1. 安装 Resty
在使用 Resty 之前,首先需要安装该库:
go get github.com/go-resty/resty/v2
2. 创建简单的 HTTP 客户端
创建一个 Resty 客户端非常简单,使用 resty.New()
即可。
package main
import (
"fmt"
"github.com/go-resty/resty/v2"
)
func main() {
client := resty.New()
resp, err := client.R().Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
fmt.Printf("请求失败: %v\n", err)
} else {
fmt.Printf("响应状态码: %d\n", resp.StatusCode())
fmt.Printf("响应正文: %s\n", resp.String())
}
}
3. 处理常见的 HTTP 请求类型
Resty 提供了简化的 API,可以方便地发送 GET、POST、PUT、DELETE 等常见请求。
POST 请求发送 JSON 数据:
resp, err := client.R().
SetHeader("Content-Type", "application/json").
SetBody(map[string]string{"username": "test", "password": "1234"}).
Post("https://jsonplaceholder.typicode.com/posts")
GET 请求设置查询参数:
resp, err := client.R().
SetQueryParam("userId", "1").
Get("https://jsonplaceholder.typicode.com/posts")
4. 发送和解析 JSON 响应
Resty 可以自动将响应的 JSON 数据解析为结构体。
type Post struct {
UserID int `json:"userId"`
ID int `json:"id"`
Title string `json:"title"`
Body string `json:"body"`
}
post := &Post{}
resp, err := client.R().
SetResult(post).
Get("https://jsonplaceholder.typicode.com/posts/1")
if err != nil {
fmt.Printf("请求失败: %v\n", err)
} else {
fmt.Printf("Post 标题: %s\n", post.Title)
}
5. 文件上传与下载
Resty 支持文件上传和下载。
文件上传:
resp, err := client.R().
SetFile("file", "example.txt").
Post("https://example.com/upload")
文件下载:
resp, err := client.R().
SetOutput("output.txt").
Get("https://example.com/download")
6. 设置超时和重试机制
可以通过 SetTimeout
设置请求超时,并通过 SetRetryCount
设置自动重试。
client := resty.New().
SetTimeout(5 * time.Second).
SetRetryCount(3).
SetRetryWaitTime(2 * time.Second)
resp, err := client.R().
Get("https://example.com/timeout-test")
7. 中间件与 Hook
Resty 支持通过 Hook 在请求之前或之后执行操作。
在请求发送之前添加 Hook:
client := resty.New().
OnBeforeRequest(func(c *resty.Client, r *resty.Request) error {
fmt.Println("请求即将发送:", r.URL)
return nil
})
在请求完成之后添加 Hook:
client := resty.New().
OnAfterResponse(func(c *resty.Client, r *resty.Response) error {
fmt.Printf("请求完成,状态码: %d\n", r.StatusCode())
return nil
})
8. 支持上下文(Context)和取消请求
Resty 完全支持 Go 的 context.Context
,可以用来控制超时和取消请求。
ctx, cancel := context.WithTimeout(context.Background(), 2*time.Second)
defer cancel()
resp, err := client.R().
SetContext(ctx).
Get("https://example.com/delay")
9. 支持代理和认证
使用代理:
client := resty.New().SetProxy("http://proxy-server:8080")
使用基本认证:
client.R().SetBasicAuth("username", "password").Get("https://example.com/protected")
10. Cookie 管理
Resty 支持通过 SetCookie
和 SetCookies
管理 Cookie。
设置单个 Cookie:
client.R().
SetCookie(&http.Cookie{Name: "session_id", Value: "abc123"}).
Get("https://example.com/cookies")
设置多个 Cookie:
client.R().
SetCookies([]*http.Cookie{
{Name: "cookie1", Value: "value1"},
{Name: "cookie2", Value: "value2"},
}).
Get("https://example.com/cookies")
11. 链式调用和全局设置
Resty 支持链式调用和全局配置,使得代码更加简洁。
链式调用示例:
client.R().
SetHeader("Accept", "application/json").
SetQueryParam("id", "123").
SetTimeout(5 * time.Second).
Get("https://example.com/api")
全局设置示例:
client := resty.New().
SetHeader("Accept", "application/json").
SetTimeout(10 * time.Second)
12. 重试条件与高级错误处理
可以通过 SetRetryCondition
设置在特定条件下才进行重试,并通过 SetError
自动处理错误响应。
设置重试条件:
client.R().
SetRetryCount(3).
AddRetryCondition(func(r *resty.Response, err error) bool {
return r.StatusCode() == 500
}).
Get("https://example.com/status/500")
自动处理错误响应:
type ErrorResponse struct {
Message string `json:"message"`
}
errResponse := &ErrorResponse{}
resp, err := client.R().
SetError(errResponse).
Get("https://example.com/error")
if err != nil {
fmt.Println("请求失败:", errResponse.Message)
}
小结
go-resty/resty
提供了功能强大且直观的 HTTP 客户端,使得处理复杂 HTTP 请求变得更加简单。无论是处理文件上传下载、自动处理 JSON、请求重试机制,还是集成代理、认证和 Hook 等功能,Resty 都能很好地满足开发者的需求。
如果你的项目中需要处理 HTTP 请求,Resty 是一个非常值得考虑的选择。