Browse code

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 <ripcurld.github@gmail.com>

Boaz Shuster authored on 2017/02/05 20:39:37
Showing 2 changed files
... ...
@@ -6,6 +6,7 @@ import (
6 6
 	"net/http"
7 7
 	"net/url"
8 8
 	"runtime"
9
+	"strings"
9 10
 	"time"
10 11
 
11 12
 	"github.com/docker/distribution/reference"
... ...
@@ -59,20 +60,19 @@ func (daemon *Daemon) ImportImage(src string, repository, tag string, msg string
59 59
 		rc = inConfig
60 60
 	} else {
61 61
 		inConfig.Close()
62
+		if len(strings.Split(src, "://")) == 1 {
63
+			src = "http://" + src
64
+		}
62 65
 		u, err := url.Parse(src)
63 66
 		if err != nil {
64 67
 			return err
65 68
 		}
66
-		if u.Scheme == "" {
67
-			u.Scheme = "http"
68
-			u.Host = src
69
-			u.Path = ""
70
-		}
71
-		outStream.Write(sf.FormatStatus("", "Downloading from %s", u))
69
+
72 70
 		resp, err = httputils.Download(u.String())
73 71
 		if err != nil {
74 72
 			return err
75 73
 		}
74
+		outStream.Write(sf.FormatStatus("", "Downloading from %s", u))
76 75
 		progressOutput := sf.NewProgressOutput(outStream, true)
77 76
 		rc = progress.NewProgressReader(resp.Body, progressOutput, resp.ContentLength, "", "Importing")
78 77
 	}
... ...
@@ -115,6 +115,29 @@ func (s *DockerSuite) TestAPIImagesHistory(c *check.C) {
115 115
 	c.Assert(historydata[0].Tags[0], checker.Equals, "test-api-images-history:latest")
116 116
 }
117 117
 
118
+func (s *DockerSuite) TestAPIImagesImportBadSrc(c *check.C) {
119
+	testRequires(c, Network)
120
+
121
+	tt := []struct {
122
+		statusExp int
123
+		fromSrc   string
124
+	}{
125
+		{http.StatusNotFound, "http://example.com/nofile.tar"},
126
+		{http.StatusNotFound, "example.com/nofile.tar"},
127
+		{http.StatusNotFound, "example.com%2Fdata%2Ffile.tar"},
128
+		{http.StatusInternalServerError, "%2Fdata%2Ffile.tar"},
129
+	}
130
+
131
+	for _, te := range tt {
132
+		res, b, err := request.SockRequestRaw("POST", strings.Join([]string{"/images/create?fromSrc=", te.fromSrc}, ""), nil, "application/json", daemonHost())
133
+		c.Assert(err, check.IsNil)
134
+		b.Close()
135
+		c.Assert(res.StatusCode, checker.Equals, te.statusExp)
136
+		c.Assert(res.Header.Get("Content-Type"), checker.Equals, "application/json")
137
+	}
138
+
139
+}
140
+
118 141
 // #14846
119 142
 func (s *DockerSuite) TestAPIImagesSearchJSONContentType(c *check.C) {
120 143
 	testRequires(c, Network)