diff --git a/api/server/errorhandler.go b/api/server/errorhandler.go deleted file mode 100644 index 71a0c13c84..0000000000 --- a/api/server/errorhandler.go +++ /dev/null @@ -1,34 +0,0 @@ -package server - -import ( - "net/http" - - "github.com/docker/docker/api/server/httpstatus" - "github.com/docker/docker/api/server/httputils" - "github.com/docker/docker/api/types" - "github.com/docker/docker/api/types/versions" - "github.com/gorilla/mux" - "google.golang.org/grpc/status" -) - -// makeErrorHandler makes an HTTP handler that decodes a Docker error and -// returns it in the response. -func makeErrorHandler(err error) http.HandlerFunc { - return func(w http.ResponseWriter, r *http.Request) { - statusCode := httpstatus.FromError(err) - vars := mux.Vars(r) - if apiVersionSupportsJSONErrors(vars["version"]) { - response := &types.ErrorResponse{ - Message: err.Error(), - } - _ = httputils.WriteJSON(w, statusCode, response) - } else { - http.Error(w, status.Convert(err).Message(), statusCode) - } - } -} - -func apiVersionSupportsJSONErrors(version string) bool { - const firstAPIVersionWithJSONErrors = "1.23" - return version == "" || versions.GreaterThan(version, firstAPIVersionWithJSONErrors) -} diff --git a/api/server/server.go b/api/server/server.go index 3855197fa2..5e90d305a9 100644 --- a/api/server/server.go +++ b/api/server/server.go @@ -10,6 +10,7 @@ import ( "github.com/docker/docker/api/server/middleware" "github.com/docker/docker/api/server/router" "github.com/docker/docker/api/server/router/debug" + "github.com/docker/docker/api/types" "github.com/docker/docker/dockerversion" "github.com/gorilla/mux" "go.opentelemetry.io/contrib/instrumentation/net/http/otelhttp" @@ -57,19 +58,13 @@ func (s *Server) makeHTTPHandler(handler httputils.APIFunc, operation string) ht if statusCode >= 500 { log.G(ctx).Errorf("Handler for %s %s returned error: %v", r.Method, r.URL.Path, err) } - makeErrorHandler(err)(w, r) + _ = httputils.WriteJSON(w, statusCode, &types.ErrorResponse{ + Message: err.Error(), + }) } }), operation).ServeHTTP } -type pageNotFoundError struct{} - -func (pageNotFoundError) Error() string { - return "page not found" -} - -func (pageNotFoundError) NotFound() {} - // CreateMux returns a new mux with all the routers registered. func (s *Server) CreateMux(routers ...router.Router) *mux.Router { m := mux.NewRouter() @@ -91,7 +86,12 @@ func (s *Server) CreateMux(routers ...router.Router) *mux.Router { m.Path("/debug" + r.Path()).Handler(f) } - notFoundHandler := makeErrorHandler(pageNotFoundError{}) + notFoundHandler := http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) { + _ = httputils.WriteJSON(w, http.StatusNotFound, &types.ErrorResponse{ + Message: "page not found", + }) + }) + m.HandleFunc(versionMatcher+"/{path:.*}", notFoundHandler) m.NotFoundHandler = notFoundHandler m.MethodNotAllowedHandler = notFoundHandler diff --git a/integration-cli/docker_api_test.go b/integration-cli/docker_api_test.go index 085afcbedd..ca1235a9ff 100644 --- a/integration-cli/docker_api_test.go +++ b/integration-cli/docker_api_test.go @@ -3,7 +3,6 @@ package main import ( "context" "fmt" - "io" "net/http" "runtime" "strconv" @@ -62,9 +61,9 @@ func (s *DockerAPISuite) TestAPIClientVersionOldNotSupported(c *testing.T) { defer body.Close() assert.Equal(c, resp.StatusCode, http.StatusBadRequest) expected := fmt.Sprintf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", version, testEnv.DaemonVersion.MinAPIVersion) - content, err := io.ReadAll(body) + b, err := request.ReadBody(body) assert.NilError(c, err) - assert.Equal(c, strings.TrimSpace(string(content)), expected) + assert.Equal(c, getErrorMessage(c, b), expected) } func (s *DockerAPISuite) TestAPIErrorJSON(c *testing.T) { @@ -77,19 +76,6 @@ func (s *DockerAPISuite) TestAPIErrorJSON(c *testing.T) { assert.Equal(c, getErrorMessage(c, b), runconfig.ErrEmptyConfig.Error()) } -func (s *DockerAPISuite) TestAPIErrorPlainText(c *testing.T) { - // Windows requires API 1.25 or later. This test is validating a behaviour which was present - // in v1.23, but changed in 1.24, hence not applicable on Windows. See apiVersionSupportsJSONErrors - testRequires(c, DaemonIsLinux) - httpResp, body, err := request.Post(testutil.GetContext(c), "/v1.23/containers/create", request.JSONBody(struct{}{})) - assert.NilError(c, err) - assert.Equal(c, httpResp.StatusCode, http.StatusBadRequest) - assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "text/plain")) - b, err := request.ReadBody(body) - assert.NilError(c, err) - assert.Equal(c, strings.TrimSpace(string(b)), runconfig.ErrEmptyConfig.Error()) -} - func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) { // 404 is a different code path to normal errors, so test separately httpResp, body, err := request.Get(testutil.GetContext(c), "/notfound", request.JSON) @@ -100,13 +86,3 @@ func (s *DockerAPISuite) TestAPIErrorNotFoundJSON(c *testing.T) { assert.NilError(c, err) assert.Equal(c, getErrorMessage(c, b), "page not found") } - -func (s *DockerAPISuite) TestAPIErrorNotFoundPlainText(c *testing.T) { - httpResp, body, err := request.Get(testutil.GetContext(c), "/v1.23/notfound", request.JSON) - assert.NilError(c, err) - assert.Equal(c, httpResp.StatusCode, http.StatusNotFound) - assert.Assert(c, strings.Contains(httpResp.Header.Get("Content-Type"), "text/plain")) - b, err := request.ReadBody(body) - assert.NilError(c, err) - assert.Equal(c, strings.TrimSpace(string(b)), "page not found") -}