github.com/lukasheimann/cloudfoundrycli@v7.1.0+incompatible/api/uaa/wrapper/retry_request.go (about)

     1  package wrapper
     2  
     3  import (
     4  	"bytes"
     5  	"io/ioutil"
     6  	"net/http"
     7  
     8  	"code.cloudfoundry.org/cli/api/uaa"
     9  )
    10  
    11  // RetryRequest is a wrapper that retries failed requests if they contain a 5XX
    12  // status code.
    13  type RetryRequest struct {
    14  	maxRetries int
    15  	connection uaa.Connection
    16  }
    17  
    18  // NewRetryRequest returns a pointer to a RetryRequest wrapper.
    19  func NewRetryRequest(maxRetries int) *RetryRequest {
    20  	return &RetryRequest{
    21  		maxRetries: maxRetries,
    22  	}
    23  }
    24  
    25  // Make retries the request if it comes back with a 5XX status code.
    26  func (retry *RetryRequest) Make(request *http.Request, passedResponse *uaa.Response) error {
    27  	var err error
    28  	var rawRequestBody []byte
    29  
    30  	if request.Body != nil {
    31  		rawRequestBody, err = ioutil.ReadAll(request.Body)
    32  		defer request.Body.Close()
    33  		if err != nil {
    34  			return err
    35  		}
    36  	}
    37  
    38  	for i := 0; i < retry.maxRetries+1; i++ {
    39  		if rawRequestBody != nil {
    40  			request.Body = ioutil.NopCloser(bytes.NewBuffer(rawRequestBody))
    41  		}
    42  		err = retry.connection.Make(request, passedResponse)
    43  		if err == nil {
    44  			return nil
    45  		}
    46  
    47  		if retry.skipRetry(request.Method, passedResponse.HTTPResponse) {
    48  			break
    49  		}
    50  	}
    51  	return err
    52  }
    53  
    54  // Wrap sets the connection in the RetryRequest and returns itself.
    55  func (retry *RetryRequest) Wrap(innerconnection uaa.Connection) uaa.Connection {
    56  	retry.connection = innerconnection
    57  	return retry
    58  }
    59  
    60  // skipRetry will skip retry if the request method is POST or contains a status
    61  // code that is not one of following http status codes: 500, 502, 503, 504.
    62  func (*RetryRequest) skipRetry(httpMethod string, response *http.Response) bool {
    63  	return httpMethod == http.MethodPost ||
    64  		response != nil &&
    65  			response.StatusCode != http.StatusInternalServerError &&
    66  			response.StatusCode != http.StatusBadGateway &&
    67  			response.StatusCode != http.StatusServiceUnavailable &&
    68  			response.StatusCode != http.StatusGatewayTimeout
    69  }