MCPcopy Create free account
hub / github.com/containers/image / registryHTTPResponseToError

Function registryHTTPResponseToError

docker/errors.go:57–102  ·  view source on GitHub ↗

registryHTTPResponseToError creates a Go error from an HTTP error response of a docker/distribution registry. WARNING: The OCI distribution spec says “A `4XX` response code from the registry MAY return a body in any format.”; but if it is JSON, it MUST use the errcode.Error structure. So, callers s

(res *http.Response)

Source from the content-addressed store, hash-verified

55// JSON, it MUST use the errcode.Error structure.
56// So, callers should primarily decide based on HTTP StatusCode, not based on error type here.
57func registryHTTPResponseToError(res *http.Response) error {
58 err := handleErrorResponse(res)
59 // len(errs) == 0 should never be returned by handleErrorResponse; if it does, we don't modify it and let the caller report it as is.
60 if errs, ok := err.(errcode.Errors); ok && len(errs) > 0 {
61 // The docker/distribution registry implementation almost never returns
62 // more than one error in the HTTP body; it seems there is only one
63 // possible instance, where the second error reports a cleanup failure
64 // we don't really care about.
65 //
66 // The only _common_ case where a multi-element error is returned is
67 // created by the handleErrorResponse parser when OAuth authorization fails:
68 // the first element contains errors from a WWW-Authenticate header, the second
69 // element contains errors from the response body.
70 //
71 // In that case the first one is currently _slightly_ more informative (ErrorCodeUnauthorized
72 // for invalid tokens, ErrorCodeDenied for permission denied with a valid token
73 // for the first error, vs. ErrorCodeUnauthorized for both cases for the second error.)
74 //
75 // Also, docker/docker similarly only logs the other errors and returns the
76 // first one.
77 if len(errs) > 1 {
78 logrus.Debugf("Discarding non-primary errors:")
79 for _, err := range errs[1:] {
80 logrus.Debugf(" %s", err.Error())
81 }
82 }
83 err = errs[0]
84 }
85 switch e := err.(type) {
86 case *unexpectedHTTPResponseError:
87 response := string(e.Response)
88 if len(response) > 50 {
89 response = response[:50] + "..."
90 }
91 // %.0w makes e visible to error.Unwrap() without including any text
92 err = fmt.Errorf("StatusCode: %d, %q%.0w", e.StatusCode, response, e)
93 case errcode.Error:
94 // e.Error() is fmt.Sprintf("%s: %s", e.Code.Error(), e.Message, which is usually
95 // rather redundant. So reword it without using e.Code.Error() if e.Message is the default.
96 if e.Message == e.Code.Message() {
97 // %.0w makes e visible to error.Unwrap() without including any text
98 err = fmt.Errorf("%s%.0w", e.Message, e)
99 }
100 }
101 return err
102}

Callers 15

CheckAuthFunction · 0.85
SearchRegistryFunction · 0.85
fetchManifestMethod · 0.85
getBlobMethod · 0.85
PutBlobWithOptionsMethod · 0.85
blobExistsMethod · 0.85
mountBlobMethod · 0.85

Calls 2

handleErrorResponseFunction · 0.85
ErrorMethod · 0.45

Tested by 3

Used in the wild real call sites across dependent graphs

searching dependent graphs…