cert_error_go119.go2
5:1redundant-build-tag
cert_error_go119.go:5:1
//go:build !go1.20// +build !go1.207:9package-comments
cert_error_go119.go:7:9
package retryablehttpcert_error_go120.go2
5:1redundant-build-tag
cert_error_go120.go:5:1
//go:build go1.20// +build go1.207:9package-comments
cert_error_go120.go:7:9
package retryablehttpclient.go108
1:1file-length-limit
client.go:1:1
// Copyright IBM Corp. 2015, 2025// SPDX-License-Identifier: MPL-2.01:1format
client.go:1:1
// Copyright IBM Corp. 2015, 2025// SPDX-License-Identifier: MPL-2.0- Fix (safe): run `strider fmt client.go`
49:2no-package-var
client.go:49:2
// Default retry configuration defaultRetryWaitMin = 1 * time.Second defaultRetryWaitMax = 30 * time.Second50:2no-package-var
client.go:50:2
defaultRetryWaitMin = 1 * time.Second defaultRetryWaitMax = 30 * time.Second defaultRetryMax = 451:2no-package-var
client.go:51:2
defaultRetryWaitMax = 30 * time.Second defaultRetryMax = 454:2no-package-var
client.go:54:2
// defaultLogger is the logger provided with defaultClient defaultLogger = log.New(os.Stderr, "", log.LstdFlags)58:2no-package-var
client.go:58:2
// a new client. It is purposely private to avoid modifications. defaultClient = NewClient()62:2no-package-var
client.go:62:2
// limit the size we consume to respReadLimit. respReadLimit = int64(4096)62:18redundant-conversion
client.go:62:18
// limit the size we consume to respReadLimit. respReadLimit = int64(4096)66:2no-package-var
client.go:66:2
// This defaults to time.Now. Changes to this should only be done in tests. timeNow = time.Now71:2no-package-var
client.go:71:2
// specifically so we resort to matching on the error string. redirectsErrorRe = regexp.MustCompile(`stopped after \d+ redirects\z`)76:2no-package-var
client.go:76:2
// specifically so we resort to matching on the error string. schemeErrorRe = regexp.MustCompile(`unsupported protocol scheme`)81:2no-package-var
client.go:81:2
// specifically so we resort to matching on the error string. invalidHeaderErrorRe = regexp.MustCompile(`invalid header`)86:2no-package-var
client.go:86:2
// specifically so we resort to matching on the error string. notTrustedErrorRe = regexp.MustCompile(`certificate is not trusted`))89:1doc-comment-period
client.go:89:1
// ReaderFunc is the type of function that can be given natively to NewRequesttype ReaderFunc func() (io.Reader, error)102:6exported-declaration-comment
client.go:102:6
// by the caller out-of-band. Failure to do so will result in a memory leak.type ResponseHandlerFunc func(*http.Response) error106:6exported-declaration-comment
client.go:106:6
// for automatically sending the right Content-Length header when possible.type LenReader interface { Len() int125:19exported-declaration-comment
client.go:125:19
// with its context changed to ctx. The provided ctx must be non-nil.func (r *Request) WithContext(ctx context.Context) *Request { return &Request{144:19exported-declaration-comment
client.go:144:19
// call, or at the same time this request is being used with Client.Do.func (r *Request) BodyBytes() ([]byte, error) { if r.body == nil {163:19exported-declaration-comment
client.go:163:19
// It is useful if a new body needs to be set without constructing a new Request.func (r *Request) SetBody(rawBody interface{}) error { bodyReader, contentLength, err := getBodyReaderAndContentLength(rawBody)163:35use-any
client.go:163:35
// It is useful if a new body needs to be set without constructing a new Request.func (r *Request) SetBody(rawBody interface{}) error { bodyReader, contentLength, err := getBodyReaderAndContentLength(rawBody)193:19exported-declaration-comment
client.go:193:19
// The signature matches io.WriterTo interface.func (r *Request) WriteTo(w io.Writer) (int64, error) { body, err := r.body()204:6cognitive-complexity
client.go:204:6
func getBodyReaderAndContentLength(rawBody interface{}) (ReaderFunc, int64, error) { var bodyReader ReaderFunc204:6cyclomatic-complexity
client.go:204:6
func getBodyReaderAndContentLength(rawBody interface{}) (ReaderFunc, int64, error) { var bodyReader ReaderFunc204:6function-length
client.go:204:6
func getBodyReaderAndContentLength(rawBody interface{}) (ReaderFunc, int64, error) { var bodyReader ReaderFunc204:44use-any
client.go:204:44
func getBodyReaderAndContentLength(rawBody interface{}) (ReaderFunc, int64, error) { var bodyReader ReaderFunc220:4discarded-error-result
client.go:220:4
if c, ok := tmp.(io.Closer); ok { c.Close() }223:2identical-switch-branches
client.go:223:2
case func() (io.Reader, error): bodyReader = body233:4discarded-error-result
client.go:233:4
if c, ok := tmp.(io.Closer); ok { c.Close() }304:1doc-comment-period
client.go:304:1
// FromRequest wraps an http.Request in a retryablehttp.Requestfunc FromRequest(r *http.Request) (*Request, error) {315:25import-shadowing
client.go:315:25
// NewRequest creates a new wrapped request.func NewRequest(method, url string, rawBody interface{}) (*Request, error) { return NewRequestWithContext(context.Background(), method, url, rawBody)315:45use-any
client.go:315:45
// NewRequest creates a new wrapped request.func NewRequest(method, url string, rawBody interface{}) (*Request, error) { return NewRequestWithContext(context.Background(), method, url, rawBody)323:6exported-declaration-comment
client.go:323:6
// obtaining a connection, sending the request, and reading the response headers and body.func NewRequestWithContext(ctx context.Context, method, url string, rawBody interface{}) (*Request, error) { httpReq, err := http.NewRequestWithContext(ctx, method, url, nil)323:57import-shadowing
client.go:323:57
// obtaining a connection, sending the request, and reading the response headers and body.func NewRequestWithContext(ctx context.Context, method, url string, rawBody interface{}) (*Request, error) { httpReq, err := http.NewRequestWithContext(ctx, method, url, nil)323:77use-any
client.go:323:77
// obtaining a connection, sending the request, and reading the response headers and body.func NewRequestWithContext(ctx context.Context, method, url string, rawBody interface{}) (*Request, error) { httpReq, err := http.NewRequestWithContext(ctx, method, url, nil)341:1top-level-declaration-order
client.go:341:1
// standard log.Logger.type Logger interface { Printf(string, ...interface{})341:6exported-declaration-comment
client.go:341:6
// standard log.Logger.type Logger interface { Printf(string, ...interface{})342:20use-any
client.go:342:20
type Logger interface { Printf(string, ...interface{})}350:6exported-declaration-comment
client.go:350:6
// interface.type LeveledLogger interface { Error(msg string, keysAndValues ...interface{})351:37use-any
client.go:351:37
type LeveledLogger interface { Error(msg string, keysAndValues ...interface{}) Info(msg string, keysAndValues ...interface{})352:36use-any
client.go:352:36
Error(msg string, keysAndValues ...interface{}) Info(msg string, keysAndValues ...interface{}) Debug(msg string, keysAndValues ...interface{})353:37use-any
client.go:353:37
Info(msg string, keysAndValues ...interface{}) Debug(msg string, keysAndValues ...interface{}) Warn(msg string, keysAndValues ...interface{})354:36use-any
client.go:354:36
Debug(msg string, keysAndValues ...interface{}) Warn(msg string, keysAndValues ...interface{})}363:21exported-declaration-comment
client.go:363:21
func (h hookLogger) Printf(s string, args ...interface{}) { h.Info(fmt.Sprintf(s, args...))363:46use-any
client.go:363:46
func (h hookLogger) Printf(s string, args ...interface{}) { h.Info(fmt.Sprintf(s, args...))371:6exported-declaration-comment
client.go:371:6
// consumers.type RequestLogHook func(Logger, *http.Request, int)378:6exported-declaration-comment
client.go:378:6
// from this method, this will affect the response returned from Do().type ResponseLogHook func(Logger, *http.Response)388:6exported-declaration-comment
client.go:388:6
// response body before returning.type CheckRetry func(ctx context.Context, resp *http.Response, err error) (bool, error)393:6exported-declaration-comment
client.go:393:6
// that should pass before trying again.type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration393:19redefines-builtin-id
client.go:393:19
// that should pass before trying again.type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration393:24redefines-builtin-id
client.go:393:24
// that should pass before trying again.type Backoff func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration399:6exported-declaration-comment
client.go:399:6
// 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)401:1doc-comment-period
client.go:401:1
// PrepareRetry is called before retry operation. It can be used for example to re-sign the requesttype PrepareRetry func(req *http.Request) error406:6exported-declaration-comment
client.go:406:6
// like automatic retries to tolerate minor outages.type Client struct { HTTPClient *http.Client // Internal HTTP client.408:13use-any
client.go:408:13
HTTPClient *http.Client // Internal HTTP client. Logger interface{} // Customer logger instance. Can be either Logger or LeveledLogger452:27use-any
client.go:452:27
func (c *Client) logger() interface{} { c.loggerInit.Do(func() {472:6exported-declaration-comment
client.go:472:6
// will retry on connection errors and server errors.func DefaultRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) { // do not retry on context.Canceled or context.DeadlineExceeded479:20discarded-error-result
client.go:479:20
// don't propagate other errors shouldRetry, _ := baseRetryPolicy(resp, err) return shouldRetry, nil486:6exported-declaration-comment
client.go:486:6
// why it decided to retry or not.func ErrorPropagatedRetryPolicy(ctx context.Context, resp *http.Response, err error) (bool, error) { // do not retry on context.Canceled or context.DeadlineExceeded495:6cognitive-complexity
client.go:495:6
func baseRetryPolicy(resp *http.Response, err error) (bool, error) { if err != nil {495:6cyclomatic-complexity
client.go:495:6
func baseRetryPolicy(resp *http.Response, err error) (bool, error) { if err != nil {523:3nil-error-return
client.go:523:3
// The error is likely recoverable so retry. return true, nil }551:6exported-declaration-comment
client.go:551:6
// seconds the server states it may be ready to process more requests from this client.func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {551:21redefines-builtin-id
client.go:551:21
// seconds the server states it may be ready to process more requests from this client.func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {551:21time-naming
client.go:551:21
// seconds the server states it may be ready to process more requests from this client.func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {551:26redefines-builtin-id
client.go:551:26
// seconds the server states it may be ready to process more requests from this client.func DefaultBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {562:5optimize-operands-order
client.go:562:5
sleep := time.Duration(mult) if float64(sleep) != mult || sleep > max { sleep = max579:5optimize-operands-order
client.go:579:5
func parseRetryAfterHeader(headers []string) (time.Duration, bool) { if len(headers) == 0 || headers[0] == "" { return 0, false603:1doc-comment-period
client.go:603:1
// LinearJitterBackoff provides a callback for Client.Backoff which will// perform linear backoff based on the attempt number and with jitter to619:6exported-declaration-comment
client.go:619:6
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // attemptNum always starts at zero but we want to start at 1 for multiplication619:26redefines-builtin-id
client.go:619:26
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // attemptNum always starts at zero but we want to start at 1 for multiplication619:26time-naming
client.go:619:26
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // attemptNum always starts at zero but we want to start at 1 for multiplication619:31redefines-builtin-id
client.go:619:31
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // attemptNum always starts at zero but we want to start at 1 for multiplication619:66unused-parameter
client.go:619:66
// and a max of 20s (15382ms, 292ms, 51321ms, 35234ms, ...)func LinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { // attemptNum always starts at zero but we want to start at 1 for multiplication621:2modifies-parameter
client.go:621:2
// attemptNum always starts at zero but we want to start at 1 for multiplication attemptNum++647:6exported-declaration-comment
client.go:647:6
// LinearJitterBackoff.func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {647:35redefines-builtin-id
client.go:647:35
// LinearJitterBackoff.func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {647:35time-naming
client.go:647:35
// LinearJitterBackoff.func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {647:40redefines-builtin-id
client.go:647:40
// LinearJitterBackoff.func RateLimitLinearJitterBackoff(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { if resp != nil {661:6exported-declaration-comment
client.go:661:6
// closed.func PassthroughErrorHandler(resp *http.Response, err error, _ int) (*http.Response, error) { return resp, err666:18cognitive-complexity
client.go:666:18
// Do wraps calling an HTTP method with retries.func (c *Client) Do(req *Request) (*http.Response, error) { c.clientInit.Do(func() {666:18cyclomatic-complexity
client.go:666:18
// Do wraps calling an HTTP method with retries.func (c *Client) Do(req *Request) (*http.Response, error) { c.clientInit.Do(func() {666:18function-length
client.go:666:18
// Do wraps calling an HTTP method with retries.func (c *Client) Do(req *Request) (*http.Response, error) { c.clientInit.Do(func() {701:5modifies-parameter
client.go:701:5
if c, ok := body.(io.ReadCloser); ok { req.Body = c } else {703:5modifies-parameter
client.go:703:5
} else { req.Body = io.NopCloser(body) }719:17unclosed-http-response-body
client.go:719:17
// Attempt the request resp, doErr = c.HTTPClient.Do(req.Request)719:32external-call-in-loop
client.go:719:32
// Attempt the request resp, doErr = c.HTTPClient.Do(req.Request)723:6optimize-operands-order
client.go:723:6
shouldRetry, checkErr = c.CheckRetry(req.Context(), resp, doErr) if !shouldRetry && doErr == nil && req.responseHandler != nil { respErr = req.responseHandler(resp)768:21possible-nil-dereference
client.go:768:21
if doErr == nil { c.drainBody(resp.Body) }796:3modifies-parameter
client.go:796:3
httpreq := *req.Request req.Request = &httpreq807:5optimize-operands-order
client.go:807:5
// this is the closest we have to success criteria if doErr == nil && respErr == nil && checkErr == nil && prepareErr == nil && !shouldRetry { return resp, nil807:5optimize-operands-order
client.go:807:5
// this is the closest we have to success criteria if doErr == nil && respErr == nil && checkErr == nil && prepareErr == nil && !shouldRetry { return resp, nil807:5optimize-operands-order
client.go:807:5
// this is the closest we have to success criteria if doErr == nil && respErr == nil && checkErr == nil && prepareErr == nil && !shouldRetry { return resp, nil862:10import-shadowing
client.go:862:10
// Get is a shortcut for doing a GET request without making a new client.func Get(url string) (*http.Response, error) { return defaultClient.Get(url)867:22import-shadowing
client.go:867:22
// Get is a convenience helper for doing simple GET requests.func (c *Client) Get(url string) (*http.Response, error) { req, err := NewRequest("GET", url, nil)876:11import-shadowing
client.go:876:11
// Head is a shortcut for doing a HEAD request without making a new client.func Head(url string) (*http.Response, error) { return defaultClient.Head(url)881:23import-shadowing
client.go:881:23
// Head is a convenience method for doing simple HEAD requests.func (c *Client) Head(url string) (*http.Response, error) { req, err := NewRequest("HEAD", url, nil)891:6exported-declaration-comment
client.go:891:6
// The bodyType parameter sets the "Content-Type" header of the request.func Post(url, bodyType string, body interface{}) (*http.Response, error) { return defaultClient.Post(url, bodyType, body)891:11import-shadowing
client.go:891:11
// The bodyType parameter sets the "Content-Type" header of the request.func Post(url, bodyType string, body interface{}) (*http.Response, error) { return defaultClient.Post(url, bodyType, body)891:38use-any
client.go:891:38
// The bodyType parameter sets the "Content-Type" header of the request.func Post(url, bodyType string, body interface{}) (*http.Response, error) { return defaultClient.Post(url, bodyType, body)897:18exported-declaration-comment
client.go:897:18
// The bodyType parameter sets the "Content-Type" header of the request.func (c *Client) Post(url, bodyType string, body interface{}) (*http.Response, error) { req, err := NewRequest("POST", url, body)897:23import-shadowing
client.go:897:23
// The bodyType parameter sets the "Content-Type" header of the request.func (c *Client) Post(url, bodyType string, body interface{}) (*http.Response, error) { req, err := NewRequest("POST", url, body)897:50use-any
client.go:897:50
// The bodyType parameter sets the "Content-Type" header of the request.func (c *Client) Post(url, bodyType string, body interface{}) (*http.Response, error) { req, err := NewRequest("POST", url, body)908:6exported-declaration-comment
client.go:908:6
// a new client.func PostForm(url string, data url.Values) (*http.Response, error) { return defaultClient.PostForm(url, data)908:15import-shadowing
client.go:908:15
// a new client.func PostForm(url string, data url.Values) (*http.Response, error) { return defaultClient.PostForm(url, data)914:18exported-declaration-comment
client.go:914:18
// pre-filled url.Values form data.func (c *Client) PostForm(url string, data url.Values) (*http.Response, error) { return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))914:27import-shadowing
client.go:914:27
// pre-filled url.Values form data.func (c *Client) PostForm(url string, data url.Values) (*http.Response, error) { return c.Post(url, "application/x-www-form-urlencoded", strings.NewReader(data.Encode()))920:18exported-declaration-comment
client.go:920:18
// shims in a *retryablehttp.Client for added retries.func (c *Client) StandardClient() *http.Client { return &http.Client{client_test.go120
1:1file-length-limit
client_test.go:1:1
// Copyright IBM Corp. 2015, 2025// SPDX-License-Identifier: MPL-2.01:1format
client_test.go:1:1
// Copyright IBM Corp. 2015, 2025// SPDX-License-Identifier: MPL-2.0- Fix (safe): run `strider fmt client_test.go`
26:6test-parallelism
client_test.go:26:6
func TestRequest(t *testing.T) { // Fails on invalid request34:29insecure-url-scheme
client_test.go:34:29
// Works with no request body _, err = NewRequest("GET", "http://foo", nil) if err != nil {41:25add-constant
client_test.go:41:25
body := bytes.NewReader([]byte("yo")) req, err := NewRequest("GET", "/", body) if err != nil {48:36optimize-operands-order
client_test.go:48:36
req.Header.Set("X-Test", "foo") if v, ok := req.Header["X-Test"]; !ok || len(v) != 1 || v[0] != "foo" { t.Fatalf("bad headers: %v", req.Header)58:6test-parallelism
client_test.go:58:6
func TestFromRequest(t *testing.T) { // Works with no request body60:34standard-http-method-constant
client_test.go:60:34
// Works with no request body httpReq, err := http.NewRequest("GET", "http://foo", nil) if err != nil {60:41insecure-url-scheme
client_test.go:60:41
// Works with no request body httpReq, err := http.NewRequest("GET", "http://foo", nil) if err != nil {62:12add-constant
client_test.go:62:12
if err != nil { t.Fatalf("err: %v", err) }71:33standard-http-method-constant
client_test.go:71:33
body := bytes.NewReader([]byte("yo")) httpReq, err = http.NewRequest("GET", "/", body) if err != nil {81:21add-constant
client_test.go:81:21
// Preserves headers httpReq.Header.Set("X-Test", "foo") if v, ok := req.Header["X-Test"]; !ok || len(v) != 1 || v[0] != "foo" {81:31add-constant
client_test.go:81:31
// Preserves headers httpReq.Header.Set("X-Test", "foo") if v, ok := req.Header["X-Test"]; !ok || len(v) != 1 || v[0] != "foo" {82:36optimize-operands-order
client_test.go:82:36
httpReq.Header.Set("X-Test", "foo") if v, ok := req.Header["X-Test"]; !ok || len(v) != 1 || v[0] != "foo" { t.Fatalf("bad headers: %v", req.Header)94:1top-level-declaration-order
client_test.go:94:1
// custom type heretype custReader struct { val string108:3modifies-parameter
client_test.go:108:3
for i = 0; i < len(p) && i+c.pos < len(c.val); i++ { p[i] = c.val[i+c.pos] }114:6test-parallelism
client_test.go:114:6
func TestClient_Do(t *testing.T) { testBytes := []byte("hello")136:6cognitive-complexity
client_test.go:136:6
func testClientDo(t *testing.T, body interface{}) { // Create a request136:6cyclomatic-complexity
client_test.go:136:6
func testClientDo(t *testing.T, body interface{}) { // Create a request136:6function-length
client_test.go:136:6
func testClientDo(t *testing.T, body interface{}) { // Create a request136:38use-any
client_test.go:136:38
func testClientDo(t *testing.T, body interface{}) { // Create a request138:32insecure-url-scheme
client_test.go:138:32
// Create a request req, err := NewRequest("PUT", "http://127.0.0.1:28934/v1/foo", body) if err != nil {172:22nested-structs
client_test.go:172:22
var resp *http.Response doneCh := make(chan struct{}) errCh := make(chan error, 1)192:10redundant-conversion
client_test.go:192:10
// errors. code := int64(500) handler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {212:22add-constant
client_test.go:212:22
} expected := []byte("hello") if !bytes.Equal(body, expected) {226:2import-shadowing
client_test.go:226:2
defer list.Close() errors := make(chan error, 1) go func() {267:6cognitive-complexity
client_test.go:267:6
func TestClient_Do_WithResponseHandler(t *testing.T) { // Create the client. Use short retry windows so we fail faster.267:6cyclomatic-complexity
client_test.go:267:6
func TestClient_Do_WithResponseHandler(t *testing.T) { // Create the client. Use short retry windows so we fail faster.267:6function-length
client_test.go:267:6
func TestClient_Do_WithResponseHandler(t *testing.T) { // Create the client. Use short retry windows so we fail faster.267:6test-parallelism
client_test.go:267:6
func TestClient_Do_WithResponseHandler(t *testing.T) { // Create the client. Use short retry windows so we fail faster.290:13nested-structs
client_test.go:290:13
var shouldSucceed bool tests := []struct { name string336:18test-parallelism
client_test.go:336:18
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { checks = 0362:6cognitive-complexity
client_test.go:362:6
func TestClient_Do_WithPrepareRetry(t *testing.T) { // Create the client. Use short retry windows so we fail faster.362:6cyclomatic-complexity
client_test.go:362:6
func TestClient_Do_WithPrepareRetry(t *testing.T) { // Create the client. Use short retry windows so we fail faster.362:6function-length
client_test.go:362:6
func TestClient_Do_WithPrepareRetry(t *testing.T) { // Create the client. Use short retry windows so we fail faster.362:6test-parallelism
client_test.go:362:6
func TestClient_Do_WithPrepareRetry(t *testing.T) { // Create the client. Use short retry windows so we fail faster.392:13nested-structs
client_test.go:392:13
var shouldSucceed bool tests := []struct { name string416:23add-constant
client_test.go:416:23
handler: func(*http.Response) error { return errors.New("retryable failure") },444:18test-parallelism
client_test.go:444:18
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { checks = 0484:6test-parallelism
client_test.go:484:6
func TestClient_Do_fails(t *testing.T) { // Mock server which always responds 500.497:13nested-structs
client_test.go:497:13
tests := []struct { url string498:3import-shadowing
client_test.go:498:3
tests := []struct { url string name string524:18test-parallelism
client_test.go:524:18
for _, tt := range tests { t.Run(tt.name, func(t *testing.T) { // Create the client. Use short retry windows so we fail faster.547:6test-parallelism
client_test.go:547:6
func TestClient_Get(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {564:2discarded-error-result
client_test.go:564:2
} resp.Body.Close()}567:6test-parallelism
client_test.go:567:6
func TestClient_RequestLogHook(t *testing.T) { t.Run("RequestLogHook successfully called with default Logger", func(t *testing.T) {568:66test-parallelism
client_test.go:568:66
func TestClient_RequestLogHook(t *testing.T) { t.Run("RequestLogHook successfully called with default Logger", func(t *testing.T) { testClientRequestLogHook(t, defaultLogger)571:62test-parallelism
client_test.go:571:62
}) t.Run("RequestLogHook successfully called with nil Logger", func(t *testing.T) { testClientRequestLogHook(t, nil)574:68test-parallelism
client_test.go:574:68
}) t.Run("RequestLogHook successfully called with nil typed Logger", func(t *testing.T) { testClientRequestLogHook(t, Logger(nil))577:75test-parallelism
client_test.go:577:75
}) t.Run("RequestLogHook successfully called with nil typed LeveledLogger", func(t *testing.T) { testClientRequestLogHook(t, LeveledLogger(nil))582:52use-any
client_test.go:582:52
func testClientRequestLogHook(t *testing.T, logger interface{}) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {585:13add-constant
client_test.go:585:13
if r.Method != "GET" { t.Fatalf("bad method: %s", r.Method) }587:22add-constant
client_test.go:587:22
} if r.RequestURI != "/foo/bar" { t.Fatalf("bad uri: %s", r.RequestURI)588:13add-constant
client_test.go:588:13
if r.RequestURI != "/foo/bar" { t.Fatalf("bad uri: %s", r.RequestURI) }622:2discarded-error-result
client_test.go:622:2
} resp.Body.Close()629:6test-parallelism
client_test.go:629:6
func TestClient_ResponseLogHook(t *testing.T) { t.Run("ResponseLogHook successfully called with hclog Logger", func(t *testing.T) {630:65test-parallelism
client_test.go:630:65
func TestClient_ResponseLogHook(t *testing.T) { t.Run("ResponseLogHook successfully called with hclog Logger", func(t *testing.T) { buf := new(bytes.Buffer)637:63test-parallelism
client_test.go:637:63
}) t.Run("ResponseLogHook successfully called with nil Logger", func(t *testing.T) { buf := new(bytes.Buffer)641:69test-parallelism
client_test.go:641:69
}) t.Run("ResponseLogHook successfully called with nil typed Logger", func(t *testing.T) { buf := new(bytes.Buffer)645:76test-parallelism
client_test.go:645:76
}) t.Run("ResponseLogHook successfully called with nil typed LeveledLogger", func(t *testing.T) { buf := new(bytes.Buffer)651:6cognitive-complexity
client_test.go:651:6
func testClientResponseLogHook(t *testing.T, l interface{}, buf *bytes.Buffer) { passAfter := time.Now().Add(100 * time.Millisecond)651:6cyclomatic-complexity
client_test.go:651:6
func testClientResponseLogHook(t *testing.T, l interface{}, buf *bytes.Buffer) { passAfter := time.Now().Add(100 * time.Millisecond)651:48use-any
client_test.go:651:48
func testClientResponseLogHook(t *testing.T, l interface{}, buf *bytes.Buffer) { passAfter := time.Now().Add(100 * time.Millisecond)711:33add-constant
client_test.go:711:33
if string(body) != "test_200_body" { t.Fatalf("expect %q, got %q", "test_200_body", string(body)) }724:6test-parallelism
client_test.go:724:6
func TestClient_NewRequestWithContext(t *testing.T) { ctx, cancel := context.WithCancel(context.Background())736:6test-parallelism
client_test.go:736:6
func TestClient_RequestWithContext(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {740:13add-constant
client_test.go:740:13
if _, err := w.Write([]byte("test_200_body")); err != nil { t.Fatalf("failed to write: %v", err) }777:6test-parallelism
client_test.go:777:6
func TestClient_CheckRetry(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {779:17add-constant
client_test.go:779:17
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Error(w, "test_500_body", http.StatusInternalServerError) }))821:6test-parallelism
client_test.go:821:6
func TestParseRetryAfterHeader(t *testing.T) { testStaticTime(t)823:13nested-structs
client_test.go:823:13
testStaticTime(t) tests := []struct { name string840:20test-parallelism
client_test.go:840:20
for _, test := range tests { t.Run(test.name, func(t *testing.T) { sleep, ok := parseRetryAfterHeader(test.headers)852:6test-parallelism
client_test.go:852:6
func TestClient_DefaultBackoff(t *testing.T) { testStaticTime(t)854:13nested-structs
client_test.go:854:13
testStaticTime(t) tests := []struct { name string859:52add-constant
client_test.go:859:52
}{ {"http_429_seconds", http.StatusTooManyRequests, "2"}, {"http_429_date", http.StatusTooManyRequests, "Fri, 31 Dec 1999 23:59:59 GMT"},862:52add-constant
client_test.go:862:52
{"http_503_seconds", http.StatusServiceUnavailable, "2"}, {"http_503_date", http.StatusServiceUnavailable, "Fri, 31 Dec 1999 23:59:59 GMT"}, }865:20test-parallelism
client_test.go:865:20
for _, test := range tests { t.Run(test.name, func(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {878:20discarded-error-result
client_test.go:878:20
client.CheckRetry = func(_ context.Context, resp *http.Response, err error) (bool, error) { retryable, _ = DefaultRetryPolicy(context.Background(), resp, err) retryAfter = DefaultBackoff(client.RetryWaitMin, client.RetryWaitMax, 1, resp)899:6test-parallelism
client_test.go:899:6
func TestClient_DefaultRetryPolicy_TLS(t *testing.T) { ts := httptest.NewTLSServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {921:6test-parallelism
client_test.go:921:6
func TestClient_DefaultRetryPolicy_redirects(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {923:23add-constant
client_test.go:923:23
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { http.Redirect(w, r, "/", http.StatusFound) }))943:6test-parallelism
client_test.go:943:6
func TestClient_DefaultRetryPolicy_invalidscheme(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {956:2import-shadowing
client_test.go:956:2
url := strings.Replace(ts.URL, "http", "ftp", 1) _, err := client.Get(url)962:12add-constant
client_test.go:962:12
if attempts != 1 { t.Fatalf("expected 1 attempt, got %d", attempts) }966:6test-parallelism
client_test.go:966:6
func TestClient_DefaultRetryPolicy_invalidheadername(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {993:6test-parallelism
client_test.go:993:6
func TestClient_DefaultRetryPolicy_invalidheadervalue(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1020:6test-parallelism
client_test.go:1020:6
func TestClient_CheckRetryStop(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {1038:12add-constant
client_test.go:1038:12
if called != 1 { t.Fatalf("CheckRetry called %d times, expected 1", called) }1046:6test-parallelism
client_test.go:1046:6
func TestClient_Head(t *testing.T) { // Mock server which always responds 200.1064:2discarded-error-result
client_test.go:1064:2
} resp.Body.Close()}1067:6test-parallelism
client_test.go:1067:6
func TestClient_Post(t *testing.T) { // Mock server which always responds 200.1102:2discarded-error-result
client_test.go:1102:2
} resp.Body.Close()}1105:6test-parallelism
client_test.go:1105:6
func TestClient_PostForm(t *testing.T) { // Mock server which always responds 200.1108:18add-constant
client_test.go:1108:18
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { if r.Method != "POST" { t.Fatalf("bad method: %s", r.Method)1121:13add-constant
client_test.go:1121:13
if err != nil { t.Fatalf("err: %s", err) }1125:13add-constant
client_test.go:1125:13
if !bytes.Equal(body, expected) { t.Fatalf("bad: %v", body) }1143:2discarded-error-result
client_test.go:1143:2
} resp.Body.Close()}1146:6function-length
client_test.go:1146:6
func TestBackoff_RateLimitLinearJitterBackoff(t *testing.T) { testCases := []struct {1146:6test-parallelism
client_test.go:1146:6
func TestBackoff_RateLimitLinearJitterBackoff(t *testing.T) { testCases := []struct {1147:17nested-structs
client_test.go:1147:17
func TestBackoff_RateLimitLinearJitterBackoff(t *testing.T) { testCases := []struct { name string1149:3redefines-builtin-id
client_test.go:1149:3
name string min time.Duration max time.Duration1150:3redefines-builtin-id
client_test.go:1150:3
min time.Duration max time.Duration headers http.Header1186:5add-constant
client_test.go:1186:5
headers: http.Header{ "Retry-After": []string{"2"}, },1241:18test-parallelism
client_test.go:1241:18
for _, tc := range testCases { t.Run(tc.name, func(t *testing.T) { got := RateLimitLinearJitterBackoff(tc.min, tc.max, 0, &http.Response{1242:59range-value-address
client_test.go:1242:59
t.Run(tc.name, func(t *testing.T) { got := RateLimitLinearJitterBackoff(tc.min, tc.max, 0, &http.Response{ StatusCode: tc.responseCode,1253:6test-parallelism
client_test.go:1253:6
func TestBackoff(t *testing.T) { type tcase struct {1255:3redefines-builtin-id
client_test.go:1255:3
type tcase struct { min time.Duration max time.Duration1256:3redefines-builtin-id
client_test.go:1256:3
min time.Duration max time.Duration i int1306:6test-parallelism
client_test.go:1306:6
func TestClient_BackoffCustom(t *testing.T) { var retries int321310:24redefines-builtin-id
client_test.go:1310:24
client := NewClient() client.Backoff = func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { atomic.AddInt32(&retries, 1)1310:29redefines-builtin-id
client_test.go:1310:29
client := NewClient() client.Backoff = func(min, max time.Duration, attemptNum int, resp *http.Response) time.Duration { atomic.AddInt32(&retries, 1)1329:2discarded-error-result
client_test.go:1329:2
} resp.Body.Close() if retries != int32(client.RetryMax) {1335:6test-parallelism
client_test.go:1335:6
func TestClient_StandardClient(t *testing.T) { // Create a retryable HTTP client.1343:28unchecked-type-assertion
client_test.go:1343:28
// Ensure the underlying retrying client is set properly. if v := standard.Transport.(*RoundTripper).Client; v != client { t.Fatalf("expected %v, got %v", client, v)1348:6cognitive-complexity
client_test.go:1348:6
func TestClient_RedirectWithBody(t *testing.T) { var redirects int321348:6cyclomatic-complexity
client_test.go:1348:6
func TestClient_RedirectWithBody(t *testing.T) { var redirects int321348:6test-parallelism
client_test.go:1348:6
func TestClient_RedirectWithBody(t *testing.T) { var redirects int321352:3single-case-switch
client_test.go:1352:3
ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { switch r.RequestURI { case "/redirect":1381:2discarded-error-result
client_test.go:1381:2
} resp.Body.Close()1396:2discarded-error-result
client_test.go:1396:2
} resp.Body.Close()roundtripper.go2
4:9package-comments
roundtripper.go:4:9
package retryablehttp19:6exported-declaration-comment
roundtripper.go:19:6
// configuration.type RoundTripper struct { // The client to use during requests. If nil, the default retryablehttproundtripper_test.go15
1:1format
roundtripper_test.go:1:1
// Copyright IBM Corp. 2015, 2025// SPDX-License-Identifier: MPL-2.0- Fix (safe): run `strider fmt roundtripper_test.go`
19:6test-parallelism
roundtripper_test.go:19:6
func TestRoundTripper_implements(t *testing.T) { // Compile-time proof of interface satisfaction.19:34unused-parameter
roundtripper_test.go:19:34
func TestRoundTripper_implements(t *testing.T) { // Compile-time proof of interface satisfaction.24:6test-parallelism
roundtripper_test.go:24:6
func TestRoundTripper_init(t *testing.T) { ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {34:12discarded-error-result
roundtripper_test.go:34:12
// RoundTrip once. req, _ := http.NewRequest("GET", ts.URL, nil) if _, err := rt.RoundTrip(req); err != nil {34:28standard-http-method-constant
roundtripper_test.go:34:28
// RoundTrip once. req, _ := http.NewRequest("GET", ts.URL, nil) if _, err := rt.RoundTrip(req); err != nil {48:11discarded-error-result
roundtripper_test.go:48:11
// RoundTrip again. req, _ = http.NewRequest("GET", ts.URL, nil) if _, err := rt.RoundTrip(req); err != nil {48:27standard-http-method-constant
roundtripper_test.go:48:27
// RoundTrip again. req, _ = http.NewRequest("GET", ts.URL, nil) if _, err := rt.RoundTrip(req); err != nil {59:6cognitive-complexity
roundtripper_test.go:59:6
func TestRoundTripper_RoundTrip(t *testing.T) { var reqCount int32 = 059:6test-parallelism
roundtripper_test.go:59:6
func TestRoundTripper_RoundTrip(t *testing.T) { var reqCount int32 = 060:23var-declaration
roundtripper_test.go:60:23
func TestRoundTripper_RoundTrip(t *testing.T) { var reqCount int32 = 096:35add-constant
roundtripper_test.go:96:35
} else if string(v) != "success!" { t.Fatalf("expected %q, got %q", "success!", v) }100:6test-parallelism
roundtripper_test.go:100:6
func TestRoundTripper_TransportFailureErrorHandling(t *testing.T) { // Make a client with some custom settings to verify they are used.115:8insecure-url-scheme
roundtripper_test.go:115:8
Op: "Get", URL: "http://999.999.999.999:999/", Err: &net.OpError{129:23insecure-url-scheme
roundtripper_test.go:129:23
client := retryClient.StandardClient() _, err := client.Get("http://999.999.999.999:999/")