Browse code

Refactor client/request

Signed-off-by: Daniel Nephin <dnephin@docker.com>

Daniel Nephin authored on 2016/11/01 01:39:38
Showing 2 changed files
... ...
@@ -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) {