From e9dac5ef5e8a4b0ecce0c89d337fea90f2c6aef3 Mon Sep 17 00:00:00 2001 From: Sebastiaan van Stijn Date: Tue, 10 Oct 2017 12:40:15 +0200 Subject: [PATCH] Always return version and server headers If a 400 error is returned due to an API version mismatch, no version and server-identification headers were returned by the API. All information in these headers is "static", so there is no reason to omit the information in case of an error being returned. This patch updates the version middleware to always return the headers. Signed-off-by: Sebastiaan van Stijn --- api/server/middleware/version.go | 9 ++++---- api/server/middleware/version_test.go | 30 +++++++++++++++++++++++++++ 2 files changed, 34 insertions(+), 5 deletions(-) diff --git a/api/server/middleware/version.go b/api/server/middleware/version.go index 32be500b06..679552910f 100644 --- a/api/server/middleware/version.go +++ b/api/server/middleware/version.go @@ -43,6 +43,10 @@ func (e versionUnsupportedError) InvalidParameter() {} // WrapHandler returns a new handler function wrapping the previous one in the request chain. func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error) func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { return func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + w.Header().Set("Server", fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS)) + w.Header().Set("API-Version", v.defaultVersion) + w.Header().Set("OSType", runtime.GOOS) + apiVersion := vars["version"] if apiVersion == "" { apiVersion = v.defaultVersion @@ -53,11 +57,6 @@ func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http. if versions.GreaterThan(apiVersion, v.defaultVersion) { return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultVersion} } - - header := fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS) - w.Header().Set("Server", header) - w.Header().Set("API-Version", v.defaultVersion) - w.Header().Set("OSType", runtime.GOOS) // nolint: golint ctx = context.WithValue(ctx, "api-version", apiVersion) return handler(ctx, w, r, vars) diff --git a/api/server/middleware/version_test.go b/api/server/middleware/version_test.go index 7cd8e8d6d0..9cf7cc247d 100644 --- a/api/server/middleware/version_test.go +++ b/api/server/middleware/version_test.go @@ -3,10 +3,12 @@ package middleware import ( "net/http" "net/http/httptest" + "runtime" "strings" "testing" "github.com/docker/docker/api/server/httputils" + "github.com/stretchr/testify/assert" "golang.org/x/net/context" ) @@ -80,3 +82,31 @@ func TestVersionMiddlewareVersionTooNew(t *testing.T) { t.Fatalf("Expected too new client error, got %v", err) } } + +func TestVersionMiddlewareWithErrorsReturnsHeaders(t *testing.T) { + handler := func(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + if httputils.VersionFromContext(ctx) == "" { + t.Fatal("Expected version, got empty string") + } + return nil + } + + defaultVersion := "1.10.0" + minVersion := "1.2.0" + m := NewVersionMiddleware(defaultVersion, defaultVersion, minVersion) + h := m.WrapHandler(handler) + + req, _ := http.NewRequest("GET", "/containers/json", nil) + resp := httptest.NewRecorder() + ctx := context.Background() + + vars := map[string]string{"version": "0.1"} + err := h(ctx, resp, req, vars) + + assert.Error(t, err) + hdr := resp.Result().Header + assert.Contains(t, hdr.Get("Server"), "Docker/"+defaultVersion) + assert.Contains(t, hdr.Get("Server"), runtime.GOOS) + assert.Equal(t, hdr.Get("API-Version"), defaultVersion) + assert.Equal(t, hdr.Get("OSType"), runtime.GOOS) +}