-
Notifications
You must be signed in to change notification settings - Fork 7
/
retry.go
66 lines (61 loc) · 1.88 KB
/
retry.go
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
package httpretry
import (
"crypto/x509"
"net/http"
"net/url"
"strings"
)
// RetryPolicy decides if a request should be retried.
//
// This is done by examining the response status code and the error message of the last response.
//
// The statusCode may be 0 if there was no response available (e.g. in case of a request error).
type RetryPolicy func(statusCode int, err error) bool
var defaultRetryPolicy RetryPolicy = func(statusCode int, err error) bool {
// check if error is of type temporary
t, ok := err.(interface{ Temporary() bool })
if ok && t.Temporary() {
return true
}
// we cannot know all errors, so we filter errors that should NOT be retried
switch e := err.(type) {
case *url.Error:
switch {
case
e.Op == "parse",
strings.Contains(e.Err.Error(), "stopped after"),
strings.Contains(e.Error(), "unsupported protocol scheme"),
strings.Contains(e.Error(), "no Host in request URL"):
return false
}
// check inner error of url.Error
switch e.Err.(type) {
case // this errors will not likely change when retrying
x509.UnknownAuthorityError,
x509.CertificateInvalidError,
x509.ConstraintViolationError:
return false
}
case error: // generic error, check for strings if nothing found, retry
return true
case nil: // no error, continue
}
// most of the codes should not be retried, so we filter status codes that SHOULD be retried
switch statusCode {
case // status codes that should be retried
http.StatusRequestTimeout,
http.StatusConflict,
http.StatusLocked,
http.StatusTooManyRequests,
http.StatusInternalServerError,
http.StatusBadGateway,
http.StatusServiceUnavailable,
http.StatusGatewayTimeout,
http.StatusInsufficientStorage:
return true
case 0: // means we did not get a response. we need to retry
return true
default: // on all other status codes we should not retry (e.g. 200, 401 etc.)
return false
}
}