diff --git a/stripe.go b/stripe.go index 07df815252..3ad95f52a6 100644 --- a/stripe.go +++ b/stripe.go @@ -576,6 +576,16 @@ func (s *BackendImplementation) shouldRetry(err error, req *http.Request, resp * return true } + // The API may ask us not to retry (e.g. if doing so would be a no-op), or + // advise us to retry (e.g. in cases of lock timeouts). Defer to those + // instructions if given. + if resp.Header.Get("Stripe-Should-Retry") == "false" { + return false + } + if resp.Header.Get("Stripe-Should-Retry") == "true" { + return true + } + // 409 Conflict if resp.StatusCode == http.StatusConflict { return true diff --git a/stripe_test.go b/stripe_test.go index c319f23e96..16382f8a8f 100644 --- a/stripe_test.go +++ b/stripe_test.go @@ -156,6 +156,35 @@ func TestShouldRetry(t *testing.T) { 0, )) + // `Stripe-Should-Retry: false` + assert.False(t, c.shouldRetry( + nil, + &http.Request{}, + &http.Response{ + Header: http.Header(map[string][]string{ + "Stripe-Should-Retry": {"false"}, + }), + // Note we send status 409 here, which would normally be retried + StatusCode: http.StatusConflict, + }, + 0, + )) + + // `Stripe-Should-Retry: true` + assert.True(t, c.shouldRetry( + nil, + &http.Request{}, + &http.Response{ + Header: http.Header(map[string][]string{ + "Stripe-Should-Retry": {"true"}, + }), + // Note we send status 400 here, which would normally not be + // retried + StatusCode: http.StatusBadRequest, + }, + 0, + )) + // 409 Conflict assert.True(t, c.shouldRetry( nil,