douli4852 2019-01-08 09:20
浏览 107
已采纳

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

I know that I can add headers to each HTTP request manually using

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)

but I want to add this header automatically for each HTTP request in my app.

What is the best way to do it?

  • 写回答

2条回答 默认 最新

  • dtewnsdf47253 2019-01-08 09:40
    关注

    I'm aware of three possible solutions to this. In (my) order of preference:

    1. Wrap http.NewRequest with custom code that adds desired headers:

      func MyRequest(method, path url, 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
      }
      

      This approach has the advantage of being straight-forward, non-magical, and portable. It will work with any third-party software, that adds its own headers, or sets custom transports.

      The only case where this won't work is if you depend on a third-party library to create your HTTP requests. I expect this is rare (I don't recall ever running into this in my own experience). And even in such a case, perhaps you can wrap that call instead.

    2. Wrap calls to client.Do to add headers, and possibly any other shared logic.

      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
      }
      

      This approach is also straight-forward, and has the added advantage (over #1) of making it easy to reduce other boilerplate. This general method can also work very well in conjunction with #1. One possible draw-back is that you must always call your MyDo method directly, meaning you cannot rely on third party software which calls http.Do itself.

    3. Use a custom 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)
      }
      

      Then use it like this:

      client := &Client{Transport: &myTransport{}}
      req := http.NewRequest("GET", "/foo", nil)
      res, err := client.Do(req)
      

      This approach has the advantage of working "behind the scenes" with just about any other software, so if you rely on a third-party library to create your http.Request objects, and to call http.Do, this may be your only option.

      However, this has the potential disadvantage of being non-obvious, and possibly breaking if you're using any third-party software which also sets a custom transport (without bothering to honor an existing custom transport).

    Ultimately, which method you use will depend on what type of portability you need with third-party software. But if that's not a concern, I suggest using the most obvious solution, which, by my estimation, is the order provided above.

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥60 更换迈创SOL6M4AE卡的时候,驱动要重新装才能使用,怎么解决?
  • ¥15 让node服务器有自动加载文件的功能
  • ¥15 jmeter脚本回放有的是对的有的是错的
  • ¥15 r语言蛋白组学相关问题
  • ¥15 Python时间序列如何拟合疏系数模型
  • ¥15 求学软件的前人们指明方向🥺
  • ¥50 如何增强飞上天的树莓派的热点信号强度,以使得笔记本可以在地面实现远程桌面连接
  • ¥20 双层网络上信息-疾病传播
  • ¥50 paddlepaddle pinn
  • ¥20 idea运行测试代码报错问题