func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration {
	mult := math.Pow(2, float64(attemptNum)) * float64(min)
	sleep := time.Duration(mult)
	if float64(sleep) != mult || sleep > max {
		sleep = max
	}
	return sleep
}
DefaultBackoff provides a default callback for Client.Backoff which
will perform exponential backoff based on the attempt number and limited
by the provided minimum and maximum durations.
package retryablehttp
import (
	"bytes"
	"context"
	"fmt"
	"io"
	"io/ioutil"
	"log"
	"math"
	"math/rand"
	"net/http"
	"net/url"
	"os"
	"strings"
	"time"
	"github.com/hashicorp/go-cleanhttp"
)
var (
	defaultRetryWaitMin = 1 * time.Second
	defaultRetryWaitMax = 30 * time.Second
	defaultRetryMax     = 4
	defaultClient = NewClient()
	respReadLimit = int64(4096)
)
type ReaderFunc func() (io.Reader, error)
type LenReader interface {
	Len() int
}
type Request struct {
	body ReaderFunc
	*http.Request
}
func (r *Request) WithContext(ctx context.Context) *Request {
	r.Request = r.Request.WithContext(ctx)
	return r
}
func NewRequest(method, url string, rawBody interface{}) (*Request, error) {
	var err error
	var body ReaderFunc
	var contentLength int64
	if rawBody != nil {
		switch rawBody.(type) {
		case ReaderFunc:
			body = rawBody.(ReaderFunc)
			tmp, err := body()
			if err != nil {
				return nil, err
			}
			if lr, ok := tmp.(LenReader); ok {
				contentLength = int64(lr.Len())
			}
			if c, ok := tmp.(io.Closer); ok {
				c.Close()
			}
		case func() (io.Reader, error):
			body = rawBody.(func() (io.Reader, error))
			tmp, err := body()
			if err != nil {
				return nil, err
			}
			if lr, ok := tmp.(LenReader); ok {
				contentLength = int64(lr.Len())
			}
			if c, ok := tmp.(io.Closer); ok {
				c.Close()
			}
		case []byte:
			buf := rawBody.([]byte)
			body = func() (io.Reader, error) {
				return bytes.NewReader(buf), nil
			}
			contentLength = int64(len(buf))
		case *bytes.Buffer:
			buf := rawBody.(*bytes.Buffer)
			body = func() (io.Reader, error) {
				return bytes.NewReader(buf.Bytes()), nil
			}
			contentLength = int64(buf.Len())
		case *bytes.Reader:
			buf, err := ioutil.ReadAll(rawBody.(*bytes.Reader))
			if err != nil {
				return nil, err
			}
			body = func() (io.Reader, error) {
				return bytes.NewReader(buf), nil
			}
			contentLength = int64(len(buf))
		case io.ReadSeeker:
			raw := rawBody.(io.ReadSeeker)
			body = func() (io.Reader, error) {
				raw.Seek(0, 0)
				return ioutil.NopCloser(raw), nil
			}
			if lr, ok := raw.(LenReader); ok {
				contentLength = int64(lr.Len())
			}
		case io.Reader:
			buf, err := ioutil.ReadAll(rawBody.(io.Reader))
			if err != nil {
				return nil, err
			}
			body = func() (io.Reader, error) {
				return bytes.NewReader(buf), nil
			}
			contentLength = int64(len(buf))
		default:
			return nil, fmt.Errorf("cannot handle type %T", rawBody)
		}
	}
	httpReq, err := http.NewRequest(method, url, nil)
	if err != nil {
		return nil, err
	}
	httpReq.ContentLength = contentLength
	return &Request{body, httpReq}, nil
}
type RequestLogHook func(*log.Logger, *http.Request, int)
type ResponseLogHook func(*log.Logger, *http.Response)
type CheckRetry func(ctx context.Context, resp *http.Response, err error) (bool, error)
type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration
type ErrorHandler func(resp *http.Response, err error, numTries int) (*http.Response, error)
type Client struct {
	HTTPClient *http.Client  
	Logger     *log.Logger   
	RetryWaitMin time.Duration  
	RetryWaitMax time.Duration  
	RetryMax     int            
	RequestLogHook RequestLogHook
	ResponseLogHook ResponseLogHook
	CheckRetry CheckRetry
	Backoff Backoff
	ErrorHandler ErrorHandler
}
func NewClient() *Client {
	return &Client{
		HTTPClient:   cleanhttp.DefaultClient(),
		Logger:       log.New(os.Stderr, "", log.LstdFlags),
		RetryWaitMin: defaultRetryWaitMin,
		RetryWaitMax: defaultRetryWaitMax,
		RetryMax:     defaultRetryMax,
		CheckRetry:   DefaultRetryPolicy,
		Backoff:      DefaultBackoff,
	}
}
func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) {
	if ctx.Err() != nil {
		return false, ctx.Err()
	}
	if err != nil {
		return true, err
	}
	if resp.StatusCode == 0 || (resp.StatusCode >= 500 && resp.StatusCode != 501) {
		return true, nil
	}
	return false, nil
}