22
22
// channel, and finally returns the given status code. If body is not nil, it
23
23
// will be returned as the request body.
24
24
func makeRecordingHTTPServer(requests chan *Request, status int, body []byte, headers http.Header) *httptest.Server {
25
var server *httptest.Server
26
returnRequest := func(w http.ResponseWriter, r *http.Request) {
27
// Capture all the request body content for later inspection.
28
requestBody, err := ioutil.ReadAll(r.Body)
32
requests <- &Request{r, requestBody}
33
// Set a default Location so we can test redirect loops easily.
34
w.Header().Set("Location", server.URL+r.URL.Path)
35
for header, values := range headers {
36
for _, value := range values {
37
w.Header().Set(header, value)
45
serveMux := http.NewServeMux()
46
serveMux.HandleFunc("/", returnRequest)
47
server = httptest.NewServer(serveMux)
25
var server *httptest.Server
26
returnRequest := func(w http.ResponseWriter, r *http.Request) {
27
// Capture all the request body content for later inspection.
28
requestBody, err := ioutil.ReadAll(r.Body)
32
requests <- &Request{r, requestBody}
33
// Set a default Location so we can test redirect loops easily.
34
w.Header().Set("Location", server.URL+r.URL.Path)
35
for header, values := range headers {
36
for _, value := range values {
37
w.Header().Set(header, value)
45
serveMux := http.NewServeMux()
46
serveMux.HandleFunc("/", returnRequest)
47
server = httptest.NewServer(serveMux)
51
51
func (*x509DispatcherSuite) TestGetRequestDoesHTTPGET(c *C) {
52
httpRequests := make(chan *Request, 1)
53
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, nil, nil)
55
// No real certificate needed since we're testing on http, not https.
56
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
59
version := "test-version"
60
request := newX509RequestGET(server.URL+path, version)
62
response, err := performX509Request(session, request)
64
c.Assert(response.StatusCode, Equals, http.StatusOK)
66
httpRequest := <-httpRequests
67
c.Check(httpRequest.Method, Equals, "GET")
68
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
69
c.Check(httpRequest.URL.String(), Equals, path)
70
c.Check(httpRequest.BodyContent, HasLen, 0)
52
httpRequests := make(chan *Request, 1)
53
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, nil, nil)
55
// No real certificate needed since we're testing on http, not https.
56
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
59
version := "test-version"
60
request := newX509RequestGET(server.URL+path, version)
62
response, err := performX509Request(session, request)
64
c.Assert(response.StatusCode, Equals, http.StatusOK)
66
httpRequest := <-httpRequests
67
c.Check(httpRequest.Method, Equals, "GET")
68
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
69
c.Check(httpRequest.URL.String(), Equals, path)
70
c.Check(httpRequest.BodyContent, HasLen, 0)
73
73
func (*x509DispatcherSuite) TestRetryPolicyCausesRequestsToBeRetried(c *C) {
75
nbRequests := nbRetries + 1
76
httpRequests := make(chan *Request, nbRequests)
77
server := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
79
// No real certificate needed since we're testing on http, not https.
80
retryPolicy := RetryPolicy{NbRetries: nbRetries, HttpStatusCodes: []int{http.StatusConflict}, Delay: time.Nanosecond}
81
session, err := newX509Session("subscriptionid", "", "West US", retryPolicy)
84
version := "test-version"
85
request := newX509RequestGET(server.URL+path, version)
87
response, err := performX509Request(session, request)
89
c.Assert(response.StatusCode, Equals, http.StatusConflict)
91
// nbRequests request were performed.
92
c.Check(httpRequests, HasLen, nbRequests)
75
nbRequests := nbRetries + 1
76
httpRequests := make(chan *Request, nbRequests)
77
server := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
79
// No real certificate needed since we're testing on http, not https.
80
retryPolicy := RetryPolicy{NbRetries: nbRetries, HttpStatusCodes: []int{http.StatusConflict}, Delay: time.Nanosecond}
81
session, err := newX509Session("subscriptionid", "", "West US", retryPolicy)
84
version := "test-version"
85
request := newX509RequestGET(server.URL+path, version)
87
response, err := performX509Request(session, request)
89
c.Assert(response.StatusCode, Equals, http.StatusConflict)
91
// nbRequests request were performed.
92
c.Check(httpRequests, HasLen, nbRequests)
95
95
func (*x509DispatcherSuite) TestPostRequestDoesHTTPPOST(c *C) {
96
httpRequests := make(chan *Request, 1)
97
requestBody := []byte{1, 2, 3}
98
responseBody := []byte{4, 5, 6}
99
requestContentType := "bogusContentType"
100
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, responseBody, nil)
102
// No real certificate needed since we're testing on http, not https.
103
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
106
version := "test-version"
107
request := newX509RequestPOST(server.URL+path, version, requestBody, requestContentType)
109
response, err := performX509Request(session, request)
111
c.Assert(response.StatusCode, Equals, http.StatusOK)
112
c.Check(response.Body, DeepEquals, responseBody)
114
httpRequest := <-httpRequests
115
c.Check(httpRequest.Header[http.CanonicalHeaderKey("Content-Type")], DeepEquals, []string{requestContentType})
116
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{request.APIVersion})
117
c.Check(httpRequest.Method, Equals, "POST")
118
c.Check(httpRequest.URL.String(), Equals, path)
119
c.Check(httpRequest.BodyContent, DeepEquals, requestBody)
96
httpRequests := make(chan *Request, 1)
97
requestBody := []byte{1, 2, 3}
98
responseBody := []byte{4, 5, 6}
99
requestContentType := "bogusContentType"
100
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, responseBody, nil)
102
// No real certificate needed since we're testing on http, not https.
103
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
106
version := "test-version"
107
request := newX509RequestPOST(server.URL+path, version, requestBody, requestContentType)
109
response, err := performX509Request(session, request)
111
c.Assert(response.StatusCode, Equals, http.StatusOK)
112
c.Check(response.Body, DeepEquals, responseBody)
114
httpRequest := <-httpRequests
115
c.Check(httpRequest.Header[http.CanonicalHeaderKey("Content-Type")], DeepEquals, []string{requestContentType})
116
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{request.APIVersion})
117
c.Check(httpRequest.Method, Equals, "POST")
118
c.Check(httpRequest.URL.String(), Equals, path)
119
c.Check(httpRequest.BodyContent, DeepEquals, requestBody)
122
122
func (*x509DispatcherSuite) TestDeleteRequestDoesHTTPDELETE(c *C) {
123
httpRequests := make(chan *Request, 1)
124
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, nil, nil)
126
// No real certificate needed since we're testing on http, not https.
127
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
130
version := "test-version"
131
request := newX509RequestDELETE(server.URL+path, version)
133
response, err := performX509Request(session, request)
135
c.Assert(response.StatusCode, Equals, http.StatusOK)
137
httpRequest := <-httpRequests
138
c.Check(httpRequest.Method, Equals, "DELETE")
139
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
140
c.Check(httpRequest.URL.String(), Equals, path)
141
c.Check(httpRequest.BodyContent, HasLen, 0)
123
httpRequests := make(chan *Request, 1)
124
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, nil, nil)
126
// No real certificate needed since we're testing on http, not https.
127
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
130
version := "test-version"
131
request := newX509RequestDELETE(server.URL+path, version)
133
response, err := performX509Request(session, request)
135
c.Assert(response.StatusCode, Equals, http.StatusOK)
137
httpRequest := <-httpRequests
138
c.Check(httpRequest.Method, Equals, "DELETE")
139
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
140
c.Check(httpRequest.URL.String(), Equals, path)
141
c.Check(httpRequest.BodyContent, HasLen, 0)
144
144
func (*x509DispatcherSuite) TestPutRequestDoesHTTPPUT(c *C) {
145
httpRequests := make(chan *Request, 1)
146
requestBody := []byte{1, 2, 3}
147
responseBody := []byte{4, 5, 6}
148
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, responseBody, nil)
150
// No real certificate needed since we're testing on http, not https.
151
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
154
version := "test-version"
155
request := newX509RequestPUT(server.URL+path, version, requestBody, "application/octet-stream")
157
response, err := performX509Request(session, request)
159
c.Assert(response.StatusCode, Equals, http.StatusOK)
160
c.Check(response.Body, DeepEquals, responseBody)
162
httpRequest := <-httpRequests
163
c.Check(httpRequest.Method, Equals, "PUT")
164
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
165
c.Check(httpRequest.URL.String(), Equals, path)
166
c.Check(httpRequest.BodyContent, DeepEquals, requestBody)
145
httpRequests := make(chan *Request, 1)
146
requestBody := []byte{1, 2, 3}
147
responseBody := []byte{4, 5, 6}
148
server := makeRecordingHTTPServer(httpRequests, http.StatusOK, responseBody, nil)
150
// No real certificate needed since we're testing on http, not https.
151
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
154
version := "test-version"
155
request := newX509RequestPUT(server.URL+path, version, requestBody, "application/octet-stream")
157
response, err := performX509Request(session, request)
159
c.Assert(response.StatusCode, Equals, http.StatusOK)
160
c.Check(response.Body, DeepEquals, responseBody)
162
httpRequest := <-httpRequests
163
c.Check(httpRequest.Method, Equals, "PUT")
164
c.Check(httpRequest.Header[http.CanonicalHeaderKey("X-Ms-Version")], DeepEquals, []string{version})
165
c.Check(httpRequest.URL.String(), Equals, path)
166
c.Check(httpRequest.BodyContent, DeepEquals, requestBody)
169
169
func (*x509DispatcherSuite) TestRequestRegistersHeader(c *C) {
170
customHeader := http.CanonicalHeaderKey("x-gwacl-test")
171
customValue := []string{"present"}
172
returnRequest := func(w http.ResponseWriter, r *http.Request) {
173
w.Header()[customHeader] = customValue
174
w.WriteHeader(http.StatusOK)
176
serveMux := http.NewServeMux()
177
serveMux.HandleFunc("/", returnRequest)
178
server := httptest.NewServer(serveMux)
180
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
183
request := newX509RequestGET(server.URL+path, "testversion")
185
response, err := performX509Request(session, request)
188
c.Check(response.Header[customHeader], DeepEquals, customValue)
170
customHeader := http.CanonicalHeaderKey("x-gwacl-test")
171
customValue := []string{"present"}
172
returnRequest := func(w http.ResponseWriter, r *http.Request) {
173
w.Header()[customHeader] = customValue
174
w.WriteHeader(http.StatusOK)
176
serveMux := http.NewServeMux()
177
serveMux.HandleFunc("/", returnRequest)
178
server := httptest.NewServer(serveMux)
180
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
183
request := newX509RequestGET(server.URL+path, "testversion")
185
response, err := performX509Request(session, request)
188
c.Check(response.Header[customHeader], DeepEquals, customValue)
191
191
func (*x509DispatcherSuite) TestRequestsFollowRedirects(c *C) {
192
httpRequests := make(chan *Request, 2)
193
serverConflict := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
194
defer serverConflict.Close()
195
redirPath := "/else/where"
196
responseHeaders := make(http.Header)
197
responseHeaders.Set("Location", serverConflict.URL+redirPath)
198
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, responseHeaders)
199
defer serverRedir.Close()
200
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
203
version := "test-version"
192
httpRequests := make(chan *Request, 2)
193
serverConflict := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
194
defer serverConflict.Close()
195
redirPath := "/else/where"
196
responseHeaders := make(http.Header)
197
responseHeaders.Set("Location", serverConflict.URL+redirPath)
198
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, responseHeaders)
199
defer serverRedir.Close()
200
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
203
version := "test-version"
205
// Test both GET and DELETE: DELETE does not normally
206
// automatically follow redirects, however Azure requires
208
requests := []*X509Request{
209
newX509RequestGET(serverRedir.URL+path, version),
210
newX509RequestDELETE(serverRedir.URL+path, version),
212
for _, request := range requests {
213
response, err := performX509Request(session, request)
215
c.Assert(response.StatusCode, Equals, http.StatusConflict)
216
c.Assert(httpRequests, HasLen, 2)
217
c.Assert((<-httpRequests).URL.String(), Equals, path)
218
c.Assert((<-httpRequests).URL.String(), Equals, redirPath)
205
// Test both GET and DELETE: DELETE does not normally
206
// automatically follow redirects, however Azure requires
208
requests := []*X509Request{
209
newX509RequestGET(serverRedir.URL+path, version),
210
newX509RequestDELETE(serverRedir.URL+path, version),
212
for _, request := range requests {
213
response, err := performX509Request(session, request)
215
c.Assert(response.StatusCode, Equals, http.StatusConflict)
216
c.Assert(httpRequests, HasLen, 2)
217
c.Assert((<-httpRequests).URL.String(), Equals, path)
218
c.Assert((<-httpRequests).URL.String(), Equals, redirPath)
222
222
func (*x509DispatcherSuite) TestRedirectRewindsBody(c *C) {
223
httpRequests := make(chan *Request, 2)
224
serverConflict := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
225
defer serverConflict.Close()
226
redirPath := "/else/where"
227
responseHeaders := make(http.Header)
228
responseHeaders.Set("Location", serverConflict.URL+redirPath)
229
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, responseHeaders)
230
defer serverRedir.Close()
231
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
234
version := "test-version"
235
content := []byte("ponies")
236
contentType := "text/plain"
223
httpRequests := make(chan *Request, 2)
224
serverConflict := makeRecordingHTTPServer(httpRequests, http.StatusConflict, nil, nil)
225
defer serverConflict.Close()
226
redirPath := "/else/where"
227
responseHeaders := make(http.Header)
228
responseHeaders.Set("Location", serverConflict.URL+redirPath)
229
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, responseHeaders)
230
defer serverRedir.Close()
231
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
234
version := "test-version"
235
content := []byte("ponies")
236
contentType := "text/plain"
238
request := newX509RequestPOST(serverRedir.URL+path, version, content, contentType)
239
response, err := performX509Request(session, request)
241
c.Assert(response.StatusCode, Equals, http.StatusConflict)
242
c.Assert(httpRequests, HasLen, 2)
243
c.Assert((<-httpRequests).BodyContent, DeepEquals, content)
244
c.Assert((<-httpRequests).BodyContent, DeepEquals, content)
238
request := newX509RequestPOST(serverRedir.URL+path, version, content, contentType)
239
response, err := performX509Request(session, request)
241
c.Assert(response.StatusCode, Equals, http.StatusConflict)
242
c.Assert(httpRequests, HasLen, 2)
243
c.Assert((<-httpRequests).BodyContent, DeepEquals, content)
244
c.Assert((<-httpRequests).BodyContent, DeepEquals, content)
247
247
func (*x509DispatcherSuite) TestRequestsLimitRedirects(c *C) {
248
httpRequests := make(chan *Request, 10)
249
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, nil)
250
defer serverRedir.Close()
251
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
254
version := "test-version"
255
request := newX509RequestGET(serverRedir.URL+path, version)
248
httpRequests := make(chan *Request, 10)
249
serverRedir := makeRecordingHTTPServer(httpRequests, http.StatusTemporaryRedirect, nil, nil)
250
defer serverRedir.Close()
251
session, err := newX509Session("subscriptionid", "", "West US", NoRetryPolicy)
254
version := "test-version"
255
request := newX509RequestGET(serverRedir.URL+path, version)
257
response, err := performX509Request(session, request)
258
c.Assert(err, ErrorMatches, "stopped after 10 redirects")
259
c.Assert(response, IsNil)
260
c.Assert(httpRequests, HasLen, 10)
262
for req := range httpRequests {
263
c.Assert(req.URL.String(), Equals, path)
257
response, err := performX509Request(session, request)
258
c.Assert(err, ErrorMatches, "stopped after 10 redirects")
259
c.Assert(response, IsNil)
260
c.Assert(httpRequests, HasLen, 10)
262
for req := range httpRequests {
263
c.Assert(req.URL.String(), Equals, path)