2 回答

TA貢獻1784條經驗 獲得超7個贊
我知道三種可能的解決方案。按照(我的)偏好順序:
http.NewRequest用添加所需標頭的自定義代碼包裝:
func MyRequest(method, path string, body io.Reader) (*http.Request, error) {
req, err := http.NewRequest(method, path, body)
if err != nil {
return nil, err
}
req.Header.Add("X-Test", "true")
return req, nil
}
這種方法的優點是直接、非魔法且可移植。它將與添加自己的標頭或設置自定義傳輸的任何第三方軟件一起使用。
唯一不起作用的情況是您依賴第三方庫來創建 HTTP 請求。我希望這種情況很少見(我不記得在我自己的經歷中遇到過這種情況)。即使在這種情況下,也許您也可以改為包裝該調用。
包裝調用以client.Do添加標頭,以及可能的任何其他共享邏輯。
func MyDo(client *http.Client, req *http.Request) (*http.Response, error) {
req.Header.Add("X-Test", "true")
// Any other common handling of the request
res, err := client.Do(req)
if err != nil {
return nil, err
}
// Any common handling of response
return res, nil
}
這種方法也很直接,并且具有額外的優勢(超過#1)可以輕松減少其他樣板文件。這種通用方法也可以很好地與#1 結合使用。一個可能的缺點是您必須始終MyDo直接調用您的方法,這意味著您不能依賴調用自身的第三方軟件http.Do。
使用自定義http.Transport
type myTransport struct{}
func (t *myTransport) RoundTrip(req *http.Request) (*http.Response, error) {
req.Header.Add("X-Test", "true")
return http.DefaultTransport.RoundTrip(req)
}
然后像這樣使用它:
client := &Client{Transport: &myTransport{}}
req := http.NewRequest("GET", "/foo", nil)
res, err := client.Do(req)
這種方法的優點是可以在幾乎任何其他軟件的“幕后”工作,因此如果您依賴第三方庫來創建對象http.Request并調用http.Do,這可能是您唯一的選擇。
但是,這具有不明顯的潛在缺點,如果您使用任何也設置自定義傳輸的第三方軟件(無需費心遵守現有的自定義傳輸),則可能會中斷。
最終,您使用哪種方法將取決于您需要第三方軟件的可移植性類型。但如果這不是問題,我建議使用最明顯的解決方案,據我估計,這就是上面提供的順序。

TA貢獻1862條經驗 獲得超7個贊
可以配置http.Client
為使用自定義傳輸,它可以處理客戶端中的每個請求(在golang.org/x/oauth2庫中找到此實現)。此示例將標頭附加到每個 http 請求:
type transport struct {
headers map[string]string
base http.RoundTripper
}
func (t *transport) RoundTrip(req *http.Request) (*http.Response, error) {
for k, v := range t.headers {
req.Header.Add(k, v)
}
base := t.base
if base == nil {
base = http.DefaultTransport
}
return base.RoundTrip(req)
}
func main() {
cli := &http.Client{
Transport: &transport{
headers: map[string]string{
"X-Test": "true",
},
},
}
rsp, err := cli.Get("http://localhost:8080")
defer rsp.Body.Close()
if err != nil {
panic(err)
}
}
- 2 回答
- 0 關注
- 183 瀏覽
添加回答
舉報