Signed-off-by: Daniel Nephin <dnephin@docker.com>
| ... | ... |
@@ -5,6 +5,7 @@ import ( |
| 5 | 5 |
"errors" |
| 6 | 6 |
"fmt" |
| 7 | 7 |
"net" |
| 8 |
+ "net/http" |
|
| 8 | 9 |
"net/http/httputil" |
| 9 | 10 |
"net/url" |
| 10 | 11 |
"strings" |
| ... | ... |
@@ -38,12 +39,14 @@ func (cli *Client) postHijacked(ctx context.Context, path string, query url.Valu |
| 38 | 38 |
return types.HijackedResponse{}, err
|
| 39 | 39 |
} |
| 40 | 40 |
|
| 41 |
- req, err := cli.newRequest("POST", path, query, bodyEncoded, headers)
|
|
| 41 |
+ apiPath := cli.getAPIPath(path, query) |
|
| 42 |
+ req, err := http.NewRequest("POST", apiPath, bodyEncoded)
|
|
| 42 | 43 |
if err != nil {
|
| 43 | 44 |
return types.HijackedResponse{}, err
|
| 44 | 45 |
} |
| 45 |
- req.Host = cli.addr |
|
| 46 |
+ req = cli.addHeaders(req, headers) |
|
| 46 | 47 |
|
| 48 |
+ req.Host = cli.addr |
|
| 47 | 49 |
req.Header.Set("Connection", "Upgrade")
|
| 48 | 50 |
req.Header.Set("Upgrade", "tcp")
|
| 49 | 51 |
|
| ... | ... |
@@ -38,21 +38,29 @@ func (cli *Client) get(ctx context.Context, path string, query url.Values, heade |
| 38 | 38 |
|
| 39 | 39 |
// postWithContext sends an http request to the docker API using the method POST with a specific go context. |
| 40 | 40 |
func (cli *Client) post(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
| 41 |
- return cli.sendRequest(ctx, "POST", path, query, obj, headers) |
|
| 41 |
+ body, headers, err := encodeBody(obj, headers) |
|
| 42 |
+ if err != nil {
|
|
| 43 |
+ return serverResponse{}, err
|
|
| 44 |
+ } |
|
| 45 |
+ return cli.sendRequest(ctx, "POST", path, query, body, headers) |
|
| 42 | 46 |
} |
| 43 | 47 |
|
| 44 | 48 |
func (cli *Client) postRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
| 45 |
- return cli.sendClientRequest(ctx, "POST", path, query, body, headers) |
|
| 49 |
+ return cli.sendRequest(ctx, "POST", path, query, body, headers) |
|
| 46 | 50 |
} |
| 47 | 51 |
|
| 48 | 52 |
// put sends an http request to the docker API using the method PUT. |
| 49 | 53 |
func (cli *Client) put(ctx context.Context, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
| 50 |
- return cli.sendRequest(ctx, "PUT", path, query, obj, headers) |
|
| 54 |
+ body, headers, err := encodeBody(obj, headers) |
|
| 55 |
+ if err != nil {
|
|
| 56 |
+ return serverResponse{}, err
|
|
| 57 |
+ } |
|
| 58 |
+ return cli.sendRequest(ctx, "PUT", path, query, body, headers) |
|
| 51 | 59 |
} |
| 52 | 60 |
|
| 53 | 61 |
// put sends an http request to the docker API using the method PUT. |
| 54 | 62 |
func (cli *Client) putRaw(ctx context.Context, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
| 55 |
- return cli.sendClientRequest(ctx, "PUT", path, query, body, headers) |
|
| 63 |
+ return cli.sendRequest(ctx, "PUT", path, query, body, headers) |
|
| 56 | 64 |
} |
| 57 | 65 |
|
| 58 | 66 |
// delete sends an http request to the docker API using the method DELETE. |
| ... | ... |
@@ -60,39 +68,35 @@ func (cli *Client) delete(ctx context.Context, path string, query url.Values, he |
| 60 | 60 |
return cli.sendRequest(ctx, "DELETE", path, query, nil, headers) |
| 61 | 61 |
} |
| 62 | 62 |
|
| 63 |
-func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, obj interface{}, headers map[string][]string) (serverResponse, error) {
|
|
| 64 |
- var body io.Reader |
|
| 63 |
+type headers map[string][]string |
|
| 65 | 64 |
|
| 66 |
- if obj != nil {
|
|
| 67 |
- var err error |
|
| 68 |
- body, err = encodeData(obj) |
|
| 69 |
- if err != nil {
|
|
| 70 |
- return serverResponse{}, err
|
|
| 71 |
- } |
|
| 72 |
- if headers == nil {
|
|
| 73 |
- headers = make(map[string][]string) |
|
| 74 |
- } |
|
| 75 |
- headers["Content-Type"] = []string{"application/json"}
|
|
| 65 |
+func encodeBody(obj interface{}, headers headers) (io.Reader, headers, error) {
|
|
| 66 |
+ if obj == nil {
|
|
| 67 |
+ return nil, headers, nil |
|
| 76 | 68 |
} |
| 77 | 69 |
|
| 78 |
- return cli.sendClientRequest(ctx, method, path, query, body, headers) |
|
| 79 |
-} |
|
| 80 |
- |
|
| 81 |
-func (cli *Client) sendClientRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers map[string][]string) (serverResponse, error) {
|
|
| 82 |
- serverResp := serverResponse{
|
|
| 83 |
- body: nil, |
|
| 84 |
- statusCode: -1, |
|
| 70 |
+ body, err := encodeData(obj) |
|
| 71 |
+ if err != nil {
|
|
| 72 |
+ return nil, headers, err |
|
| 85 | 73 |
} |
| 74 |
+ if headers == nil {
|
|
| 75 |
+ headers = make(map[string][]string) |
|
| 76 |
+ } |
|
| 77 |
+ headers["Content-Type"] = []string{"application/json"}
|
|
| 78 |
+ return body, headers, nil |
|
| 79 |
+} |
|
| 86 | 80 |
|
| 81 |
+func (cli *Client) buildRequest(method, path string, body io.Reader, headers headers) (*http.Request, error) {
|
|
| 87 | 82 |
expectedPayload := (method == "POST" || method == "PUT") |
| 88 | 83 |
if expectedPayload && body == nil {
|
| 89 | 84 |
body = bytes.NewReader([]byte{})
|
| 90 | 85 |
} |
| 91 | 86 |
|
| 92 |
- req, err := cli.newRequest(method, path, query, body, headers) |
|
| 87 |
+ req, err := http.NewRequest(method, path, body) |
|
| 93 | 88 |
if err != nil {
|
| 94 |
- return serverResp, err |
|
| 89 |
+ return nil, err |
|
| 95 | 90 |
} |
| 91 |
+ req = cli.addHeaders(req, headers) |
|
| 96 | 92 |
|
| 97 | 93 |
if cli.proto == "unix" || cli.proto == "npipe" {
|
| 98 | 94 |
// For local communications, it doesn't matter what the host is. We just |
| ... | ... |
@@ -106,6 +110,19 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q |
| 106 | 106 |
if expectedPayload && req.Header.Get("Content-Type") == "" {
|
| 107 | 107 |
req.Header.Set("Content-Type", "text/plain")
|
| 108 | 108 |
} |
| 109 |
+ return req, nil |
|
| 110 |
+} |
|
| 111 |
+ |
|
| 112 |
+func (cli *Client) sendRequest(ctx context.Context, method, path string, query url.Values, body io.Reader, headers headers) (serverResponse, error) {
|
|
| 113 |
+ req, err := cli.buildRequest(method, cli.getAPIPath(path, query), body, headers) |
|
| 114 |
+ if err != nil {
|
|
| 115 |
+ return serverResponse{}, err
|
|
| 116 |
+ } |
|
| 117 |
+ return cli.doRequest(ctx, req) |
|
| 118 |
+} |
|
| 119 |
+ |
|
| 120 |
+func (cli *Client) doRequest(ctx context.Context, req *http.Request) (serverResponse, error) {
|
|
| 121 |
+ serverResp := serverResponse{statusCode: -1}
|
|
| 109 | 122 |
|
| 110 | 123 |
resp, err := ctxhttp.Do(ctx, cli.client, req) |
| 111 | 124 |
if err != nil {
|
| ... | ... |
@@ -193,13 +210,7 @@ func (cli *Client) sendClientRequest(ctx context.Context, method, path string, q |
| 193 | 193 |
return serverResp, nil |
| 194 | 194 |
} |
| 195 | 195 |
|
| 196 |
-func (cli *Client) newRequest(method, path string, query url.Values, body io.Reader, headers map[string][]string) (*http.Request, error) {
|
|
| 197 |
- apiPath := cli.getAPIPath(path, query) |
|
| 198 |
- req, err := http.NewRequest(method, apiPath, body) |
|
| 199 |
- if err != nil {
|
|
| 200 |
- return nil, err |
|
| 201 |
- } |
|
| 202 |
- |
|
| 196 |
+func (cli *Client) addHeaders(req *http.Request, headers headers) *http.Request {
|
|
| 203 | 197 |
// Add CLI Config's HTTP Headers BEFORE we set the Docker headers |
| 204 | 198 |
// then the user can't change OUR headers |
| 205 | 199 |
for k, v := range cli.customHTTPHeaders {
|
| ... | ... |
@@ -211,8 +222,7 @@ func (cli *Client) newRequest(method, path string, query url.Values, body io.Rea |
| 211 | 211 |
req.Header[k] = v |
| 212 | 212 |
} |
| 213 | 213 |
} |
| 214 |
- |
|
| 215 |
- return req, nil |
|
| 214 |
+ return req |
|
| 216 | 215 |
} |
| 217 | 216 |
|
| 218 | 217 |
func encodeData(data interface{}) (*bytes.Buffer, error) {
|