From e050f1760dd8a3d48d95bb3d2de503fc4177ff5f Mon Sep 17 00:00:00 2001 From: Boaz Shuster Date: Sun, 5 Feb 2017 13:39:37 +0200 Subject: [PATCH] Fix the create API when fromSrc has a bad URL When sending a bad URL in the fromSrc parameter using cURL the response will have status code 200 while it should have 404 or 500 (depends on the error). This commit addresses this problem in the following ways: * Before, `src` was parsed using url.Parse and if the returned `url.Scheme` was empty it was set to 'http' and `url.Host` was set to `src`. This is bad because if `src` was 'web.com/tars/image1.tar' The `url.String()` returns 'web.com%2Ftars%2Fimage1.tar` which will cause the daemon to fail downloading the file * Before writing the "Downloading" message, the image is attempted to be downloaded and if there is no error the "Downloading" message is sent. Signed-off-by: Boaz Shuster --- daemon/import.go | 12 ++++++------ integration-cli/docker_api_images_test.go | 23 +++++++++++++++++++++++ 2 files changed, 29 insertions(+), 6 deletions(-) diff --git a/daemon/import.go b/daemon/import.go index adc82550de..fc9f2682c5 100644 --- a/daemon/import.go +++ b/daemon/import.go @@ -6,6 +6,7 @@ import ( "net/http" "net/url" "runtime" + "strings" "time" "github.com/docker/distribution/reference" @@ -59,20 +60,19 @@ func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string rc = inConfig } else { inConfig.Close() + if len(strings.Split(src, "://")) == 1 { + src = "http://" + src + } u, err := url.Parse(src) if err != nil { return err } - if u.Scheme == "" { - u.Scheme = "http" - u.Host = src - u.Path = "" - } - outStream.Write(sf.FormatStatus("", "Downloading from %s", u)) + resp, err = httputils.Download(u.String()) if err != nil { return err } + outStream.Write(sf.FormatStatus("", "Downloading from %s", u)) progressOutput := sf.NewProgressOutput(outStream, true) rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing") } diff --git a/integration-cli/docker_api_images_test.go b/integration-cli/docker_api_images_test.go index 6f911491bf..80a9ca3229 100644 --- a/integration-cli/docker_api_images_test.go +++ b/integration-cli/docker_api_images_test.go @@ -115,6 +115,29 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) { c.Assert(historydata[0].Tags[0], checker.Equals, "test-api-images-history:latest") } +func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) { + testRequires(c, Network) + + tt := []struct { + statusExp int + fromSrc string + }{ + {http.StatusNotFound, "http://example.com/nofile.tar"}, + {http.StatusNotFound, "example.com/nofile.tar"}, + {http.StatusNotFound, "example.com%2Fdata%2Ffile.tar"}, + {http.StatusInternalServerError, "%2Fdata%2Ffile.tar"}, + } + + for _, te := range tt { + res, b, err := request.SockRequestRaw("POST", strings.Join([]string{"/images/create?fromSrc=", te.fromSrc}, ""), nil, "application/json", daemonHost()) + c.Assert(err, check.IsNil) + b.Close() + c.Assert(res.StatusCode, checker.Equals, te.statusExp) + c.Assert(res.Header.Get("Content-Type"), checker.Equals, "application/json") + } + +} + // #14846 func (s *DockerSuite) TestAPIImagesSearchJSONContentType(c *check.C) { testRequires(c, Network)