github.com/adityamillind98/moby@v23.0.0-rc.4+incompatible/client/ping.go (about) 1 package client // import "github.com/docker/docker/client" 2 3 import ( 4 "context" 5 "net/http" 6 "path" 7 "strings" 8 9 "github.com/docker/docker/api/types" 10 "github.com/docker/docker/api/types/swarm" 11 "github.com/docker/docker/errdefs" 12 ) 13 14 // Ping pings the server and returns the value of the "Docker-Experimental", 15 // "Builder-Version", "OS-Type" & "API-Version" headers. It attempts to use 16 // a HEAD request on the endpoint, but falls back to GET if HEAD is not supported 17 // by the daemon. 18 func (cli *Client) Ping(ctx context.Context) (types.Ping, error) { 19 var ping types.Ping 20 21 // Using cli.buildRequest() + cli.doRequest() instead of cli.sendRequest() 22 // because ping requests are used during API version negotiation, so we want 23 // to hit the non-versioned /_ping endpoint, not /v1.xx/_ping 24 req, err := cli.buildRequest(http.MethodHead, path.Join(cli.basePath, "/_ping"), nil, nil) 25 if err != nil { 26 return ping, err 27 } 28 serverResp, err := cli.doRequest(ctx, req) 29 if err == nil { 30 defer ensureReaderClosed(serverResp) 31 switch serverResp.statusCode { 32 case http.StatusOK, http.StatusInternalServerError: 33 // Server handled the request, so parse the response 34 return parsePingResponse(cli, serverResp) 35 } 36 } else if IsErrConnectionFailed(err) { 37 return ping, err 38 } 39 40 req, err = cli.buildRequest(http.MethodGet, path.Join(cli.basePath, "/_ping"), nil, nil) 41 if err != nil { 42 return ping, err 43 } 44 serverResp, err = cli.doRequest(ctx, req) 45 defer ensureReaderClosed(serverResp) 46 if err != nil { 47 return ping, err 48 } 49 return parsePingResponse(cli, serverResp) 50 } 51 52 func parsePingResponse(cli *Client, resp serverResponse) (types.Ping, error) { 53 var ping types.Ping 54 if resp.header == nil { 55 err := cli.checkResponseErr(resp) 56 return ping, errdefs.FromStatusCode(err, resp.statusCode) 57 } 58 ping.APIVersion = resp.header.Get("API-Version") 59 ping.OSType = resp.header.Get("OSType") 60 if resp.header.Get("Docker-Experimental") == "true" { 61 ping.Experimental = true 62 } 63 if bv := resp.header.Get("Builder-Version"); bv != "" { 64 ping.BuilderVersion = types.BuilderVersion(bv) 65 } 66 if si := resp.header.Get("Swarm"); si != "" { 67 parts := strings.SplitN(si, "/", 2) 68 ping.SwarmStatus = &swarm.Status{ 69 NodeState: swarm.LocalNodeState(parts[0]), 70 ControlAvailable: len(parts) == 2 && parts[1] == "manager", 71 } 72 } 73 err := cli.checkResponseErr(resp) 74 return ping, errdefs.FromStatusCode(err, resp.statusCode) 75 }