package http import ( "net/http" "time" ) type HTTPClient struct { Client *http.Client MaxRetries int Backoff func(attempt int) time.Duration CheckRespStatus func(resp *http.Response, err error) bool BearerToken string } func (r *HTTPClient) Do(req *http.Request) (*http.Response, error) { if r.BearerToken != "" { req.Header.Set("Authorization", "Bearer "+r.BearerToken) } var resp *http.Response var err error for attempt := 0; attempt < r.MaxRetries; attempt++ { resp, err = r.Client.Do(req) if !r.CheckRespStatus(resp, err) { return resp, err } time.Sleep(r.Backoff(attempt)) } return resp, err } func NewHTTPClient(token string, maxRetries int, timeout time.Duration) *HTTPClient { return &HTTPClient{ BearerToken: token, Client: &http.Client{Timeout: timeout}, MaxRetries: maxRetries, Backoff: func(attempt int) time.Duration { return time.Duration(attempt) * time.Second }, CheckRespStatus: func(resp *http.Response, err error) bool { if err != nil { return true } if resp.StatusCode < 200 || resp.StatusCode >= 300 { return true } // no need to retry because the status code is 2XX return false }, } }