package utils import ( "bytes" "encoding/json" "fmt" "io" "net" "net/http" "sync" "time" ) var once sync.Once var _client *http.Client func GetHttpClient() *http.Client { once.Do(func() { _client = &http.Client{ Timeout: time.Minute * 1, //设置超时时间 Transport: &http.Transport{ Proxy: http.ProxyFromEnvironment, DialContext: (&net.Dialer{ Timeout: 30 * time.Second, KeepAlive: 30 * time.Second, }).DialContext, TLSHandshakeTimeout: 10 * time.Second, //限制 TLS握手的时间 ResponseHeaderTimeout: 10 * time.Second, //限制读取response header的时间,默认 timeout + 5*time.Second ExpectContinueTimeout: 1 * time.Second, //限制client在发送包含 Expect: 100-continue的header到收到继续发送body的response之间的时间等待。 MaxIdleConns: 100, //所有host的连接池最大连接数量,默认无穷大 MaxIdleConnsPerHost: 30, //每个host的连接池最大空闲连接数,默认2 MaxConnsPerHost: 10, //每个host的最大连接数量 IdleConnTimeout: 3 * time.Minute, //how long an idle connection is kept in the connection pool. }, } }) return _client } func getBytes(request interface{}) ([]byte, error) { var body []byte switch t := request.(type) { case []byte: body = t case string: body = []byte(t) default: var err error body, err = json.Marshal(request) if err != nil { return nil, err } } return body, nil } type OnHttpResponse func(res *http.Response) error func HttpRequest(req *http.Request, onResponse OnHttpResponse) error { client := GetHttpClient() res, err := client.Do(req) if err != nil { return err } defer res.Body.Close() if onResponse != nil { err = onResponse(res) } return err } func HttpMethod(url, method string, header http.Header, body io.Reader, onResponse OnHttpResponse) error { req, err := http.NewRequest(method, url, body) if err != nil { return err } if header != nil { req.Header = header } return HttpRequest(req, onResponse) } func HttpGet(url string, header http.Header, body io.Reader, onResponse OnHttpResponse) error { return HttpMethod(url, http.MethodGet, header, body, onResponse) } func HttpPost(url string, header http.Header, body io.Reader, onResponse OnHttpResponse) error { return HttpMethod(url, http.MethodPost, header, body, onResponse) } func HttpPostRequestJson(url string, request interface{}, resp interface{}) error { header := make(http.Header) header.Set("Content-Type", "application/json") body, err := getBytes(request) if err != nil { return err } return HttpPost(url, header, bytes.NewReader(body), func(res *http.Response) error { if res.StatusCode != http.StatusOK { return fmt.Errorf("http request (%s) error %s", url, res.Status) } content, err := io.ReadAll(res.Body) if err != nil { return err } return json.Unmarshal(content, resp) }) }