moby/client/ping.go

76 lines
2.4 KiB
Go
Raw Normal View History

package client // import "github.com/docker/docker/client"
import (
"context"
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
"net/http"
"path"
"strings"
"github.com/docker/docker/api/types"
"github.com/docker/docker/api/types/swarm"
"github.com/docker/docker/errdefs"
)
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
// Ping pings the server and returns the value of the "Docker-Experimental",
// "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use
// a HEAD request on the endpoint, but falls back to GET if HEAD is not supported
// by the daemon.
func (cli *Client) Ping(ctx context.Context) (types.Ping, error) {
var ping types.Ping
// Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest()
// because ping requests are used during API version negotiation, so we want
// to hit the non-versioned /_ping endpoint, not /v1.xx/_ping
req, err := cli.buildRequest(http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil)
if err != nil {
return ping, err
}
serverResp, err := cli.doRequest(ctx, req)
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
if err == nil {
defer ensureReaderClosed(serverResp)
switch serverResp.statusCode {
case http.StatusOK, http.StatusInternalServerError:
// Server handled the request, so parse the response
return parsePingResponse(cli, serverResp)
}
} else if IsErrConnectionFailed(err) {
return ping, err
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
}
req, err = cli.buildRequest(http.MethodGet, path.Join(cli.basePath, "/_ping"), nil, nil)
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
if err != nil {
return ping, err
}
serverResp, err = cli.doRequest(ctx, req)
defer ensureReaderClosed(serverResp)
if err != nil {
return ping, err
}
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
return parsePingResponse(cli, serverResp)
}
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) {
var ping types.Ping
if resp.header == nil {
err := cli.checkResponseErr(resp)
return ping, errdefs.FromStatusCode(err, resp.statusCode)
Add HEAD support for /_ping endpoint Monitoring systems and load balancers are usually configured to use HEAD requests for health monitoring. The /_ping endpoint currently does not support this type of request, which means that those systems have fallback to GET requests. This patch adds support for HEAD requests on the /_ping endpoint. Although optional, this patch also returns `Content-Type` and `Content-Length` headers in case of a HEAD request; Refering to RFC 7231, section 4.3.2: The HEAD method is identical to GET except that the server MUST NOT send a message body in the response (i.e., the response terminates at the end of the header section). The server SHOULD send the same header fields in response to a HEAD request as it would have sent if the request had been a GET, except that the payload header fields (Section 3.3) MAY be omitted. This method can be used for obtaining metadata about the selected representation without transferring the representation data and is often used for testing hypertext links for validity, accessibility, and recent modification. A payload within a HEAD request message has no defined semantics; sending a payload body on a HEAD request might cause some existing implementations to reject the request. The response to a HEAD request is cacheable; a cache MAY use it to satisfy subsequent HEAD requests unless otherwise indicated by the Cache-Control header field (Section 5.2 of [RFC7234]). A HEAD response might also have an effect on previously cached responses to GET; see Section 4.3.5 of [RFC7234]. With this patch applied, either `GET` or `HEAD` requests work; the only difference is that the body is empty in case of a `HEAD` request; curl -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:35:16 GMT Content-Length: 2 Content-Type: text/plain; charset=utf-8 OK curl --head -i --unix-socket /var/run/docker.sock http://localhost/_ping HTTP/1.1 200 OK Api-Version: 1.40 Cache-Control: no-cache, no-store, must-revalidate Content-Length: 0 Content-Type: text/plain; charset=utf-8 Docker-Experimental: false Ostype: linux Pragma: no-cache Server: Docker/dev (linux) Date: Mon, 14 Jan 2019 12:34:15 GMT The client is also updated to use `HEAD` by default, but fallback to `GET` if the daemon does not support this method. Signed-off-by: Sebastiaan van Stijn <github@gone.nl>
2019-01-14 17:08:49 +00:00
}
ping.APIVersion = resp.header.Get("API-Version")
ping.OSType = resp.header.Get("OSType")
if resp.header.Get("Docker-Experimental") == "true" {
ping.Experimental = true
}
if bv := resp.header.Get("Builder-Version"); bv != "" {
ping.BuilderVersion = types.BuilderVersion(bv)
}
if si := resp.header.Get("Swarm"); si != "" {
parts := strings.SplitN(si, "/", 2)
ping.SwarmStatus = &swarm.Status{
NodeState: swarm.LocalNodeState(parts[0]),
ControlAvailable: len(parts) == 2 && parts[1] == "manager",
}
}
err := cli.checkResponseErr(resp)
return ping, errdefs.FromStatusCode(err, resp.statusCode)
}