Skip to content

Commit e2620e5

Browse files
authored
Actually retry retryable status codes (#1618)
1 parent 21ac1b2 commit e2620e5

File tree

2 files changed

+26
-3
lines changed

2 files changed

+26
-3
lines changed

pkg/v1/remote/transport/error.go

Lines changed: 25 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,9 @@ type Error struct {
3434
Request *http.Request
3535
// The raw body if we couldn't understand it.
3636
rawBody string
37+
38+
// Bit of a hack to make it easier to force a retry.
39+
temporary bool
3740
}
3841

3942
// Check that Error implements error
@@ -72,6 +75,10 @@ func (e *Error) responseErr() string {
7275

7376
// Temporary returns whether the request that preceded the error is temporary.
7477
func (e *Error) Temporary() bool {
78+
if e.temporary {
79+
return true
80+
}
81+
7582
if len(e.Errors) == 0 {
7683
_, ok := temporaryStatusCodes[e.StatusCode]
7784
return ok
@@ -153,21 +160,37 @@ func CheckError(resp *http.Response, codes ...int) error {
153160
return nil
154161
}
155162
}
163+
156164
b, err := io.ReadAll(resp.Body)
157165
if err != nil {
158166
return err
159167
}
160168

169+
return makeError(resp, b)
170+
}
171+
172+
func makeError(resp *http.Response, body []byte) *Error {
161173
// https://github.com/docker/distribution/blob/master/docs/spec/api.md#errors
162174
structuredError := &Error{}
163175

164176
// This can fail if e.g. the response body is not valid JSON. That's fine,
165177
// we'll construct an appropriate error string from the body and status code.
166-
_ = json.Unmarshal(b, structuredError)
178+
_ = json.Unmarshal(body, structuredError)
167179

168-
structuredError.rawBody = string(b)
180+
structuredError.rawBody = string(body)
169181
structuredError.StatusCode = resp.StatusCode
170182
structuredError.Request = resp.Request
171183

172184
return structuredError
173185
}
186+
187+
func retryError(resp *http.Response) error {
188+
b, err := io.ReadAll(resp.Body)
189+
if err != nil {
190+
return err
191+
}
192+
193+
rerr := makeError(resp, b)
194+
rerr.temporary = true
195+
return rerr
196+
}

pkg/v1/remote/transport/retry.go

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -100,7 +100,7 @@ func (t *retryTransport) RoundTrip(in *http.Request) (out *http.Response, err er
100100
if out != nil {
101101
for _, code := range t.codes {
102102
if out.StatusCode == code {
103-
return CheckError(out)
103+
return retryError(out)
104104
}
105105
}
106106
}

0 commit comments

Comments
 (0)