詳解Golang net/http包中的RoundTripper接口
RoundTripper 是什么?
RoundTripper 是 net/http 包中的一個(gè)接口,定義了處理 HTTP 請(qǐng)求返回和響應(yīng)的方法,是 http.Client 結(jié)構(gòu)體中執(zhí)行 http 請(qǐng)求的核心部分。接口定義如下:
type RoundTripper interface { RoundTrip(*Request) (*Response, error) }
只定義了 RoundTrip 一個(gè)方法,用于執(zhí)行單個(gè) HTTP 事務(wù),發(fā)送請(qǐng)求數(shù)據(jù)并返回對(duì)應(yīng)的響應(yīng)數(shù)據(jù)。RoundTrip 不應(yīng)該去解析響應(yīng)數(shù)據(jù),特別是如果獲得了響應(yīng)數(shù)據(jù)后,RoundTrip 必須返回值為 nil 的 error(不管響應(yīng)的HTTP狀態(tài)碼是什么)。如果沒(méi)有獲得響數(shù)據(jù),應(yīng)返回一個(gè)非 nil 的 error,RoundTrip 也不應(yīng)該嘗試處理更高級(jí)的協(xié)議細(xì)節(jié),如重定向、身份驗(yàn)證或 cookie 等。
除了消費(fèi)和關(guān)閉請(qǐng)求的 Body 之外,RoundTrip 不應(yīng)該修改請(qǐng)求,RoundTrip 可以在單獨(dú)的 goroutine 中讀取請(qǐng)求的字段。在 Response Body 被關(guān)閉之前,調(diào)用方不應(yīng)該改變或重用請(qǐng)求。RoundTrip 必須始終關(guān)閉 body(即使遇到 error),但根據(jù)實(shí)現(xiàn),即使在 RoundTrip 返回之后也可以在單獨(dú)的 goroutine 中關(guān)閉。
使用場(chǎng)景
借助 RoundTripper 可以在每個(gè)請(qǐng)求中添加特定的 header 或者對(duì)返回的響應(yīng)數(shù)據(jù)進(jìn)行特定的處理,例如記錄日志或根據(jù)返回的狀態(tài)碼執(zhí)行對(duì)應(yīng)邏輯。接下來(lái)看一個(gè)用于實(shí)現(xiàn)鏈路追蹤功能,只需要實(shí)現(xiàn) RoundTripper 接口,在執(zhí)行 HTTP 請(qǐng)求的同時(shí),收集遙測(cè)數(shù)據(jù),如請(qǐng)求的持續(xù)時(shí)間、狀態(tài)碼等,這些數(shù)據(jù)可以用于性能監(jiān)控和故障排查。實(shí)現(xiàn) RoundTripper 接口的示例代碼如下:
package http_otel import ( "net/http" "go.opentelemetry.io/otel" "go.opentelemetry.io/otel/attribute" "go.opentelemetry.io/otel/codes" ) type OtelRoundTripper struct { original http.RoundTripper } func (ort *OtelRoundTripper) RoundTrip(req *http.Request) (*http.Response, error) { tracer := otel.Tracer("") ctx, span := tracer.Start(req.Context(), req.URL.Path) defer span.End() req = req.WithContext(ctx) resp, err := ort.original.RoundTrip(req) if err != nil { span.RecordError(err) span.SetStatus(codes.Error, err.Error()) } else { attrs := []attribute.KeyValue{ { Key: "http.status_code", Value: attribute.IntValue(resp.StatusCode), }, { Key: "http.method", Value: attribute.StringValue(req.Method), }, { Key: "http.route", Value: attribute.StringValue(req.URL.RequestURI()), }, { Key: "http.scheme", Value: attribute.StringValue(req.URL.Scheme), }, { Key: "http.user_agent", Value: attribute.StringValue(req.UserAgent()), }, } span.SetAttributes(attrs...) } return resp, err } func New() *OtelRoundTripper { return &OtelRoundTripper{ original: tripper, } }
使用 net/http 包實(shí)現(xiàn)鏈路追蹤代碼如下:
package main import ( "bytes" "fmt" "xxx/http-otel" "io" "net/http" ) func main() { reader := bytes.NewReader([]byte(`{"foo":"bar"}`)) request, err := http.NewRequest("POST", "http://xxx.com/user/list", reader) if err != nil { panic(err) } request = request.WithContext(traceCtx) // traceCtx 指上文的 context,這里使用偽代碼作演示 request.Header.Set("Content-Type", "application/json") client := http.Client{Transport: http_otel.New()} resp, err := client.Do(request) if err != nil { panic(err) } defer resp.Body.Close() b, err := io.ReadAll(resp.Body) fmt.Println(string(b), err) }
首先定義了一個(gè)用于實(shí)現(xiàn)鏈路追蹤功能的 OtelRoundTripper 結(jié)構(gòu)體,然后實(shí)現(xiàn)了 RoundTrip 方法。在 RoundTrip 方法中,首先開(kāi)啟一個(gè)新的 trace span,并且將追蹤的信息編碼到 HTTP 請(qǐng)求的 header 中。在請(qǐng)求完成后,將返回的 HTTP 響應(yīng)信息記錄到 trace 中,并返回 HTTP 響應(yīng)數(shù)據(jù)。
小結(jié)
RoundTripper 接口的強(qiáng)大之處在于能夠以簡(jiǎn)單且可擴(kuò)展的方式自定義和控制 HTTP 請(qǐng)求的處理。無(wú)論是添加特定的 header、處理響應(yīng)還是執(zhí)行其他更高級(jí)的邏輯,都可以借助 RoundTripper 來(lái)實(shí)現(xiàn)。
以上就是詳解Golang net/http包中的RoundTripper接口的詳細(xì)內(nèi)容,更多關(guān)于Golang RoundTripper接口的資料請(qǐng)關(guān)注腳本之家其它相關(guān)文章!
相關(guān)文章
手把手帶你走進(jìn)Go語(yǔ)言之運(yùn)算符解析
這篇文章主要介紹了手Go語(yǔ)言之運(yùn)算符解析,本文給大家介紹的非常詳細(xì),對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2021-09-09Go語(yǔ)言七篇入門(mén)教程三函數(shù)方法及接口
這篇文章主要為大家介紹了Go語(yǔ)言的函數(shù)方法及接口的示例詳解,本文是Go語(yǔ)言七篇入門(mén)系列文章,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步2021-11-11使用dep 配置golang 開(kāi)發(fā)環(huán)境的操作方法
下面小編就為大家?guī)?lái)一篇使用dep 配置golang 開(kāi)發(fā)環(huán)境的操作方法。小編覺(jué)得挺不錯(cuò)的,現(xiàn)在就分享給大家,也給大家做個(gè)參考。一起跟隨小編過(guò)來(lái)看看吧2017-09-09Go語(yǔ)言特點(diǎn)及基本數(shù)據(jù)類(lèi)型使用詳解
這篇文章主要為大家介紹了Go語(yǔ)言特點(diǎn)及基本數(shù)據(jù)類(lèi)型使用詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-03-03go單例實(shí)現(xiàn)雙重檢測(cè)是否安全的示例代碼
這篇文章主要介紹了go單例實(shí)現(xiàn)雙重檢測(cè)是否安全,本文給大家分享雙重檢驗(yàn)示例代碼,代碼簡(jiǎn)單易懂,對(duì)大家的學(xué)習(xí)或工作具有一定的參考借鑒價(jià)值,需要的朋友可以參考下2022-03-03Go Excelize API源碼解讀GetSheetViewOptions與SetPageLayo
這篇文章主要為大家介紹了Go Excelize API源碼解讀GetSheetViewOptions與SetPageLayout方法示例,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進(jìn)步,早日升職加薪2022-08-08Golang使用JWT進(jìn)行認(rèn)證和加密的示例詳解
JWT是一個(gè)簽名的JSON對(duì)象,通常用作Oauth2的Bearer?token,JWT包括三個(gè)用.分割的部分。本文將利用JWT進(jìn)行認(rèn)證和加密,感興趣的可以了解一下2023-02-02golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法
這篇文章主要介紹了golang實(shí)現(xiàn)unicode轉(zhuǎn)換為字符串string的方法,實(shí)例分析了Go語(yǔ)言編碼轉(zhuǎn)換的相關(guān)技巧,具有一定參考借鑒價(jià)值,需要的朋友可以參考下2016-07-07