为了账号安全,请及时绑定邮箱和手机立即绑定

使用客户端为每个 HTTP 请求添加标头

使用客户端为每个 HTTP 请求添加标头

Go
饮歌长啸 2023-06-01 09:57:53
我知道我可以使用手动向每个 HTTP 请求添加标头cli := &http.Client{}req, err := http.NewRequest("GET", "https://myhost", nil)req.Header.Add("X-Test", "true")if err != nil {    panic(err)}rsp, err := cli.Do(req)但我想为我的应用程序中的每个 HTTP 请求自动添加此标头。最好的方法是什么?
查看完整描述

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,这可能是您唯一的选择。


但是,这具有不明显的潜在缺点,如果您使用任何也设置自定义传输的第三方软件(无需费心遵守现有的自定义传输),则可能会中断。


最终,您使用哪种方法将取决于您需要第三方软件的可移植性类型。但如果这不是问题,我建议使用最明显的解决方案,据我估计,这就是上面提供的顺序。


查看完整回答
反对 回复 2023-06-01
?
牧羊人nacy

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)

    }

}


查看完整回答
反对 回复 2023-06-01
  • 2 回答
  • 0 关注
  • 136 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信