@@ -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.
7477func (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+ }
0 commit comments