func (client *Client) Do(httpRequest *http.Request) (
	httpRes *http.Response, resBody []byte, err error,
) {
	logp := "Do"
	if debug.Value >= 3 {
		dump, err := httputil.DumpRequestOut(httpRequest, true)
		if err != nil {
			log.Printf("%s: %s\n", logp, err)
		} else {
			fmt.Printf("%s\n", dump)
		}
	}
	httpRes, err = client.Client.Do(httpRequest)
	if err != nil {
		return nil, nil, fmt.Errorf("%s: %w", logp, err)
	}
	if debug.Value >= 3 {
		dump, err := httputil.DumpResponse(httpRes, true)
		if err != nil {
			log.Printf("%s: %s", logp, err)
		} else {
			fmt.Printf("%s\n", dump)
		}
	}
	rawBody, err := ioutil.ReadAll(httpRes.Body)
	if err != nil {
		return nil, nil, fmt.Errorf("%s: %w", logp, err)
	}
	err = httpRes.Body.Close()
	if err != nil {
		return httpRes, resBody, fmt.Errorf("%s: %w", logp, err)
	}
	resBody, err = client.uncompress(httpRes, rawBody)
	if err != nil {
		return httpRes, resBody, fmt.Errorf("%s: %w", logp, err)
	}
	httpRes.Body = io.NopCloser(bytes.NewReader(rawBody))
	return httpRes, resBody, nil
}
Do overwrite the standard http Client.Do to allow debugging request and
response, and to read and return the response body immediately.
package http
import (
	"bytes"
	"compress/bzip2"
	"compress/flate"
	"compress/gzip"
	"compress/lzw"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"mime/multipart"
	"net"
	"net/http"
	"net/http/httputil"
	"net/url"
	"strings"
	"time"
	"github.com/shuLhan/share"
	"github.com/shuLhan/share/lib/debug"
)
const (
	defUserAgent = "libhttp/" + share.Version +
		" (github.com/shuLhan/share/lib/http; ms@kilabit.info)"
)
type Client struct {
	*http.Client
	flateReader io.ReadCloser
	gzipReader  *gzip.Reader
	serverURL  string
	defHeaders http.Header
}
func NewClient(serverURL string, headers http.Header, insecure bool) (client *Client) {
	if headers == nil {
		headers = make(http.Header)
	}
	httpTransport := &http.Transport{
		Proxy: http.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,
	}
	client = &Client{
		serverURL:  serverURL,
		defHeaders: headers,
		Client:     &http.Client{},
	}
	if insecure {
		httpTransport.TLSClientConfig = &tls.Config{
			InsecureSkipVerify: insecure,
		}
	}
	client.Client.Transport = httpTransport
	client.setUserAgent()
	return client
}
func (client *Client) Delete(path string, headers http.Header, params url.Values) (
	httpRes *http.Response, resBody []byte, err error,
) {
	if params != nil {
		path += "?" + params.Encode()
	}
	return client.doRequest(http.MethodDelete, headers, path, "", nil)
}