httpclient
模塊介紹
httpclient 是基於 net/http
封裝的 Go HTTP 客戶端請求包,支持常用的請求方式、常用設置,比如:
- 支持設置 Mock 信息
- 支持設置失敗時告警
- 支持設置失敗時重試
- 支持設置項目內部的 Trace
- 支持設置超時時間、Header 等
請求說明
方法名 | 描述 |
---|---|
httpclient.Get() | GET 請求 |
httpclient.Post() | POST 請求 |
httpclient.PostForm() | POST 請求,form 形式 |
httpclient.PostJSON() | POST 請求,json 形式 |
httpclient.PutForm() | PUT 請求,form 形式 |
httpclient.PutJSON() | PUT 請求,json 形式 |
httpclient.PatchForm() | PATCH 請求,form 形式 |
httpclient.PatchJSON() | PATCH 請求,json 形式 |
httpclient.Delete() | DELETE 請求 |
配置說明
配置項 | 配置方法 |
---|---|
設置 TTL 本次請求最大超時時間 | httpclient.WithTTL(ttl time.Duration) |
設置 Header 信息 | httpclient.WithHeader(key, value string) |
設置 Logger 信息 | httpclient.WithLogger(logger *zap.Logger) |
設置 Trace 信息 | httpclient.WithTrace(t trace.T) |
設置 Mock 信息 | httpclient.WithMock(m Mock) |
設置失敗時告警 | httpclient.WithOnFailedAlarm(alarmTitle string, alarmObject AlarmObject, alarmVerify AlarmVerify) |
設置失敗時重試 | httpclient.WithOnFailedRetry(retryTimes int, retryDelay time.Duration, retryVerify RetryVerify) |
設置 TTL
// 設置本次請求最大超時時間為 5s
httpclient.WithTTL(time.Second*5),
設置 Header 信息
可以調用多次進行設置多對 key-value 信息。
// 設置多對 key-value 信息,比如這樣:
httpclient.WithHeader("Authorization", "xxxx"),
httpclient.WithHeader("Date", "xxxx"),
設置 Logger 信息
傳遞的 logger 便於 httpclient 打印日志。
// 使用上下文中的 logger,比如這樣:
httpclient.WithLogger(ctx.Logger()),
設置 Trace 信息
傳遞的 trace 便於記錄使用 httpclient 調用第三方接口的鏈路日志。
// 使用上下文中的 trace,比如這樣:
httpclient.WithTrace(ctx.Trace()),
設置 Mock 信息
// Mock 類型
type Mock func() (body []byte)
// 需實現 Mock 方法,比如這樣:
func MockDemoPost() (body []byte) {
res := new(demoPostResponse)
res.Code = 1
res.Msg = "ok"
res.Data.Name = "mock_Name"
res.Data.Job = "mock_Job"
body, _ = json.Marshal(res)
return body
}
// 使用時:
httpclient.WithMock(MockDemoPost),
傳遞的 Mock 方式便於設置調用第三方接口的 Mock 數據。只要約定了接口文檔,即使對方接口未開發時,也不影響數據聯調。
設置失敗時告警
// alarmTitle 設置失敗告警標題 String
// AlarmObject 告警通知對象,可以是郵件、短信或微信
type AlarmObject interface {
Send(subject, body string) error
}
// 需要去實現 AlarmObject 接口,比如這樣:
var _ httpclient.AlarmObject = (*AlarmEmail)(nil)
type AlarmEmail struct{}
func (a *AlarmEmail) Send(subject, body string) error {
options := &mail.Options{
MailHost: "smtp.163.com",
MailPort: 465,
MailUser: "xx@163.com",
MailPass: "",
MailTo: "",
Subject: subject,
Body: body,
}
return mail.Send(options)
}
// AlarmVerify 定義符合告警的驗證規則
type AlarmVerify func(body []byte) (shouldAlarm bool)
// 需要去實現 AlarmVerify 方法,比如這樣:
func alarmVerify(body []byte) (shouldalarm bool) {
if len(body) == 0 {
return true
}
type Response struct {
Code int `json:"code"`
}
resp := new(Response)
if err := json.Unmarshal(body, resp); err != nil {
return true
}
// 當第三方接口返回的 code 不等於約定的成功值(1)時,就要進行告警
return resp.Code != 1
}
// 使用時:
httpclient.WithOnFailedAlarm("接口告警", new(third_party_request.AlarmEmail), alarmVerify),
設置失敗時重試
// retryTimes 設置重試次數 Int,默認:3
// retryDelay 設置重試前延遲等待時間 time.Duration,默認:time.Millisecond * 100
// RetryVerify 定義符合重試的驗證規則
type RetryVerify func(body []byte) (shouldRetry bool)
// 需要去實現 RetryVerify 方法,比如這樣:
func retryVerify(body []byte) (shouldRetry bool) {
if len(body) == 0 {
return true
}
type Response struct {
Code int `json:"code"`
}
resp := new(Response)
if err := json.Unmarshal(body, resp); err != nil {
return true
}
// 當第三方接口返回的 code 等於約定值(10010)時,就要進行重試
return resp.Code = 10010
}
// RetryVerify 也可以為 nil , 當為 nil 時,默認重試規則為 http_code 為如下情況:
// http.StatusRequestTimeout, 408
// http.StatusLocked, 423
// http.StatusTooEarly, 425
// http.StatusTooManyRequests, 429
// http.StatusServiceUnavailable, 503
// http.StatusGatewayTimeout, 504
// 使用時:
httpclient.WithOnFailedRetry(3, time.Second*1, retryVerify),
示例代碼
// 以 httpclient.PostForm 為例
api := "http://127.0.0.1:9999/demo/post"
params := url.Values{}
params.Set("name", name)
body, err := httpclient.PostForm(api, params,
httpclient.WithTTL(time.Second*5),
httpclient.WithTrace(ctx.Trace()),
httpclient.WithLogger(ctx.Logger()),
httpclient.WithHeader("Authorization", "xxxx"),
httpclient.WithMock(MockDemoPost),
httpclient.WithOnFailedRetry(3, time.Second*1, retryVerify),
httpclient.WithOnFailedAlarm("接口告警", new(third_party_request.AlarmEmail), alarmVerify),
)
if err != nil {
return nil, err
}
res = new(demoPostResponse)
err = json.Unmarshal(body, res)
if err != nil {
return nil, errors.Wrap(err, "DemoPost json unmarshal error")
}
if res.Code != 1 {
return nil, errors.New(fmt.Sprintf("code err: %d-%s", res.Code, res.Msg))
}
return res, nil
以上代碼在 go-gin-api 項目中,地址:https://github.com/xinliangnote/go-gin-api