github.com/Financial-Times/publish-availability-monitor@v1.12.0/httpcaller/httpCaller.go (about) 1 package httpcaller 2 3 import ( 4 "fmt" 5 "io" 6 "net/http" 7 "time" 8 9 "github.com/giantswarm/retry-go" 10 ) 11 12 // Caller abstracts http calls 13 type Caller interface { 14 DoCall(config Config) (*http.Response, error) 15 } 16 17 // Default implementation of Caller 18 type DefaultCaller struct { 19 client *http.Client 20 } 21 22 type Config struct { 23 HTTPMethod string 24 URL string 25 Username string 26 Password string 27 APIKey string 28 TID string 29 ContentType string 30 Entity io.Reader 31 } 32 33 func NewCaller(timeoutSeconds int) DefaultCaller { 34 var client http.Client 35 if timeoutSeconds > 0 { 36 client = http.Client{ 37 Timeout: time.Duration(timeoutSeconds) * time.Second, 38 CheckRedirect: func(req *http.Request, via []*http.Request) error { 39 return http.ErrUseLastResponse 40 }, 41 } 42 } else { 43 client = http.Client{ 44 CheckRedirect: func(req *http.Request, via []*http.Request) error { 45 return http.ErrUseLastResponse 46 }, 47 } 48 } 49 50 return DefaultCaller{&client} 51 } 52 53 // Performs http GET calls using the default http client 54 func (c DefaultCaller) DoCall(config Config) (resp *http.Response, err error) { 55 if config.HTTPMethod == "" { 56 config.HTTPMethod = "GET" 57 } 58 req, err := http.NewRequest(config.HTTPMethod, config.URL, config.Entity) 59 if config.Username != "" && config.Password != "" { 60 req.SetBasicAuth(config.Username, config.Password) 61 } 62 63 if config.APIKey != "" { 64 req.Header.Add("X-Api-Key", config.APIKey) 65 } 66 67 if config.TID != "" { 68 req.Header.Add("X-Request-Id", config.TID) 69 } 70 71 if config.ContentType != "" { 72 req.Header.Add("Content-Type", config.ContentType) 73 } 74 75 req.Header.Add("User-Agent", "UPP Publish Availability Monitor") 76 77 op := func() error { 78 resp, err = c.client.Do(req) //nolint:bodyclose 79 if err != nil { 80 return err 81 } 82 83 if resp.StatusCode >= 500 && resp.StatusCode < 600 { 84 //Error status code: create an err in order to trigger a retry 85 return fmt.Errorf("error status code received: %d", resp.StatusCode) 86 } 87 return nil 88 } 89 90 _ = retry.Do(op, retry.RetryChecker(func(err error) bool { return err != nil }), retry.MaxTries(2)) 91 return resp, err 92 }