The NET/HTTP package of the standard library provides HTTP client and server implementations. This article looks at the main client-related functions of the HTTP package through several major constructs.
1. Client
The client is responsible for sending requests to the server, specifying the low-level configuration of HTTP requests through an http.Transport instance, and replacing it with a default DefualtTransport instance.
// A Client is an HTTP client. Its zero value (DefaultClient) is a usable client that uses DefaultTransport.
type Client struct {
Transport RoundTripper
CheckRedirect func(req *Request, via []*Request) error
Jar CookieJar
Timeout time.Duration
}
// The RoundTripper interface provides a way to finally send the request. HTTP.Transport implements the RoundTripper interface
type RoundTripper interface {
// RoundTrip performs a single HTTP transaction and returns a response to the provided request.
RoundTrip(*Request) (*Response, error)
}
// DefaultTransport
var DefaultTransport RoundTripper = &Transport{
Proxy: ProxyFromEnvironment,
DialContext: (&net.Dialer{
Timeout: 30 * time.Second,
KeepAlive: 30 * time.Second,
DualStack: true,
}).DialContext,
ForceAttemptHTTP2: true,
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
}
Copy the code
The Do() method will eventually call RoundTrip to handle the request
// send issues an HTTP request.
func send(ireq *Request, rt RoundTripper, deadline time.Time) (resp *Response, didTimeout func(a) bool.err error) {
// Hide this part of the code to save space
resp, err = rt.RoundTrip(req)
// Hide this part of the code to save space
return resp, nil.nil
}
Copy the code
Configure the Transport instance for http.client
tr := &http.Transport{
Proxy: http.ProxyURL(w.ProxyAddr),
MaxIdleConnsPerHost: min(w.C, maxConn),
DisableCompression: w.DisableCompression,
DisableKeepAlives: w.DisableKeepAlives,
TLSClientConfig: &tls.Config{
InsecureSkipVerify: true,
ServerName: url.Host,
},
}
// Add the configuration to http. Client using the Transport instance
client := &http.Client{
Transport: tr,
Timeout: w.ConfigYaml.Http.Timeout * time.Second,
}
Copy the code
The Client structure provides methods for sending HTTP requests:
Do() takes an HTTP.request argument, and the other requests internally call the Do() method
Get(),Head(),
Post(), which can be custom contentType, receives body data
func (c *Client) Post(url, contentType string, body io.Reader) (resp *Response, err error) {
req, err := NewRequest("POST", url, body)
iferr ! =nil {
return nil, err
}
req.Header.Set("Content-Type", contentType)
return c.Do(req)
}
Copy the code
PostForm(), also sends a POST request, the difference is that the PostForm contentType is fixed to “Application/X-www-form-urlencoded”, and receives a URL. Values. Encode the data as “URL-encoded” (“bar=baz&foo=quux”),
func (c *Client) PostForm(url string, data url.Values) (resp *Response, err error) {
return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))
}
Copy the code
CloseIdleConnections() closes all previously requested connections that are now in the “keep-alive” state. It does not break any connections that are currently in use.
2. Transport
Configure the structure of low-level information for HTTP requests
Package:
http
// A Transport is a low-level primitive for making HTTP and HTTPS requests.
// For high-level functionality, such as cookies and redirects, see Client.
type Transport struct {
idleMu sync.Mutex
closeIdle bool
idleConn map[connectMethodKey][]*persistConn
idleConnWait map[connectMethodKey]wantConnQueue
idleLRU connLRU
reqMu sync.Mutex
reqCanceler map[*Request]func(error)
altMu sync.Mutex
altProto atomic.Value
connsPerHostMu sync.Mutex
connsPerHost map[connectMethodKey]int
connsPerHostWait map[connectMethodKey]wantConnQueue
Proxy func(*Request) (*url.URL, error)
DialContext func(ctx context.Context, network string, addr string) (net.Conn, error)
Dial func(network string, addr string) (net.Conn, error)
DialTLSContext func(ctx context.Context, network string, addr string) (net.Conn, error)
DialTLS func(network string, addr string) (net.Conn, error)
TLSClientConfig *tls.Config
TLSHandshakeTimeout time.Duration
DisableKeepAlives bool
DisableCompression bool
MaxIdleConns int
MaxIdleConnsPerHost int
MaxConnsPerHost int
IdleConnTimeout time.Duration
ResponseHeaderTimeout time.Duration
ExpectContinueTimeout time.Duration
TLSNextProto map[string]func(authority string, c *tls.Conn) RoundTripper
ProxyConnectHeader Header
MaxResponseHeaderBytes int64
WriteBufferSize int
ReadBufferSize int
nextProtoOnce sync.Once
h2transport h2Transport
tlsNextProtoWasNil bool
ForceAttemptHTTP2 bool
}
Copy the code
Http. Client actually executes requests with an instance of Transport. If not configured, DefaultTransport is used
func (c *Client) send(req *Request, deadline time.Time) (resp *Response, didTimeout func(a) bool.err error) {
ifc.Jar ! =nil {
for _, cookie := range c.Jar.Cookies(req.URL) {
req.AddCookie(cookie)
}
}
// The actual request is executed with a Transport instance
resp, didTimeout, err = send(req, c.transport(), deadline)
iferr ! =nil {
return nil, didTimeout, err
}
ifc.Jar ! =nil {
if rc := resp.Cookies(); len(rc) > 0 {
c.Jar.SetCookies(req.URL, rc)
}
}
return resp, nil.nil
}
// If http. Transport is not configured, DefaultTransport will be used instead
func (c *Client) transport(a) RoundTripper {
ifc.Transport ! =nil {
return c.Transport
}
return DefaultTransport
}
Copy the code
3. Request
Request represents a Request received through a Server or sent through a Client.
//A Request represents an HTTP request received by a server or to be sent by a client.
type Request struct {
Method string
URL *url.URL
Proto string
ProtoMajor int
ProtoMinor int
Header Header
Body io.ReadCloser
GetBody func(a) (io.ReadCloser, error)
ContentLength int64
TransferEncoding []string
Close bool
Host string
Form url.Values
PostForm url.Values
MultipartForm *multipart.Form
Trailer Header
RemoteAddr string
RequestURI string
TLS *tls.ConnectionState
Cancel <-chan struct{}
Response *Response
ctx context.Context
}
Copy the code
4. Cookie
Cookie Indicates the “set-cookie” in the HTTP response Header or the “Cookie” in the HTTP request Header.
type Cookie struct {
Name string
Value string
Path string
Domain string
Expires time.Time
RawExpires string
MaxAge int
Secure bool
HttpOnly bool
SameSite SameSite
Raw string
Unparsed []string
}
Methods:
func (c *Cookie) String(a) string
func SetCookie(w ResponseWriter, cookie *Cookie)
Copy the code
5. Response
Response Indicates the Response from the HTTP request. Http.Client and http.Transport return a Response. Once the Response header is received, the body field of the Response needs to be treated as a stream.
type Response struct {
Status string
StatusCode int
Proto string
ProtoMajor int
ProtoMinor int
Header Header
Body io.ReadCloser
ContentLength int64
TransferEncoding []string
Close bool
Uncompressed bool
Trailer Header
// Request is the request that was sent to obtain this Response.
// Request's Body is nil (having already been consumed).
// This is only populated for Client requests.
Request *Request
TLS *tls.ConnectionState
}
Methods:
Cookies() []*Cookie // Parse from header and return all set-cookies
Location() (*url.URL, error)
ProtoAtLeast(major int, minor int) bool // Verify that the HTTP protocol used in the response is at least major.minor.
Write(w io.Writer) error // Write the content of response to w
Copy the code