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  }