package helper import ( "bytes" "context" "fmt" "io/ioutil" "net" "net/http" "time" ) func SendRequest(method string, endpoint string, values []byte, authKey string) ([]byte, error) { const ConnectMaxWaitTime = time.Minute const RequestMaxWaitTime = 5 * time.Minute client := http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: ConnectMaxWaitTime, }).DialContext, }, } ctx, cancel := context.WithTimeout(context.Background(), RequestMaxWaitTime) defer cancel() emptyBody := []byte{} req, err := http.NewRequestWithContext(ctx, method, endpoint, bytes.NewBuffer(values)) req.Proto = "HTTP/2.0" if err != nil { Error(err) return emptyBody, err } q := req.URL.Query() req.URL.RawQuery = q.Encode() req.Header.Set("Connection", "close") req.Header.Add("Authorization", authKey) req.Close = true client.CloseIdleConnections() response, err := client.Do(req) if e, ok := err.(net.Error); ok && e.Timeout() { if response != nil { response.Body.Close() } Error(err) return emptyBody, err } else if err != nil { if response != nil { response.Body.Close() } Error(err) return emptyBody, err } if response.StatusCode != http.StatusOK { if response != nil { response.Body.Close() } err := fmt.Errorf("response: code: %d, body: %v", response.StatusCode, response.Body) Error(err) return emptyBody, err } body, err := ioutil.ReadAll(response.Body) if err != nil { Error(err) if response != nil { response.Body.Close() } return emptyBody, nil } // if you call it in loop, don't use defer response.Body.Close() return body, nil } func NewHttpClient() (http.Client, context.Context) { const ConnectMaxWaitTime = 30 * time.Second const RequestMaxWaitTime = 60 * time.Second //proxyUrl, _ := url.Parse("http://79.98.129.183:3128") client := http.Client{ Transport: &http.Transport{ DialContext: (&net.Dialer{ Timeout: ConnectMaxWaitTime, }).DialContext, //Proxy: http.ProxyURL(proxyUrl), }, } ctx, cancel := context.WithTimeout(context.Background(), RequestMaxWaitTime) defer cancel() return client, ctx }