diff --git a/api/server/router/system/system_routes.go b/api/server/router/system/system_routes.go index a2ff692de3..950d9d89a5 100644 --- a/api/server/router/system/system_routes.go +++ b/api/server/router/system/system_routes.go @@ -27,6 +27,9 @@ func optionsHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, } func (s *systemRouter) pingHandler(ctx context.Context, w http.ResponseWriter, r *http.Request, vars map[string]string) error { + w.Header().Add("Cache-Control", "no-cache, no-store, must-revalidate") + w.Header().Add("Pragma", "no-cache") + builderVersion := build.BuilderVersion(*s.features) if bv := builderVersion; bv != "" { w.Header().Set("Builder-Version", string(bv)) diff --git a/api/swagger.yaml b/api/swagger.yaml index dfc7fe744e..d6d345d5bc 100644 --- a/api/swagger.yaml +++ b/api/swagger.yaml @@ -7107,10 +7107,23 @@ paths: Docker-Experimental: type: "boolean" description: "If the server is running with experimental mode enabled" + Cache-Control: + type: "string" + default: "no-cache, no-store, must-revalidate" + Pragma: + type: "string" + default: "no-cache" 500: description: "server error" schema: $ref: "#/definitions/ErrorResponse" + headers: + Cache-Control: + type: "string" + default: "no-cache, no-store, must-revalidate" + Pragma: + type: "string" + default: "no-cache" tags: ["System"] /commit: post: diff --git a/docs/api/version-history.md b/docs/api/version-history.md index 3a838839e2..aa3733cfce 100644 --- a/docs/api/version-history.md +++ b/docs/api/version-history.md @@ -17,6 +17,9 @@ keywords: "API, Docker, rcli, REST, documentation" [Docker Engine API v1.40](https://docs.docker.com/engine/api/v1.40/) documentation +* `GET /_ping` now sets `Cache-Control` and `Pragma` headers to prevent the result + from being cached. This change is not versioned, and affects all API versions + if the daemon has this patch. * `GET /services` now returns `Sysctls` as part of the `ContainerSpec`. * `GET /services/{id}` now returns `Sysctls` as part of the `ContainerSpec`. * `POST /services/create` now accepts `Sysctls` as part of the `ContainerSpec`. diff --git a/integration/system/ping_test.go b/integration/system/ping_test.go new file mode 100644 index 0000000000..fc57b68606 --- /dev/null +++ b/integration/system/ping_test.go @@ -0,0 +1,29 @@ +package system // import "github.com/docker/docker/integration/system" + +import ( + "net/http" + "strings" + "testing" + + "github.com/docker/docker/internal/test/request" + "gotest.tools/assert" +) + +func TestPingCacheHeaders(t *testing.T) { + defer setupTest(t)() + + res, _, err := request.Get("/_ping") + assert.NilError(t, err) + assert.Equal(t, res.StatusCode, http.StatusOK) + + assert.Equal(t, hdr(res, "Cache-Control"), "no-cache, no-store, must-revalidate") + assert.Equal(t, hdr(res, "Pragma"), "no-cache") +} + +func hdr(res *http.Response, name string) string { + val, ok := res.Header[http.CanonicalHeaderKey(name)] + if !ok || len(val) == 0 { + return "" + } + return strings.Join(val, ", ") +}