mirror of
https://github.com/moby/moby.git
synced 2022-11-09 12:21:53 -05:00
Return 400 error if API client is too new
Commit e98e4a7111
implemented API version
negotiation using the `/_ping` endpoint. In that change, URL validation for the
maximum supported API version was removed from the API server (validation for
the _minimum_ version was kept in place).
With this feature, clients that support version negotiation would negotiate the
maximum version supported by the daemon, and downgrade to an older API version
if the client's default API version is not supported.
However, clients that do _not_ support version negotiation can call API versions
that are higher than the maximum supported version. Due to the missing version
check, this is silently ignored, and the daemon's default API version is used.
This is a problem, because the actual API version in use is non-deterministic;
for example, calling `/v9999.9999/version` on a daemon that runs API v1.34 will
use API v1.34, but calling the same URL on an older daemon may use API version
v1.24.
This patch reverts the removal of the API check for maximum supported versions.
The documentation has been updated accordingly
Before this patch is applied, the daemon returns a 200 (success):
$ curl -v --unix-socket /var/run/docker.sock http://localhost/v9999.9999/version
* Trying /var/run/docker.sock...
* Connected to localhost (/Users/sebastiaan/Library/Containers/com.dock) port 80 (#0)
> GET /v9999.9999/version HTTP/1.1
> Host: localhost
> User-Agent: curl/7.54.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Api-Version: 1.32
< Content-Length: 240
< Content-Type: application/json
< Date: Tue, 10 Oct 2017 09:11:29 GMT
< Docker-Experimental: true
< Ostype: linux
< Server: Docker/17.09.0-ce (linux)
<
{"Version":"17.09.0-ce","ApiVersion":"1.32","MinAPIVersion":"1.12","GitCommit":"afdb6d4","GoVersion":"go1.8.3","Os":"linux","Arch":"amd64","KernelVersion":"4.9.49-moby","Experimental":true,"BuildTime":"2017-09-26T22:45:38.000000000+00:00"}
* Connection #0 to host localhost left intact
After this patch is applied, a 400 (Bad Request) is returned:
$ curl -v --unix-socket /var/run/docker.sock http://localhost/v9999.9999/version
* Trying /var/run/docker.sock...
* Connected to localhost (/var/run/docker.sock) port 80 (#0)
> GET /v9999.9999/info HTTP/1.1
> Host: localhost
> User-Agent: curl/7.52.1
> Accept: */*
>
< HTTP/1.1 400 Bad Request
< Content-Type: application/json
< Date: Tue, 10 Oct 2017 08:08:34 GMT
< Content-Length: 89
<
{"message":"client version 9999.9999 is too new. Maximim supported API version is 1.34"}
* Curl_http_done: called premature == 0
* Connection #0 to host localhost left intact
Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
This commit is contained in:
parent
9ed0922683
commit
01f9227ec9
10 changed files with 72 additions and 15 deletions
|
@ -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)
|
||||
|
|
|
@ -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)
|
||||
}
|
||||
}
|
||||
|
|
|
@ -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:
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
|
@ -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
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue