-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
ociclient.makeError obscures StatusCode in a basic stringified error unless registry response is specifically-crafted JSON #26
Comments
Yup. I've definitely been thinking that the errors support needs to be improved. Thanks for creating the issue! Some random thoughts:
|
Just to correct myself here -- this is related to opencontainers/distribution-spec#178 + opencontainers/distribution-spec#280 (ala opencontainers/distribution-spec#443). If we go back in time a bit to before the spec got "cleaned up", we get: (Which clearly describes the structured errors that All that got removed before 1.0 of the distribution-spec, for reasons that apparently weren't made clear in writing anywhere (as seen in issue 443 there). |
Should the spec add those structured errors back, or should we remove support for them if the spec dropped them on purpose? |
IMO the spec should add them back, even if only as informational/SHOULD/MAY since they are in common use and documenting common use for interoperability is the literal point of the spec existing in the first place, but I'm not a maintainer of the distribution spec (only image and runtime). 🙈 However, @jonjohnsonjr there is a maintainer of the distribution spec, and I don't think I'm putting words in his mouth if I say he does think the spec would have value in having things like those structured errors back (opencontainers/distribution-spec#496 being some pretty compelling evidence towards that -- presumably closed because he was just restoring previously in-the-spec content and didn't think it should have too many cycles spent nit-picking, but that's definitely me projecting / trying to read between the lines). ❤️ |
TODO more explanation Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
TODO more explanation Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
TODO more explanation Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error code for a error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error status for an error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
Currently the standard wire representation of an error is duplicated across both client and server, and there is no way for: - a client to access the actual HTTP status of a response - an `Interface` implementation to cause the `ociserver` to return a specific HTTP error status for an error code that it doesn't know about. This change addresses that by moving the wire representation into the top level `ociregistry` package, splitting `HTTPError` into its own type, and making both `ociclient` and `ociserver` aware of them. One deliberate decision made here guards against some scenarios when nesting an `ociclient` implementation inside `ociserver`. There is a risk that, due to the fact we're using the same `HTTPError` in `httpclient` and `httpserve, if `ociclient` talks to a misbehaving server that returns inappropriate HTTP response codes, those codes could propagate back through `ociserver`, causing that to return inappropriate codes too. So in `ociserver` we only use the `HTTPError` code if there is no known HTTP status for the error code. This seems like a reasonable half-way-house compromise. We also change the `ociregistry.Error` interface so that `Detail` returns `json.RawMessage` instead of `any`. This means that the error detail is consistent no matter if the error has come from `ociclient` or from a Go-implemented `ociregistry.Interface` implementation, and means we can use `ociregistry.WireError` as the base error implementation used by all the exported specific error values. This in turn means that the error message changes because `WireError` includes the error code (lower-cased) in the message, but that consistency seems like a good thing. Fixes #26. Signed-off-by: Roger Peppe <[email protected]> Change-Id: I5a79c1c6fec9f22c1f565830d73486b406dd181d
I don't know if it's intentional (it seems like it's not, given how the function is structured), but
ociclient.makeError
does a lot ofreturn fmt.Errorf(...)
for many cases that seem like they should be returning a wrappedwireError
,wireErrors
, orociregistry.Error
instead so consumers can still access the original status code.oci/ociregistry/ociclient/error.go
Lines 127 to 172 in 1f693b7
I don't think there's anything in the distribution spec that mandates the structure of non-200 status codes from a registry, but I might be very wrong there! (from what I can see, this matches the implementation over in the server half of this library, but I'm using
ociclient
against non-cue-labs registries 😇)The specific case I'm running into is a request from a registry that's returning a 404, but it becomes a basic
fmt.Errorf("404 Not Found: ...")
(with the added bug that I think my registry must be returning a "JSON-y"Content-Type:
value because theociclient.makeError
code is trying toUnmarshal
it 😅), so I can't identify/adjust my client behavior based on the 404 without doing a string match, which isn't ideal (and seems counter to the design ofociregistry.ErrNameUnknown
and friends, and even thewireError
/wireErrors
wrappers that allow direct access to the HTTP status code).At first, I thought the
Errors
slice onwrapErrors
was generic enough that I would've proposed moving up thevar errs wireErrors
(and population ofhttpStatusCode
on it) to the top of the function, and then everyreturn fmt.Errorf(...)
instead be something likeerrs.Errors = append(errs.Errors, fmt.Errorf(...)); return &errs
or something (perhaps even theHEAD
error translation code for the!isJSONMediaType(resp.Header.Get("Content-Type"))
case, maybe with a second error added to theErrors
slice if you wanted to still include the errant body), but I see it's not a generic errors wrapper (which is fair, since it then wouldn'tUnmarshal
correctly), so I'm not sure what to propose here except that it'd be really nice if there were some way to accessStatusCode
on errors from the registry inociclient
.The text was updated successfully, but these errors were encountered: