-
Notifications
You must be signed in to change notification settings - Fork 18.9k
Fix error 500 on distribution endpoint #37534
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
Conversation
11167da to
a0564b9
Compare
Codecov Report
@@ Coverage Diff @@
## master #37534 +/- ##
==========================================
- Coverage 36.56% 36.54% -0.02%
==========================================
Files 610 610
Lines 45395 45411 +16
==========================================
- Hits 16598 16595 -3
- Misses 26505 26523 +18
- Partials 2292 2293 +1 |
daemon/images/image_pull.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Only error returned comes from
Lines 342 to 344 in 8aa694c
| if strings.HasPrefix(val, "-") || strings.HasSuffix(val, "-") { | |
| return "", fmt.Errorf("invalid index name (%s). Cannot begin or end with a hyphen", val) | |
| } |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Maybe this should be specified as invalid param in registry/config.go instead.
Presuming that this is an invalid param from the registry service seems a bit too strong of an assumption.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Good suggestion, I'll make that change 👍
|
ping @dmcgowan @vdemeester @cpuguy83 PTAL |
api/server/httputils/errors.go
Outdated
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Perhaps we should have a utility in github.com/docker/distribution to work with these errors; they're a bit hard to use (imo)
a0564b9 to
2cb2eef
Compare
cpuguy83
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Minor nit.
I guess this is fine to bubble up http codes from distribution.
2cb2eef to
b05c3ee
Compare
|
@cpuguy83 addressed your nit; just recalled that the last commit may have to be discussed; do we want to convert 403 to 404, or leave that part out? (We do use it in other locations) |
|
Discussing in the maintainers meeting, and I'll drop the last commit |
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This assists to address a regression where distribution errors were not properly
handled, resulting in a generic 500 (internal server error) to be returned for
`/distribution/name/json` if you weren't authenticated, whereas it should return
a 40x (401).
This patch attempts to extract the HTTP status-code that was returned by the
distribution code, and falls back to returning a 500 status if unable to match.
Before this change:
curl -v --unix-socket /var/run/docker.sock http://localhost/distribution/name/json
* Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> GET /distribution/name/json HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 500 Internal Server Error
< Api-Version: 1.37
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/dev (linux)
< Date: Tue, 03 Jul 2018 15:52:53 GMT
< Content-Length: 115
<
{"message":"errors:\ndenied: requested access to the resource is denied\nunauthorized: authentication required\n"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
daemon logs:
DEBU[2018-07-03T15:52:51.424950601Z] Calling GET /distribution/name/json
DEBU[2018-07-03T15:52:53.179895572Z] FIXME: Got an API for which error does not match any expected type!!!: errors:
denied: requested access to the resource is denied
unauthorized: authentication required
error_type=errcode.Errors module=api
ERRO[2018-07-03T15:52:53.179942783Z] Handler for GET /distribution/name/json returned error: errors:
denied: requested access to the resource is denied
unauthorized: authentication required
With this patch applied:
curl -v --unix-socket /var/run/docker.sock http://localhost/distribution/name/json
* Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> GET /distribution/name/json HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 403 Forbidden
< Api-Version: 1.38
< Content-Type: application/json
< Docker-Experimental: false
< Ostype: linux
< Server: Docker/dev (linux)
< Date: Fri, 03 Aug 2018 14:58:09 GMT
< Content-Length: 115
<
{"message":"errors:\ndenied: requested access to the resource is denied\nunauthorized: authentication required\n"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
daemon logs:
DEBU[2018-08-03T14:58:08.018726228Z] Calling GET /distribution/name/json
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
b05c3ee to
cdcea6f
Compare
|
Removed the last commit; this should be ready to go now ping @vdemeester @yongtang PTAL |
|
LGTM |
yongtang
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM
vdemeester
left a comment
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGTM 🐯
Fix error 500 on distribution endpoint Signed-off-by: xichengliudui <1693291525@qq.com>
|
hm, I just noticed that the API defines that this endpoint could either return a I'll do some digging as to what's the expectation |
|
Ok, so looks like the registry returns two errors; both an The change in this PR picks the "outer" error (
Trying what happens if an invalid authentication is sent Which hm.. only returns Corresponding daemon logs; Given that the above is using a non-existing image, I also tried using an existing private image, but that produces the same result. |
|
Adding some debugging code; diff --git a/api/server/httputils/errors.go b/api/server/httputils/errors.go
index 2abdce2bcf..48c14a7f3c 100644
--- a/api/server/httputils/errors.go
+++ b/api/server/httputils/errors.go
@@ -142,6 +142,11 @@ func statusCodeFromDistributionError(err error) int {
if len(errs) < 1 {
return http.StatusInternalServerError
}
+ for i := range errs {
+ if debugerr, ok := errs[i].(errcode.ErrorCoder); ok {
+ logrus.Debugf("distribution error %d, message: %s, statusCode: %d", i, debugerr.ErrorCode().Descriptor().Message, debugerr.ErrorCode().Descriptor().HTTPStatusCode)
+ }
+ }
if _, ok := errs[0].(errcode.ErrorCoder); ok {
return statusCodeFromDistributionError(errs[0])
}
@@ -152,5 +157,6 @@ func statusCodeFromDistributionError(err error) int {
return statusCodeFromDistributionError(e.Cause())
}
}
+ logrus.Debugf("distribution returned an unknown error %v", err)
return http.StatusInternalServerError
}
diff --git a/api/server/router/distribution/distribution_routes.go b/api/server/router/distribution/distribution_routes.go
index d285728382..122a7d9ad9 100644
--- a/api/server/router/distribution/distribution_routes.go
+++ b/api/server/router/distribution/distribution_routes.go
@@ -73,7 +73,7 @@ func (s *distributionRouter) getDistributionInfo(ctx context.Context, w http.Res
descriptor, err := distrepo.Tags(ctx).Get(ctx, taggedRef.Tag())
if err != nil {
- return err
+ return errors.Wrap(err, "ERROR COMES FROM HERE")
}
distributionInspect.Descriptor = v1.Descriptor{
MediaType: descriptor.MediaType,
diff --git a/vendor/github.com/docker/distribution/registry/client/repository.go b/vendor/github.com/docker/distribution/registry/client/repository.go
index aa442e6540..b189d5c5af 100644
--- a/vendor/github.com/docker/distribution/registry/client/repository.go
+++ b/vendor/github.com/docker/distribution/registry/client/repository.go
@@ -320,6 +320,12 @@ func (t *tags) Get(ctx context.Context, tag string) (distribution.Descriptor, er
}
resp, err := newRequest("HEAD")
+ if resp != nil {
+ fmt.Printf("Request returned status: %d - %s", resp.StatusCode, resp.Status)
+ }
+ if err != nil {
+ fmt.Printf("Error requesting url: %q - %v\n", u, err)
+ }
if err != nil {
return distribution.Descriptor{}, err
}Produces this in the logs (for request without authentication): In the situation with authentication, we don't seem to reach So Doing the same with a plain package main
import (
"fmt"
"net/http"
)
func main() {
client := &http.Client{}
method := "GET"
u := "https://registry-1.docker.io/v2/library/name/manifests/latest"
req, err := http.NewRequest(method, u, nil)
if err != nil {
fmt.Println(err)
}
resp, err := client.Do(req)
if resp != nil {
fmt.Printf("Request returned status: %d - %s", resp.StatusCode, resp.Status)
}
if err != nil {
fmt.Printf("Error requesting url: %q - %v\n", u, err)
}
_ = resp.Body.Close()
}Does return a response (thus a status-code); |
|
That client is constructed in Lines 136 to 138 in b0e6eed
moby/vendor/github.com/docker/distribution/registry/client/repository.go Lines 135 to 152 in b0e6eed
|

This PR consists of two commits
1. Return "invalid parameter" (4xx) errors for distribution
For errors related to the provided input, return an
errdefs.InvalidParameter(),so that they can be returned as a
4xxerror by the API.2. Handle correct status codes for distribution errors
This assists to address a regression where distribution errors were not properly
handled, resulting in a generic 500 (internal server error) to be returned for
/distribution/name/jsonif you weren't authenticated, whereas it should returna 40x (401).
This patch attempts to extract the HTTP status-code that was returned by the
distribution code, and falls back to returning a 500 status if unable to match.
Before this change:
daemon logs:
With this patch applied:
daemon logs: