Home > Article > Backend Development > golang encapsulates http requests
With the development of the Internet, HTTP requests have become the standard for back-end development and are also the way for the front-end to initiate network requests. In Golang, the standard library has a built-in net/http package, providing a complete HTTP client and server. However, encapsulating an HTTP request library allows us to initiate HTTP requests more efficiently and conveniently during the development process. In this article, we will discuss how to encapsulate a Golang HTTP request library.
1. Requirements Analysis
Before encapsulating an HTTP request library, we need to clarify some requirements and functions in order to better design and develop our library. Here, we believe that a complete HTTP request library needs to have the following functions:
Based on the above requirements and functions, we can start to design and develop our HTTP request library.
2. Design and Implementation
2.1 Design Points
When designing our HTTP request library, we need to consider some key points in order to achieve a highly available and reliable Extensible and easy-to-use requests library. Specifically, we should consider the following aspects:
When initiating an HTTP request, we must consider network problems, such as connection timeout, request timeout, etc. Therefore, our HTTP request library needs to support setting the connection timeout and request timeout.
When we initiate an HTTP request, various unpredictable exceptions may occur, such as network exceptions, return value exceptions, etc. In order to make our HTTP request library more robust, these exceptions need to be handled, for example, based on http status codes, exception information, etc.
In RESTful API, it is often necessary to submit JSON data or form data, etc. Therefore, in our HTTP request library, we need to support the submission and parsing of these data.
After initiating the HTTP request, we need to process the return value. Generally, the format of the return value of different API interfaces may be different. Therefore, we need to support corresponding processing according to the return value format of the API interface.
2.2 Implementation process
Based on the above design points, when we start to implement the HTTP request library, we can follow the following steps:
When encapsulating an HTTP request library, we need to encapsulate the HTTP request information. Specifically, we can define a structure of an HTTP request to store and transfer the information required for the HTTP request. The following is an example of the structure of an HTTP request:
type Request struct { URL string Method string Headers map[string]string Body []byte Params map[string]string Timeout int RetryTimes int }
After we define the HTTP request structure, we can send HTTP requests through Golang's standard library.
For example, we can use the http.NewRequest() method to create an HTTP request:
req, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body)) if err != nil { return nil, err }
Use the DialContext() method in http.Transport to set the connection timeout and request timeout:
client := &http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: time.Duration(req.Timeout) * time.Second, KeepAlive: time.Duration(req.Timeout) * time.Second, }).DialContext, MaxIdleConns: 100, // http.ConnectionPool数量 IdleConnTimeout: 90 * time.Second, // http.ConnectionPool中连接的空闲超时时间 TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, } }
Next, we can use the Do() method to initiate an HTTP request and get the return value:
resp, err := client.Do(req) if err != nil { return nil, err }
After successfully initiating the HTTP request, we need to release resources to avoid memory leaks caused by malicious requests:
defer resp.Body.Close()
When initiating an HTTP request, various unpredictable exceptions may occur, such as network exceptions, return value exceptions, etc. Therefore, these exceptions need to be handled in our HTTP request library.
For example, we can check HTTP request exceptions based on HTTP status code and response body. If an exception occurs, we can return corresponding error information according to the type of exception, so that it can be discovered and processed in time during the development process.
When calling RESTful API, we need to support different submission formats, such as JSON data or form data, etc. To make our HTTP request library more versatile, a ContentType attribute field can be added to support different submission formats. At the same time, when submitting JSON data, we also need to encode the data into JSON format.
After calling the interface, we need to process the return value. Generally, the format of the return value of different API interfaces may be different. Therefore, we need to perform corresponding processing in the upper-layer application according to the return value format of the API interface. For example, you can set the deserialization method based on the format of the return value.
2.3 Code Implementation
Based on the above design points, when we start to implement the HTTP request library, we can refer to the following code implementation:
package httpreq import ( "bytes" "encoding/json" "io/ioutil" "net" "net/http" "time" ) type Request struct { URL string Method string Headers map[string]string Body []byte Params map[string]string Timeout int RetryTimes int ContentType string } type Response struct { StatusCode int Body []byte } func Do(req Request) (*Response, error) { if req.Method == "" { req.Method = http.MethodGet } // 处理请求参数 if req.Params != nil { req.URL = AddQueryParams(req.URL, req.Params) } // 创建一个请求 httpRequest, err := http.NewRequest(req.Method, req.URL, bytes.NewBuffer(req.Body)) if err != nil { return nil, err } // 处理请求头 if req.Headers != nil { for k, v := range req.Headers { httpRequest.Header.Set(k, v) } } // 设置ContentType if req.ContentType != "" { httpRequest.Header.Set("Content-Type", req.ContentType) } // 设置请求超时 httpClient := &http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: time.Duration(req.Timeout) * time.Second, KeepAlive: time.Duration(req.Timeout) * time.Second, }).DialContext, MaxIdleConns: 100, // http.ConnectionPool数量 IdleConnTimeout: 90 * time.Second, // http.ConnectionPool中连接的空闲超时时间 TLSHandshakeTimeout: 10 * time.Second, ExpectContinueTimeout: 1 * time.Second, }, } // 发起请求 resp, err := httpClient.Do(httpRequest) if err != nil { return nil, err } defer resp.Body.Close() body, err := ioutil.ReadAll(resp.Body) if err != nil { return nil, err } // 处理异常 if resp.StatusCode >= 400 { return nil, NewError(resp.StatusCode, body) } return &Response{StatusCode: resp.StatusCode, Body: body}, nil } func AddQueryParams(url string, params map[string]string) string { var queryParams string for k, v := range params { queryParams = queryParams + "&" + k + "=" + v } url = url + "?" + queryParams[1:] return url } func NewError(statusCode int, body []byte) error { errorMsg := string(body) if errorMsg == "" { errorMsg = http.StatusText(statusCode) } return &httpError{StatusCode: statusCode, Message: errorMsg} } type httpError struct { StatusCode int Message string } func (e *httpError) Error() string { return e.Message } func (r *Response) BindJSON(v interface{}) error { return json.Unmarshal(r.Body, v) } func (r *Response) BindText() string { return string(r.Body) }
3. Summary
Through the above discussion, we can find that encapsulating a Golang HTTP request library is not a particularly difficult task. The key is that we should be clear about our needs and understand some details of network requests, and then we can use the methods provided by the standard library to encapsulate an excellent HTTP request library in Golang. At the same time, during the implementation process, we also need to consider some details, such as exception handling, RESTful API support, processing of return values, etc. Through careful design and implementation, we can develop a high-quality HTTP request library to make our Golang development more efficient and convenient.
The above is the detailed content of golang encapsulates http requests. For more information, please follow other related articles on the PHP Chinese website!