diff --git a/api/client/hijack.go b/api/client/hijack.go index 5f4794a5e7..becb8a7479 100644 --- a/api/client/hijack.go +++ b/api/client/hijack.go @@ -149,7 +149,7 @@ func (cli *DockerCli) hijack(method, path string, setRawTerminal bool, in io.Rea req.Header.Set(k, v) } - req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) + req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION+" ("+runtime.GOOS+")") req.Header.Set("Content-Type", "text/plain") req.Header.Set("Connection", "Upgrade") req.Header.Set("Upgrade", "tcp") diff --git a/api/client/utils.go b/api/client/utils.go index 6fb9b256fd..3483d4727e 100644 --- a/api/client/utils.go +++ b/api/client/utils.go @@ -64,7 +64,7 @@ func (cli *DockerCli) clientRequest(method, path string, in io.Reader, headers m req.Header.Set(k, v) } - req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION) + req.Header.Set("User-Agent", "Docker-Client/"+dockerversion.VERSION+" ("+runtime.GOOS+")") req.URL.Host = cli.addr req.URL.Scheme = cli.scheme diff --git a/api/server/server.go b/api/server/server.go index d7ec2d47d7..605fe2999b 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -1459,6 +1459,13 @@ func makeHttpHandler(logging bool, localMethod string, localRoute string, handle if strings.Contains(r.Header.Get("User-Agent"), "Docker-Client/") { userAgent := strings.Split(r.Header.Get("User-Agent"), "/") + + // v1.20 onwards includes the GOOS of the client after the version + // such as Docker/1.7.0 (linux) + if len(userAgent) == 2 && strings.Contains(userAgent[1], " ") { + userAgent[1] = strings.Split(userAgent[1], " ")[0] + } + if len(userAgent) == 2 && !dockerVersion.Equal(version.Version(userAgent[1])) { logrus.Debugf("Warning: client and server don't have the same version (client: %s, server: %s)", userAgent[1], dockerVersion) } diff --git a/integration-cli/docker_api_test.go b/integration-cli/docker_api_test.go index 0bd48880a8..f1d0c327d6 100644 --- a/integration-cli/docker_api_test.go +++ b/integration-cli/docker_api_test.go @@ -35,7 +35,7 @@ func (s *DockerSuite) TestVersionStatusCode(c *check.C) { req, err := http.NewRequest("GET", "/v999.0/version", nil) c.Assert(err, check.IsNil) - req.Header.Set("User-Agent", "Docker-Client/999.0") + req.Header.Set("User-Agent", "Docker-Client/999.0 (os)") res, err := client.Do(req) c.Assert(res.StatusCode, check.Equals, http.StatusBadRequest) diff --git a/integration-cli/docker_cli_config_test.go b/integration-cli/docker_cli_config_test.go index 5ccd7af10e..82c133b2f7 100644 --- a/integration-cli/docker_cli_config_test.go +++ b/integration-cli/docker_cli_config_test.go @@ -7,7 +7,9 @@ import ( "os" "os/exec" "path/filepath" + "runtime" + "github.com/docker/docker/autogen/dockerversion" "github.com/docker/docker/pkg/homedir" "github.com/go-check/check" ) @@ -50,6 +52,14 @@ func (s *DockerSuite) TestConfigHttpHeader(c *check.C) { cmd := exec.Command(dockerBinary, "-H="+server.URL[7:], "ps") out, _, _ := runCommandWithOutput(cmd) + if headers["User-Agent"] == nil { + c.Fatalf("Missing User-Agent: %q\nout:%v", headers, out) + } + + if headers["User-Agent"][0] != "Docker-Client/"+dockerversion.VERSION+" ("+runtime.GOOS+")" { + c.Fatalf("Badly formatted User-Agent: %q\nout:%v", headers, out) + } + if headers["Myheader"] == nil || headers["Myheader"][0] != "MyValue" { c.Fatalf("Missing/bad header: %q\nout:%v", headers, out) }