Update go-retryablehttp vendor
This commit is contained in:
parent
ec4b839741
commit
7f886b5675
|
@ -16,9 +16,9 @@ import (
|
|||
|
||||
"github.com/hashicorp/errwrap"
|
||||
"github.com/hashicorp/go-cleanhttp"
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
"github.com/hashicorp/go-rootcerts"
|
||||
"github.com/hashicorp/vault/helper/parseutil"
|
||||
"github.com/sethgrid/pester"
|
||||
"golang.org/x/net/http2"
|
||||
)
|
||||
|
||||
|
@ -69,6 +69,9 @@ type Config struct {
|
|||
// If there is an error when creating the configuration, this will be the
|
||||
// error
|
||||
Error error
|
||||
|
||||
// The Backoff function to use; a default is used if not provided
|
||||
Backoff retryablehttp.Backoff
|
||||
}
|
||||
|
||||
// TLSConfig contains the parameters needed to configure TLS on the HTTP client
|
||||
|
@ -131,12 +134,14 @@ func DefaultConfig() *Config {
|
|||
// but in e.g. http_test actual redirect handling is necessary
|
||||
config.HttpClient.CheckRedirect = func(req *http.Request, via []*http.Request) error {
|
||||
// Returning this value causes the Go net library to not close the
|
||||
// response body and to nil out the error. Otherwise pester tries
|
||||
// three times on every redirect because it sees an error from this
|
||||
// response body and to nil out the error. Otherwise retry clients may
|
||||
// try three times on every redirect because it sees an error from this
|
||||
// function (to prevent redirects) passing through to it.
|
||||
return http.ErrUseLastResponse
|
||||
}
|
||||
|
||||
config.Backoff = retryablehttp.LinearJitterBackoff
|
||||
|
||||
return config
|
||||
}
|
||||
|
||||
|
@ -434,6 +439,16 @@ func (c *Client) SetHeaders(headers http.Header) {
|
|||
c.headers = headers
|
||||
}
|
||||
|
||||
// SetBackoff sets the backoff function to be used for future requests.
|
||||
func (c *Client) SetBackoff(backoff retryablehttp.Backoff) {
|
||||
c.modifyLock.RLock()
|
||||
c.config.modifyLock.Lock()
|
||||
defer c.config.modifyLock.Unlock()
|
||||
c.modifyLock.RUnlock()
|
||||
|
||||
c.config.Backoff = backoff
|
||||
}
|
||||
|
||||
// Clone creates a new client with the same configuration. Note that the same
|
||||
// underlying http.Client is used; modifying the client from more than one
|
||||
// goroutine at once may not be safe, so modify the client as needed and then
|
||||
|
@ -449,6 +464,7 @@ func (c *Client) Clone() (*Client, error) {
|
|||
HttpClient: config.HttpClient,
|
||||
MaxRetries: config.MaxRetries,
|
||||
Timeout: config.Timeout,
|
||||
Backoff: config.Backoff,
|
||||
}
|
||||
config.modifyLock.RUnlock()
|
||||
|
||||
|
@ -544,14 +560,35 @@ func (c *Client) RawRequest(r *Request) (*Response, error) {
|
|||
|
||||
redirectCount := 0
|
||||
START:
|
||||
req, err := r.ToHTTP()
|
||||
req, err := r.toRetryableHTTP(false)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if req == nil {
|
||||
return nil, fmt.Errorf("nil request created")
|
||||
}
|
||||
|
||||
client := pester.NewExtendedClient(c.config.HttpClient)
|
||||
client.Backoff = pester.LinearJitterBackoff
|
||||
client.MaxRetries = c.config.MaxRetries
|
||||
backoff := c.config.Backoff
|
||||
if backoff == nil {
|
||||
backoff = retryablehttp.LinearJitterBackoff
|
||||
}
|
||||
|
||||
maxRetries := c.config.MaxRetries
|
||||
if maxRetries == 0 {
|
||||
maxRetries = 2
|
||||
}
|
||||
|
||||
client := &retryablehttp.Client{
|
||||
HTTPClient: c.config.HttpClient,
|
||||
RetryWaitMin: 1 * time.Second,
|
||||
RetryWaitMax: 5 * time.Second,
|
||||
RetryMax: maxRetries,
|
||||
CheckRetry: retryablehttp.DefaultRetryPolicy,
|
||||
Backoff: backoff,
|
||||
ErrorHandler: func(resp *http.Response, err error, numTries int) (*http.Response, error) {
|
||||
return resp, err
|
||||
},
|
||||
}
|
||||
|
||||
var result *Response
|
||||
resp, err := client.Do(req)
|
||||
|
|
|
@ -4,8 +4,11 @@ import (
|
|||
"bytes"
|
||||
"encoding/json"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"net/http"
|
||||
"net/url"
|
||||
|
||||
retryablehttp "github.com/hashicorp/go-retryablehttp"
|
||||
)
|
||||
|
||||
// Request is a raw request configuration structure used to initiate
|
||||
|
@ -53,13 +56,41 @@ func (r *Request) ResetJSONBody() error {
|
|||
// ToHTTP turns this request into a valid *http.Request for use with the
|
||||
// net/http package.
|
||||
func (r *Request) ToHTTP() (*http.Request, error) {
|
||||
req, err := r.toRetryableHTTP(true)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return req.Request, nil
|
||||
}
|
||||
|
||||
func (r *Request) toRetryableHTTP(regular bool) (*retryablehttp.Request, error) {
|
||||
// Encode the query parameters
|
||||
r.URL.RawQuery = r.Params.Encode()
|
||||
|
||||
// Create the HTTP request
|
||||
req, err := http.NewRequest(r.Method, r.URL.RequestURI(), r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
// Create the HTTP request, defaulting to retryable
|
||||
var req *retryablehttp.Request
|
||||
|
||||
if regular {
|
||||
regReq, err := http.NewRequest(r.Method, r.URL.RequestURI(), r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
req = &retryablehttp.Request{
|
||||
Request: regReq,
|
||||
}
|
||||
} else {
|
||||
var buf []byte
|
||||
var err error
|
||||
if r.Body != nil {
|
||||
buf, err = ioutil.ReadAll(r.Body)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
req, err = retryablehttp.NewRequest(r.Method, r.URL.RequestURI(), bytes.NewReader(buf))
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
}
|
||||
|
||||
req.URL.User = r.URL.User
|
||||
|
|
|
@ -572,7 +572,7 @@ ssl_storage_port: 7001
|
|||
#
|
||||
# Setting listen_address to 0.0.0.0 is always wrong.
|
||||
#
|
||||
listen_address: 172.17.0.5
|
||||
listen_address: 172.17.0.4
|
||||
|
||||
# Set listen_address OR listen_interface, not both. Interfaces must correspond
|
||||
# to a single address, IP aliasing is not supported.
|
||||
|
|
74
vendor/github.com/hashicorp/go-retryablehttp/client.go
generated
vendored
74
vendor/github.com/hashicorp/go-retryablehttp/client.go
generated
vendored
|
@ -20,6 +20,7 @@ import (
|
|||
"io/ioutil"
|
||||
"log"
|
||||
"math"
|
||||
"math/rand"
|
||||
"net/http"
|
||||
"net/url"
|
||||
"os"
|
||||
|
@ -112,6 +113,12 @@ type CheckRetry func(resp *http.Response, err error) (bool, error)
|
|||
// that should pass before trying again.
|
||||
type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration
|
||||
|
||||
// ErrorHandler is called if retries are expired, containing the last status
|
||||
// from the http library. The default will close the body and return an error
|
||||
// indicating how many tries were attempted. If overriding this, be sure to
|
||||
// close the body if needed.
|
||||
type ErrorHandler func(resp *http.Response, err error, numTries int) (*http.Response, error)
|
||||
|
||||
// Client is used to make HTTP requests. It adds additional functionality
|
||||
// like automatic retries to tolerate minor outages.
|
||||
type Client struct {
|
||||
|
@ -136,6 +143,9 @@ type Client struct {
|
|||
|
||||
// Backoff specifies the policy for how long to wait between retries
|
||||
Backoff Backoff
|
||||
|
||||
// ErrorHandler specifies the custom error handler to use, if any
|
||||
ErrorHandler ErrorHandler
|
||||
}
|
||||
|
||||
// NewClient creates a new Client with default settings.
|
||||
|
@ -180,9 +190,31 @@ func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response)
|
|||
return sleep
|
||||
}
|
||||
|
||||
// LinearJitterBackoff provides a callback for Client.Backoff which will
|
||||
// perform linear backoff based on the attempt number and limited by the
|
||||
// provided minimum and maximum, which are applied *prior to linear
|
||||
// adjustment*. Jitter will be applied to prevent a thundering herd.
|
||||
func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
|
||||
if max <= min {
|
||||
// Unclear what to do here, so return min
|
||||
return min
|
||||
}
|
||||
// Seed rand; doing this every time is fine
|
||||
rand := rand.New(rand.NewSource(int64(time.Now().Nanosecond())))
|
||||
// Pick a random number that lies somewhere between the min and max and
|
||||
// multiply by the attemptNum. attemptNum starts at zero so we always
|
||||
// increment here.
|
||||
return time.Duration((int64(rand.Int63()) % int64(max-min)) * int64((attemptNum + 1)))
|
||||
}
|
||||
|
||||
// Do wraps calling an HTTP method with retries.
|
||||
func (c *Client) Do(req *Request) (*http.Response, error) {
|
||||
c.Logger.Printf("[DEBUG] %s %s", req.Method, req.URL)
|
||||
if c.Logger != nil {
|
||||
c.Logger.Printf("[DEBUG] %s %s", req.Method, req.URL)
|
||||
}
|
||||
|
||||
var resp *http.Response
|
||||
var err error
|
||||
|
||||
for i := 0; ; i++ {
|
||||
var code int // HTTP response code
|
||||
|
@ -199,13 +231,18 @@ func (c *Client) Do(req *Request) (*http.Response, error) {
|
|||
}
|
||||
|
||||
// Attempt the request
|
||||
resp, err := c.HTTPClient.Do(req.Request)
|
||||
resp, err = c.HTTPClient.Do(req.Request)
|
||||
if resp != nil {
|
||||
code = resp.StatusCode
|
||||
}
|
||||
|
||||
// Check if we should continue with retries.
|
||||
checkOK, checkErr := c.CheckRetry(resp, err)
|
||||
|
||||
if err != nil {
|
||||
c.Logger.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, err)
|
||||
if c.Logger != nil {
|
||||
c.Logger.Printf("[ERR] %s %s request failed: %v", req.Method, req.URL, err)
|
||||
}
|
||||
} else {
|
||||
// Call this here to maintain the behavior of logging all requests,
|
||||
// even if CheckRetry signals to stop.
|
||||
|
@ -223,25 +260,38 @@ func (c *Client) Do(req *Request) (*http.Response, error) {
|
|||
return resp, err
|
||||
}
|
||||
|
||||
// We're going to retry, consume any response to reuse the connection.
|
||||
if err == nil {
|
||||
c.drainBody(resp.Body)
|
||||
}
|
||||
|
||||
// We do this before drainBody beause there's no need for the I/O if
|
||||
// we're breaking out
|
||||
remain := c.RetryMax - i
|
||||
if remain == 0 {
|
||||
break
|
||||
}
|
||||
|
||||
// We're going to retry, consume any response to reuse the connection.
|
||||
if err == nil && resp != nil {
|
||||
c.drainBody(resp.Body)
|
||||
}
|
||||
|
||||
wait := c.Backoff(c.RetryWaitMin, c.RetryWaitMax, i, resp)
|
||||
desc := fmt.Sprintf("%s %s", req.Method, req.URL)
|
||||
if code > 0 {
|
||||
desc = fmt.Sprintf("%s (status: %d)", desc, code)
|
||||
}
|
||||
c.Logger.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain)
|
||||
if c.Logger != nil {
|
||||
c.Logger.Printf("[DEBUG] %s: retrying in %s (%d left)", desc, wait, remain)
|
||||
}
|
||||
time.Sleep(wait)
|
||||
}
|
||||
|
||||
// Return an error if we fall out of the retry loop
|
||||
if c.ErrorHandler != nil {
|
||||
return c.ErrorHandler(resp, err, c.RetryMax+1)
|
||||
}
|
||||
|
||||
// By default, we close the response body and return an error without
|
||||
// returning the response
|
||||
if resp != nil {
|
||||
resp.Body.Close()
|
||||
}
|
||||
return nil, fmt.Errorf("%s %s giving up after %d attempts",
|
||||
req.Method, req.URL, c.RetryMax+1)
|
||||
}
|
||||
|
@ -251,7 +301,9 @@ func (c *Client) drainBody(body io.ReadCloser) {
|
|||
defer body.Close()
|
||||
_, err := io.Copy(ioutil.Discard, io.LimitReader(body, respReadLimit))
|
||||
if err != nil {
|
||||
c.Logger.Printf("[ERR] error reading response body: %v", err)
|
||||
if c.Logger != nil {
|
||||
c.Logger.Printf("[ERR] error reading response body: %v", err)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
6
vendor/vendor.json
vendored
6
vendor/vendor.json
vendored
|
@ -1141,10 +1141,10 @@
|
|||
"revisionTime": "2018-03-31T00:25:53Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "yzoWV7yrS/TvOrKy5ZrdUjsYaOA=",
|
||||
"checksumSHA1": "dWD+1wzyeQJnmdfFORXX7vU3xs4=",
|
||||
"path": "github.com/hashicorp/go-retryablehttp",
|
||||
"revision": "794af36148bf63c118d6db80eb902a136b907e71",
|
||||
"revisionTime": "2017-08-24T18:08:59Z"
|
||||
"revision": "ba24e6e2765455196ea08f97ca8b2a5587d704ec",
|
||||
"revisionTime": "2018-05-09T21:39:37Z"
|
||||
},
|
||||
{
|
||||
"checksumSHA1": "A1PcINvF3UiwHRKn8UcgARgvGRs=",
|
||||
|
|
Loading…
Reference in a new issue