|
@@ -9,6 +9,10 @@ import (
|
|
|
"net/http"
|
|
|
"net/url"
|
|
|
"strings"
|
|
|
+
|
|
|
+ "github.com/docker/engine-api/client/transport/cancellable"
|
|
|
+
|
|
|
+ "golang.org/x/net/context"
|
|
|
)
|
|
|
|
|
|
// serverResponse is a wrapper for http API responses.
|
|
@@ -20,40 +24,55 @@ type serverResponse struct {
|
|
|
|
|
|
// head sends an http request to the docker API using the method HEAD.
|
|
|
func (cli *Client) head(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendRequest("HEAD", path, query, nil, headers)
|
|
|
+ return cli.sendRequest(context.Background(), "HEAD", path, query, nil, headers)
|
|
|
}
|
|
|
|
|
|
// get sends an http request to the docker API using the method GET.
|
|
|
func (cli *Client) get(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendRequest("GET", path, query, nil, headers)
|
|
|
+ return cli.getWithContext(context.Background(), path, query, headers)
|
|
|
+}
|
|
|
+
|
|
|
+// getWithContext sends an http request to the docker API using the method GET with a specific go context.
|
|
|
+func (cli *Client) getWithContext(ctx context.Context, path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
|
+ return cli.sendRequest(ctx, "GET", path, query, nil, headers)
|
|
|
}
|
|
|
|
|
|
// post sends an http request to the docker API using the method POST.
|
|
|
func (cli *Client) post(path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendRequest("POST", path, query, body, headers)
|
|
|
+ return cli.postWithContext(context.Background(), path, query, body, headers)
|
|
|
}
|
|
|
|
|
|
-// postRaw sends the raw input to the docker API using the method POST.
|
|
|
-func (cli *Client) postRaw(path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendClientRequest("POST", path, query, body, headers)
|
|
|
+// postWithContext sends an http request to the docker API using the method POST with a specific go context.
|
|
|
+func (cli *Client) postWithContext(ctx context.Context, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
|
+ return cli.sendRequest(ctx, "POST", path, query, body, headers)
|
|
|
+}
|
|
|
+
|
|
|
+// postRaw sends the raw input to the docker API using the method POST with a specific go context.
|
|
|
+func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
+ return cli.sendClientRequest(ctx, "POST", path, query, body, headers)
|
|
|
}
|
|
|
|
|
|
// put sends an http request to the docker API using the method PUT.
|
|
|
func (cli *Client) put(path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendRequest("PUT", path, query, body, headers)
|
|
|
+ return cli.sendRequest(context.Background(), "PUT", path, query, body, headers)
|
|
|
}
|
|
|
|
|
|
// putRaw sends the raw input to the docker API using the method PUT.
|
|
|
func (cli *Client) putRaw(path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendClientRequest("PUT", path, query, body, headers)
|
|
|
+ return cli.putRawWithContext(context.Background(), path, query, body, headers)
|
|
|
+}
|
|
|
+
|
|
|
+// putRawWithContext sends the raw input to the docker API using the method PUT with a specific go context.
|
|
|
+func (cli *Client) putRawWithContext(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
+ return cli.sendClientRequest(ctx, "PUT", path, query, body, headers)
|
|
|
}
|
|
|
|
|
|
// delete sends an http request to the docker API using the method DELETE.
|
|
|
func (cli *Client) delete(path string, query url.Values, headers map[string][]string) (*serverResponse, error) {
|
|
|
- return cli.sendRequest("DELETE", path, query, nil, headers)
|
|
|
+ return cli.sendRequest(context.Background(), "DELETE", path, query, nil, headers)
|
|
|
}
|
|
|
|
|
|
-func (cli *Client) sendRequest(method, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
|
+func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body interface{}, headers map[string][]string) (*serverResponse, error) {
|
|
|
params, err := encodeData(body)
|
|
|
if err != nil {
|
|
|
return nil, err
|
|
@@ -66,10 +85,10 @@ func (cli *Client) sendRequest(method, path string, query url.Values, body inter
|
|
|
headers["Content-Type"] = []string{"application/json"}
|
|
|
}
|
|
|
|
|
|
- return cli.sendClientRequest(method, path, query, params, headers)
|
|
|
+ return cli.sendClientRequest(ctx, method, path, query, params, headers)
|
|
|
}
|
|
|
|
|
|
-func (cli *Client) sendClientRequest(method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
+func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (*serverResponse, error) {
|
|
|
serverResp := &serverResponse{
|
|
|
body: nil,
|
|
|
statusCode: -1,
|
|
@@ -82,13 +101,13 @@ func (cli *Client) sendClientRequest(method, path string, query url.Values, body
|
|
|
|
|
|
req, err := cli.newRequest(method, path, query, body, headers)
|
|
|
req.URL.Host = cli.addr
|
|
|
- req.URL.Scheme = cli.scheme
|
|
|
+ req.URL.Scheme = cli.transport.Scheme()
|
|
|
|
|
|
if expectedPayload && req.Header.Get("Content-Type") == "" {
|
|
|
req.Header.Set("Content-Type", "text/plain")
|
|
|
}
|
|
|
|
|
|
- resp, err := cli.httpClient.Do(req)
|
|
|
+ resp, err := cancellable.Do(ctx, cli.transport, req)
|
|
|
if resp != nil {
|
|
|
serverResp.statusCode = resp.StatusCode
|
|
|
}
|
|
@@ -98,10 +117,10 @@ func (cli *Client) sendClientRequest(method, path string, query url.Values, body
|
|
|
return serverResp, ErrConnectionFailed
|
|
|
}
|
|
|
|
|
|
- if cli.scheme == "http" && strings.Contains(err.Error(), "malformed HTTP response") {
|
|
|
+ if !cli.transport.Secure() && strings.Contains(err.Error(), "malformed HTTP response") {
|
|
|
return serverResp, fmt.Errorf("%v.\n* Are you trying to connect to a TLS-enabled daemon without TLS?", err)
|
|
|
}
|
|
|
- if cli.scheme == "https" && strings.Contains(err.Error(), "remote error: bad certificate") {
|
|
|
+ if cli.transport.Secure() && strings.Contains(err.Error(), "remote error: bad certificate") {
|
|
|
return serverResp, fmt.Errorf("The server probably has client authentication (--tlsverify) enabled. Please check your TLS client certification settings: %v", err)
|
|
|
}
|
|
|
|