diff --git a/api/server/middleware/version.go b/api/server/middleware/version.go index ef35c728f1..32be500b06 100644 --- a/api/server/middleware/version.go +++ b/api/server/middleware/version.go @@ -28,11 +28,14 @@ func NewVersionMiddleware(s, d, m string) VersionMiddleware { } type versionUnsupportedError struct { - version, minVersion string + version, minVersion, maxVersion string } func (e versionUnsupportedError) Error() string { - return fmt.Sprintf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", e.version, e.minVersion) + if e.minVersion != "" { + return fmt.Sprintf("client version %s is too old. Minimum supported API version is %s, please upgrade your client to a newer version", e.version, e.minVersion) + } + return fmt.Sprintf("client version %s is too new. Maximum supported API version is %s", e.version, e.maxVersion) } func (e versionUnsupportedError) InvalidParameter() {} @@ -44,9 +47,11 @@ func (v VersionMiddleware) WrapHandler(handler func(ctx context.Context, w http. if apiVersion == "" { apiVersion = v.defaultVersion } - if versions.LessThan(apiVersion, v.minVersion) { - return versionUnsupportedError{apiVersion, v.minVersion} + return versionUnsupportedError{version: apiVersion, minVersion: v.minVersion} + } + if versions.GreaterThan(apiVersion, v.defaultVersion) { + return versionUnsupportedError{version: apiVersion, maxVersion: v.defaultVersion} } header := fmt.Sprintf("Docker/%s (%s)", v.serverVersion, runtime.GOOS) diff --git a/api/server/middleware/version_test.go b/api/server/middleware/version_test.go index 29787bf4d8..7cd8e8d6d0 100644 --- a/api/server/middleware/version_test.go +++ b/api/server/middleware/version_test.go @@ -31,7 +31,7 @@ func TestVersionMiddleware(t *testing.T) { } } -func TestVersionMiddlewareWithErrors(t *testing.T) { +func TestVersionMiddlewareVersionTooOld(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") @@ -55,3 +55,28 @@ func TestVersionMiddlewareWithErrors(t *testing.T) { t.Fatalf("Expected too old client error, got %v", err) } } + +func TestVersionMiddlewareVersionTooNew(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": "9999.9999"} + err := h(ctx, resp, req, vars) + + if !strings.Contains(err.Error(), "client version 9999.9999 is too new. Maximum supported API version is 1.10.0") { + t.Fatalf("Expected too new client error, got %v", err) + } +} diff --git a/api/swagger.yaml b/api/swagger.yaml index 2e4615f77f..c3b9c29244 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -50,6 +50,8 @@ info: In previous versions of Docker, it was possible to access the API without providing a version. This behaviour is now deprecated will be removed in a future version of Docker. + If the API version specified in the URL is not supported by the daemon, a HTTP `400 Bad Request` error message is returned. + The API uses an open schema model, which means server may add extra properties to responses. Likewise, the server will ignore any extra query parameters and request body properties. When you write clients, you need to ignore additional properties in responses to ensure they do not break when talking to newer Docker daemons. This documentation is for version 1.34 of the API. Use this table to find documentation for previous versions of the API: diff --git a/docs/api/v1.18.md b/docs/api/v1.18.md index 5543d59d34..7ae32ccc93 100644 --- a/docs/api/v1.18.md +++ b/docs/api/v1.18.md @@ -25,6 +25,11 @@ redirect_from: `stdin` and `stderr`. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.19.md b/docs/api/v1.19.md index 59e4fbe4cc..3ecd312c34 100644 --- a/docs/api/v1.19.md +++ b/docs/api/v1.19.md @@ -23,10 +23,13 @@ redirect_from: - The API tends to be REST. However, for some complex commands, like `attach` or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. - - When the client API version is newer than the daemon's, these calls return an HTTP - `400 Bad Request` error message. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.20.md b/docs/api/v1.20.md index 6db6476203..1f94bdaddb 100644 --- a/docs/api/v1.20.md +++ b/docs/api/v1.20.md @@ -23,10 +23,13 @@ redirect_from: - The API tends to be REST. However, for some complex commands, like `attach` or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. - - When the client API version is newer than the daemon's, these calls return an HTTP - `400 Bad Request` error message. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.21.md b/docs/api/v1.21.md index 202fbb1de0..a3b79ed8ba 100644 --- a/docs/api/v1.21.md +++ b/docs/api/v1.21.md @@ -23,10 +23,13 @@ redirect_from: - The API tends to be REST. However, for some complex commands, like `attach` or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. - - When the client API version is newer than the daemon's, these calls return an HTTP - `400 Bad Request` error message. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.22.md b/docs/api/v1.22.md index 51c1ab475a..a6027bb760 100644 --- a/docs/api/v1.22.md +++ b/docs/api/v1.22.md @@ -23,10 +23,13 @@ redirect_from: - The API tends to be REST. However, for some complex commands, like `attach` or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. - - When the client API version is newer than the daemon's, these calls return an HTTP - `400 Bad Request` error message. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.23.md b/docs/api/v1.23.md index a5acfe4321..19f9e5a961 100644 --- a/docs/api/v1.23.md +++ b/docs/api/v1.23.md @@ -23,10 +23,13 @@ redirect_from: - The API tends to be REST. However, for some complex commands, like `attach` or `pull`, the HTTP connection is hijacked to transport `stdout`, `stdin` and `stderr`. - - When the client API version is newer than the daemon's, these calls return an HTTP - `400 Bad Request` error message. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Endpoints diff --git a/docs/api/v1.24.md b/docs/api/v1.24.md index b79bbbdb22..6ab5dc2483 100644 --- a/docs/api/v1.24.md +++ b/docs/api/v1.24.md @@ -25,6 +25,11 @@ redirect_from: `stdin` and `stderr`. - A `Content-Length` header should be present in `POST` requests to endpoints that expect a body. + - To lock to a specific version of the API, you prefix the URL with the version + of the API to use. For example, `/v1.18/info`. If no version is included in + the URL, the maximum supported API version is used. + - If the API version specified in the URL is not supported by the daemon, a HTTP + `400 Bad Request` error message is returned. ## 2. Errors