Go - httpclient 常用操作

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: "[email protected]",
		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

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章