发起HTTP请求

在日常开发中,发起 HTTP 请求是一个非常频繁的任务。

Go 语言提供了 net/http 包,协助用户实施与 HTTP 协议相关的开发任务。该包既提供了 HTTP服务器 实现,又提供了 客户端 实现。

本文介绍如何使用 net/http 包发起 HTTP 请求,覆盖大部分应用场景:

Get请求

发起 Get 请求是最常见的场景之一,使用 http.Get 函数即可。代码示例如下:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "net/http"
  6. "io/ioutil"
  7. )
  8.  
  9. func main() {
  10. rsps, err := http.Get("http://example.com")
  11. if err != nil {
  12. fmt.Println("Request failed:", err)
  13. return
  14. }
  15. defer rsps.Body.Close()
  16.  
  17. body, err := ioutil.ReadAll(rsps.Body)
  18. if err != nil {
  19. fmt.Println("Read body failed:", err)
  20. return
  21. }
  22.  
  23. fmt.Println(string(body))
  24. }

10 行调用 http.Get 函数发起 Get 请求;第 15 行在 main 函数结束时关闭 Body 对象;第 17 行读取整个响应体;第 23 行输出响应内容。

警告

http.Get 函数使用默认的客户端设置,默认不超时。挂起的请求将劫持 goroutine ,严重时可导致程序停止响应。因此,禁止在生产业务中使用默认客户端设置。超时设置 一节介绍如何设置请求超时时间。

Post请求

发起 Post 请求的方式也是类似的,代码如下:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "net/http"
  6. "io/ioutil"
  7. )
  8.  
  9. func main() {
  10. rsps, err := http.Post("http://example.com/", "plain/text", nil)
  11. if err != nil {
  12. fmt.Println("Request failed:", err)
  13. return
  14. }
  15. defer rsps.Body.Close()
  16.  
  17. body, err := ioutil.ReadAll(rsps.Body)
  18. if err != nil {
  19. fmt.Println("Read body failed:", err)
  20. return
  21. }
  22.  
  23. fmt.Println(string(body))
  24. }

注意到, http.Post 函数接口与 http.Get 稍有区别,多了两个参数:

  • Content Type 头部,这里我们填 plain/text
  • 请求体,为 io.Reader 类型,没有请求体则填 nil

超时设置

超时设置需先准备一个 http.Client 结构体, Timeout 字段即是超时设置,单位为秒。之后调用结构体相关请求方法发起请求,示例代码片段如下:

  1. var client = &http.Client{
  2. Timeout: time.Second * 5,
  3. }
  4.  
  5. rsps, err := client.Get("http://example.com")

小技巧

生产业务请务必设置超时时间,以免 goroutine 被超时请求劫持而停止响应。

设置头部

设置头部须直接操作 http.Request 结构体,以添加头部 X-My-Auth 为例:

  1. package main
  2.  
  3. import (
  4. "fmt"
  5. "net/http"
  6. "io/ioutil"
  7. "time"
  8. )
  9.  
  10. func main() {
  11. var client = &http.Client{
  12. Timeout: time.Second * 5,
  13. }
  14.  
  15. rqst, err := http.NewRequest("GET", "http://example.com", nil)
  16. if err != nil {
  17. fmt.Println("New request failed:", err)
  18. return
  19. }
  20.  
  21. rqst.Header.Add("X-My-Auth", "xxxx")
  22.  
  23. rsps, err := client.Do(rqst)
  24. if err != nil {
  25. fmt.Println("Request failed:", err)
  26. return
  27. }
  28. defer rsps.Body.Close()
  29.  
  30. body, err := ioutil.ReadAll(rsps.Body)
  31. if err != nil {
  32. fmt.Println("Read body failed:", err)
  33. return
  34. }
  35.  
  36. fmt.Println(string(body))
  37. }

15 行初始化 http.Request 结构体,指定请求方法, URL 以及请求体;第 21 行调用 Header 字段 Add 方法添加给定头部;第 23 行调用客户端 Do 方法发起请求。

添加 Cookie 也是通过调用 http.Request 结构体方法完成,代码片段如下:

  1. rqst, err := http.NewRequest("GET", "http://example.com", nil)
  2. if err != nil {
  3. fmt.Println("New request failed:", err)
  4. return
  5. }
  6.  
  7. rqst.AddCookie(&http.Cookie{
  8. Name: "MyCookie",
  9. Value: "xxxx",
  10. })
  11.  
  12. rsps, err := client.Do(rqst)

1 行初始化 http.Request 结构体;第 7 行调用 AddCookie 方法设置设置 Cookie ,参数为 Cookie 结构体,只填充键值字段;

Basic认证

同样,进行 Basic 认证也需要操作 http.Request 结构体。代码片段如下:

  1. rqst, err := http.NewRequest("GET", "http://example.com", nil)
  2. if err != nil {
  3. fmt.Println("New request failed:", err)
  4. return
  5. }
  6.  
  7. rqst.SetBasicAuth("user", "password")
  8.  
  9. rsps, err := client.Do(rqst)

1 行初始化 http.Request 结构体;第 7 行调用 SetBasicAuth 方法设置认证信息。

下一步

订阅更新,获取更多学习资料,请关注我们的 微信公众号

../_images/wechat-mp-qrcode.png小菜学编程

参考文献