Go HTTP Programming (1): How does the client initiate an HTTP request

 There is no problem at all to access network services based on the HTTP protocol through the  net.Dial or  net.DialTimeoutfunction, because the HTTP protocol is based on the TCP/IP protocol stack. But no problems does not mean easy, if through  net.Dial an HTTP programming function, HTTP status code, packet header processing section and the entity it is quite cumbersome for more details (you can read about the HTTP protocol network protocol in the application layer protocol to Learn more), so the Go language standard library has a built-in  net/http  package to cover the specific implementation of HTTP client and server. Through the  net/http package, we can write HTTP client and server programs more conveniently and quickly.

First, let's look at HTTP client programming.

http.Client

The net/http  package provides the most concise HTTP client implementation, and you can directly use the most common  GET and  POST methods to initiate HTTP requests.

Specifically, we can   initiate HTTP requests through the following methods provided by net/http the Clientclasses in the package  :

func (c *Client) Do(req *Request) (*Response, error)
func (c *Client) Get(url string) (resp *Response, err error)
func (c *Client) Head(url string) (resp *Response, err error)
func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error)
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error)

The following briefly introduces the use of these methods.

http.Get

Sample code

To initiate a GET request, just call the  http.Get() method and pass in the request URL. The sample code is as follows:

resp, err := http.Get("https://www.csdn.net/") 
if err != nil {
    fmt.Printf("发起请求失败:%v", err)
    return 
}

defer resp.Body.Close() 
io.Copy(os.Stdout, resp.Body)

The above code is used to initiate a request to the CSDN homepage and print its web content to the standard output stream.

Bottom call

In fact  http.Get , when a request is initiated http.Client , the Get method on the above default object is called by  default  :

func Get(url string) (resp *Response, err error) {
    return DefaultClient.Get(url)
}

And the  DefaultClient default point is the  http.Client object instance:

var DefaultClient = &Client{}

It is  net/http a property of the disclosed package, when we  http on the call  Get, Post, PostForm, Head when the method, the final corresponding method is invoked on the object.

return value

Back to the  http.Get() method itself, the method returns two values, the first is the response object, and the second is the  error object. If an error occurs during the request process, the  error object is not empty, otherwise, the status code and response can be obtained through the response object Header, response entity and other information. The response object belongs to the class  http.Response. You can check the  API documentation or source code to understand the specific information of the type. Generally, we can  resp.Body get the response entity,  resp.Header get the response header, and  resp.StatusCode get the response status code.

After getting the response successfully, remember to call the  resp.Body above  Close method to end the network request to release resources.

http.Post

To send data in POST, it is also very simple, just call the  http.Post() method and pass the following 3 parameters in turn:

  • URL of the request target
  • Resource type of POST request data (MIMEType)
  • Data bitstream ( []byte form)

The following sample code demonstrates how to upload a user avatar:

resp, err := http.Post("https://xueyuanjun.com/avatar", "image/jpeg", &imageDataBuf) 
if err != nil {
    // 处理错误
    return 
}

if resp.StatusCode != http.StatusOK { 
    // 处理错误 
    return 
} 

// ...

The underlying implementation and return value are the  http.Get same.

http.PostForm

http.PostForm() The method implements the application/x-www-form-urlencoded POST form submission in the standard encoding format  .

The following sample code simulates HTML login form submission:

resp, err := http.PostForm("https://xueyuanjun.com/login", url.Values{"name":{"学院君"}, "password": {"test-passwd"}}) 

if err != nil {
    // 处理错误
    return 
} 

if resp.StatusCode != http.StatusOK { 
    // 处理错误 
    return 
} 

// ...

Note that POST request parameters need to url.Values be encoded and encapsulated by  methods.

The underlying implementation and return value are the  http.Get same.

http.Head

The HTTP Head request means that only the response header information of the target URL is requested, and the response entity is not returned. We can http.Head() initiate a Head request through a  method, which http.Get() is the same as the method  , just pass in the target URL parameters.

The following sample code is used to request the HTTP response header information of the CSDN homepage :

resp, err := http.Head("https://www.csdn.net/")
if err != nil {
    fmt.Println("Request Failed: ", err.Error())
    return
}

defer resp.Body.Close()
// 打印头信息
for  key, value := range resp.Header  {
    fmt.Println(key, ":", value)
}

http.Head() The response entity resp.Body value returned by the  method  is empty.

The underlying implementation and return value are the  http.Get same.

(*http.Client).Do

Finally, let's take a look at  http.Client the Do methods of the class  .

In most cases http.Get, http.Post and  http.PostForm to meet demand, but if we need to initiate HTTP requests to set up more custom request headers, such as:

  • Set a custom  User-Agent, not the default  Go http package;
  • Pass cookie information;
  • HTTP requests initiated by other means, such as  PUT, PATCH, DELETE and the like.

At this point, it can be achieved by http.Client the Do() method provided by the  class  . When using this method, the method in the  class is no longer called through the default  DefaultClient object  http.Client, but we need to manually instantiate the  Client object and pass in and add custom request header information The request object to initiate an HTTP request:

// 初始化客户端请求对象
req, err := http.NewRequest("GET", "https://xueyuanjun.com", nil)
if err != nil {
    fmt.Printf("请求初始化失败:%v", err)
    return
}
// 添加自定义请求头
req.Header.Add("Custom-Header", "Custom-Value")
// ... 其它请求头配置
client := &http.Client{
    // ... 设置客户端属性
}
resp, err := client.Do(req)
if err != nil {
    fmt.Printf("客户端发起请求失败:%v", err)
    return
}

defer resp.Body.Close()
io.Copy(os.Stdout, resp.Body)

The http.NewRequest method used to initialize the request object  needs to pass in three parameters, the first is the request method, the second is the target URL, and the third is the request entity. Only requests such as POST, PUT, and DELETE need to set the request entity , For HEAD and GET, just pass in  nil .

http.NewRequest The first value returned by the method is the request object instance  req, which belongs to the class  http.Request. You can call the public methods and attributes on this class to customize the request object, such as request method, URL, request header, etc.

After the setting is complete, you can pass the request object into the  client.Do() method to initiate an HTTP request, and the subsequent operations are the same as the previous four basic methods.

More usage details will be introduced separately in subsequent tutorials, such as how to set up cookies, how to upload and download files, how to handle request/response timeouts, etc. Here is just a brief introduction to the use of these basic HTTP request methods.

Guess you like

Origin blog.csdn.net/wxy_csdn_world/article/details/107442694