Signed-off-by: David Calavera <david.calavera@gmail.com>
| ... | ... |
@@ -7,9 +7,11 @@ import ( |
| 7 | 7 |
"fmt" |
| 8 | 8 |
"io" |
| 9 | 9 |
"net/http" |
| 10 |
+ "net/url" |
|
| 10 | 11 |
"strings" |
| 11 | 12 |
|
| 12 | 13 |
"github.com/docker/distribution/digest" |
| 14 |
+ "github.com/docker/distribution/registry/api/errcode" |
|
| 13 | 15 |
"github.com/docker/docker/api/server/httputils" |
| 14 | 16 |
"github.com/docker/docker/builder/dockerfile" |
| 15 | 17 |
derr "github.com/docker/docker/errors" |
| ... | ... |
@@ -137,6 +139,12 @@ func (s *router) postImagesCreate(ctx context.Context, w http.ResponseWriter, r |
| 137 | 137 |
err = s.daemon.PullImage(ref, metaHeaders, authConfig, output) |
| 138 | 138 |
} |
| 139 | 139 |
} |
| 140 |
+ // Check the error from pulling an image to make sure the request |
|
| 141 |
+ // was authorized. Modify the status if the request was |
|
| 142 |
+ // unauthorized to respond with 401 rather than 500. |
|
| 143 |
+ if err != nil && isAuthorizedError(err) {
|
|
| 144 |
+ err = errcode.ErrorCodeUnauthorized.WithMessage(fmt.Sprintf("Authentication is required: %s", err))
|
|
| 145 |
+ } |
|
| 140 | 146 |
} else { //import
|
| 141 | 147 |
var newRef reference.Named |
| 142 | 148 |
if repo != "" {
|
| ... | ... |
@@ -373,3 +381,16 @@ func (s *router) getImagesSearch(ctx context.Context, w http.ResponseWriter, r * |
| 373 | 373 |
} |
| 374 | 374 |
return httputils.WriteJSON(w, http.StatusOK, query.Results) |
| 375 | 375 |
} |
| 376 |
+ |
|
| 377 |
+func isAuthorizedError(err error) bool {
|
|
| 378 |
+ if urlError, ok := err.(*url.Error); ok {
|
|
| 379 |
+ err = urlError.Err |
|
| 380 |
+ } |
|
| 381 |
+ |
|
| 382 |
+ if dError, ok := err.(errcode.Error); ok {
|
|
| 383 |
+ if dError.ErrorCode() == errcode.ErrorCodeUnauthorized {
|
|
| 384 |
+ return true |
|
| 385 |
+ } |
|
| 386 |
+ } |
|
| 387 |
+ return false |
|
| 388 |
+} |
| ... | ... |
@@ -28,7 +28,6 @@ var ( |
| 28 | 28 |
// ErrAlreadyExists is an error returned if an image being pushed |
| 29 | 29 |
// already exists on the remote side |
| 30 | 30 |
ErrAlreadyExists = errors.New("Image already exists")
|
| 31 |
- errLoginRequired = errors.New("Authentication is required.")
|
|
| 32 | 31 |
) |
| 33 | 32 |
|
| 34 | 33 |
func init() {
|
| ... | ... |
@@ -19,6 +19,7 @@ import ( |
| 19 | 19 |
"strings" |
| 20 | 20 |
|
| 21 | 21 |
"github.com/Sirupsen/logrus" |
| 22 |
+ "github.com/docker/distribution/registry/api/errcode" |
|
| 22 | 23 |
"github.com/docker/docker/pkg/httputils" |
| 23 | 24 |
"github.com/docker/docker/pkg/ioutils" |
| 24 | 25 |
"github.com/docker/docker/pkg/stringid" |
| ... | ... |
@@ -213,7 +214,7 @@ func (r *Session) GetRemoteHistory(imgID, registry string) ([]string, error) {
|
| 213 | 213 |
defer res.Body.Close() |
| 214 | 214 |
if res.StatusCode != 200 {
|
| 215 | 215 |
if res.StatusCode == 401 {
|
| 216 |
- return nil, errLoginRequired |
|
| 216 |
+ return nil, errcode.ErrorCodeUnauthorized.WithArgs() |
|
| 217 | 217 |
} |
| 218 | 218 |
return nil, httputils.NewHTTPRequestError(fmt.Sprintf("Server error: %d trying to fetch remote history for %s", res.StatusCode, imgID), res)
|
| 219 | 219 |
} |
| ... | ... |
@@ -427,7 +428,7 @@ func (r *Session) GetRepositoryData(name reference.Named) (*RepositoryData, erro |
| 427 | 427 |
} |
| 428 | 428 |
defer res.Body.Close() |
| 429 | 429 |
if res.StatusCode == 401 {
|
| 430 |
- return nil, errLoginRequired |
|
| 430 |
+ return nil, errcode.ErrorCodeUnauthorized.WithArgs() |
|
| 431 | 431 |
} |
| 432 | 432 |
// TODO: Right now we're ignoring checksums in the response body. |
| 433 | 433 |
// In the future, we need to use them to check image validity. |
| ... | ... |
@@ -661,7 +662,7 @@ func (r *Session) PushImageJSONIndex(remote reference.Named, imgList []*ImgData, |
| 661 | 661 |
defer res.Body.Close() |
| 662 | 662 |
|
| 663 | 663 |
if res.StatusCode == 401 {
|
| 664 |
- return nil, errLoginRequired |
|
| 664 |
+ return nil, errcode.ErrorCodeUnauthorized.WithArgs() |
|
| 665 | 665 |
} |
| 666 | 666 |
|
| 667 | 667 |
var tokens, endpoints []string |