Browse code

client: remove getDockerOS utility in favor of "Ostype" header

This utility was added in 83b5729f6452de6b40719b9485947eea0bd0eedd to
replace httputils.ParseServerHeader, which was added to print a warning
on Windows in 126529c6d0a20675de8f50939c57f23259d3e763. At the time, the
only available option to detect the daemon's OS was to parse the `Server`
header, which contained the version of Docker as well as the OS.

However, 7199522ea2e77c77bf931474eca92aa502ce0031 introduced an `OSType`
("Ostype") header that's included on all responses, and a later commit
e9dac5ef5e8a4b0ecce0c89d337fea90f2c6aef3 changed that to also be included
when producing an error for unsupported API versions.

Note that the casing in the midddleware was changed from `OSType` to
`Ostype` (normalized form) in 76a5ca1d4d97ad313b8f1f0deb1ae5563a158a40,
but headers are case-insensitive, and `header.Get()` should handle either
case in the response.

In short; every API response contains an "Ostype" header, which already
contains the OS ("windows" or "linux") that doesn't require any parsing,
so let's put that header to use.

Signed-off-by: Sebastiaan van Stijn <github@gone.nl>

Sebastiaan van Stijn authored on 2025/06/28 01:03:47
Showing 4 changed files
... ...
@@ -28,7 +28,7 @@ func (cli *Client) ContainerStats(ctx context.Context, containerID string, strea
28 28
 
29 29
 	return container.StatsResponseReader{
30 30
 		Body:   resp.Body,
31
-		OSType: getDockerOS(resp.Header.Get("Server")),
31
+		OSType: resp.Header.Get("Ostype"),
32 32
 	}, nil
33 33
 }
34 34
 
... ...
@@ -51,6 +51,6 @@ func (cli *Client) ContainerStatsOneShot(ctx context.Context, containerID string
51 51
 
52 52
 	return container.StatsResponseReader{
53 53
 		Body:   resp.Body,
54
-		OSType: getDockerOS(resp.Header.Get("Server")),
54
+		OSType: resp.Header.Get("Ostype"),
55 55
 	}, nil
56 56
 }
... ...
@@ -40,7 +40,7 @@ func (cli *Client) ImageBuild(ctx context.Context, buildContext io.Reader, optio
40 40
 
41 41
 	return build.ImageBuildResponse{
42 42
 		Body:   resp.Body,
43
-		OSType: getDockerOS(resp.Header.Get("Server")),
43
+		OSType: resp.Header.Get("Ostype"),
44 44
 	}, nil
45 45
 }
46 46
 
... ...
@@ -191,7 +191,7 @@ func TestImageBuild(t *testing.T) {
191 191
 				}
192 192
 
193 193
 				headers := http.Header{}
194
-				headers.Add("Server", "Docker/v1.23 (MyOS)")
194
+				headers.Add("Ostype", "MyOS")
195 195
 				return &http.Response{
196 196
 					StatusCode: http.StatusOK,
197 197
 					Body:       io.NopCloser(bytes.NewReader([]byte("body"))),
... ...
@@ -208,15 +208,3 @@ func TestImageBuild(t *testing.T) {
208 208
 		assert.Check(t, is.Equal(string(response), "body"))
209 209
 	}
210 210
 }
211
-
212
-func TestGetDockerOS(t *testing.T) {
213
-	cases := map[string]string{
214
-		"Docker/v1.22 (linux)":   "linux",
215
-		"Docker/v1.22 (windows)": "windows",
216
-		"Foo/v1.22 (bar)":        "",
217
-	}
218
-	for header, os := range cases {
219
-		g := getDockerOS(header)
220
-		assert.Check(t, is.Equal(g, os))
221
-	}
222
-}
... ...
@@ -8,12 +8,9 @@ import (
8 8
 
9 9
 	cerrdefs "github.com/containerd/errdefs"
10 10
 	"github.com/docker/docker/api/types/filters"
11
-	"github.com/docker/docker/internal/lazyregexp"
12 11
 	ocispec "github.com/opencontainers/image-spec/specs-go/v1"
13 12
 )
14 13
 
15
-var headerRegexp = lazyregexp.New(`\ADocker/.+\s\((.+)\)\z`)
16
-
17 14
 type emptyIDError string
18 15
 
19 16
 func (e emptyIDError) InvalidParameter() {}
... ...
@@ -31,16 +28,6 @@ func trimID(objType, id string) (string, error) {
31 31
 	return id, nil
32 32
 }
33 33
 
34
-// getDockerOS returns the operating system based on the server header from the daemon.
35
-func getDockerOS(serverHeader string) string {
36
-	var osType string
37
-	matches := headerRegexp.FindStringSubmatch(serverHeader)
38
-	if len(matches) > 0 {
39
-		osType = matches[1]
40
-	}
41
-	return osType
42
-}
43
-
44 34
 // getFiltersQuery returns a url query with "filters" query term, based on the
45 35
 // filters provided.
46 36
 func getFiltersQuery(f filters.Args) (url.Values, error) {