Skip to content

Commit d1b766a

Browse files
Merge pull request #3382 from knm3000/content_fetch_retry
Handle RequestTimeout and TooManyRequests
2 parents 041d8d7 + 3d3dbc8 commit d1b766a

2 files changed

Lines changed: 27 additions & 4 deletions

File tree

remotes/docker/fetcher_test.go

Lines changed: 21 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -109,6 +109,7 @@ func TestDockerFetcherOpen(t *testing.T) {
109109
wantErr bool
110110
wantServerMessageError bool
111111
wantPlainError bool
112+
retries int
112113
}{
113114
{
114115
name: "should return status and error.message if it exists if the registry request fails",
@@ -128,12 +129,31 @@ func TestDockerFetcherOpen(t *testing.T) {
128129
want: nil,
129130
wantErr: true,
130131
wantPlainError: true,
132+
}, {
133+
name: "should return StatusRequestTimeout after 5 retries",
134+
mockedStatus: http.StatusRequestTimeout,
135+
mockedErr: fmt.Errorf(http.StatusText(http.StatusRequestTimeout)),
136+
want: nil,
137+
wantErr: true,
138+
wantPlainError: true,
139+
retries: 5,
140+
}, {
141+
name: "should return StatusTooManyRequests after 5 retries",
142+
mockedStatus: http.StatusTooManyRequests,
143+
mockedErr: fmt.Errorf(http.StatusText(http.StatusTooManyRequests)),
144+
want: nil,
145+
wantErr: true,
146+
wantPlainError: true,
147+
retries: 5,
131148
},
132149
}
133150
for _, tt := range tests {
134151
t.Run(tt.name, func(t *testing.T) {
135152

136153
s := httptest.NewServer(http.HandlerFunc(func(rw http.ResponseWriter, r *http.Request) {
154+
if tt.retries > 0 {
155+
tt.retries--
156+
}
137157
rw.WriteHeader(tt.mockedStatus)
138158
bytes, _ := json.Marshal(tt.mockedErr)
139159
rw.Write(bytes)
@@ -147,6 +167,7 @@ func TestDockerFetcherOpen(t *testing.T) {
147167
got, err := r.open(context.TODO(), s.URL, "", 0)
148168
assert.Equal(t, tt.wantErr, (err != nil))
149169
assert.Equal(t, tt.want, got)
170+
assert.Equal(t, tt.retries, 0)
150171
if tt.wantErr {
151172
var expectedError error
152173
if tt.wantServerMessageError {

remotes/docker/resolver.go

Lines changed: 6 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -455,7 +455,8 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
455455
return nil, nil
456456
}
457457
last := responses[len(responses)-1]
458-
if last.StatusCode == http.StatusUnauthorized {
458+
switch last.StatusCode {
459+
case http.StatusUnauthorized:
459460
log.G(ctx).WithField("header", last.Header.Get("WWW-Authenticate")).Debug("Unauthorized")
460461
if r.auth != nil {
461462
if err := r.auth.AddResponses(ctx, responses); err == nil {
@@ -464,16 +465,17 @@ func (r *dockerBase) retryRequest(ctx context.Context, req *http.Request, respon
464465
return nil, err
465466
}
466467
}
467-
468468
return nil, nil
469-
} else if last.StatusCode == http.StatusMethodNotAllowed && req.Method == http.MethodHead {
469+
case http.StatusMethodNotAllowed:
470470
// Support registries which have not properly implemented the HEAD method for
471471
// manifests endpoint
472-
if strings.Contains(req.URL.Path, "/manifests/") {
472+
if req.Method == http.MethodHead && strings.Contains(req.URL.Path, "/manifests/") {
473473
// TODO: copy request?
474474
req.Method = http.MethodGet
475475
return copyRequest(req)
476476
}
477+
case http.StatusRequestTimeout, http.StatusTooManyRequests:
478+
return copyRequest(req)
477479
}
478480

479481
// TODO: Handle 50x errors accounting for attempt history

0 commit comments

Comments
 (0)