Skip to content

Commit

Permalink
Merge pull request moby#35150 from thaJeztah/fix-api-version-check
Browse files Browse the repository at this point in the history
Return 400 error if API client is too new
  • Loading branch information
vieux authored Oct 11, 2017
2 parents 9b9d00d + 01f9227 commit 6f117e2
Show file tree
Hide file tree
Showing 10 changed files with 72 additions and 15 deletions.
13 changes: 9 additions & 4 deletions api/server/middleware/version.go
Original file line number Diff line number Diff line change
Expand Up @@ -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() {}
Expand All @@ -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)
Expand Down
27 changes: 26 additions & 1 deletion api/server/middleware/version_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -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")
Expand All @@ -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)
}
}
2 changes: 2 additions & 0 deletions api/swagger.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -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:
Expand Down
5 changes: 5 additions & 0 deletions docs/api/v1.18.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions docs/api/v1.19.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions docs/api/v1.20.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions docs/api/v1.21.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions docs/api/v1.22.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
7 changes: 5 additions & 2 deletions docs/api/v1.23.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down
5 changes: 5 additions & 0 deletions docs/api/v1.24.md
Original file line number Diff line number Diff line change
Expand Up @@ -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

Expand Down

0 comments on commit 6f117e2

Please sign in to comment.