git.iko.soy/typeable/oauth2-proxy
on request-rules help sign in
376 lines 9.0 kB history raw
1package requests
3import (
4 "bytes"
5 "context"
6 "encoding/base64"
7 "encoding/json"
8 "fmt"
9 "net/http"
11 "github.com/bitly/go-simplejson"
12 . "github.com/onsi/ginkgo"
13 . "github.com/onsi/gomega"
16var _ = Describe("Builder suite", func() {
17 var b Builder
18 getBuilder := func() Builder { return b }
20 baseHeaders := http.Header{
21 "Accept-Encoding": []string{"gzip"},
22 "User-Agent": []string{"Go-http-client/1.1"},
23 }
25 BeforeEach(func() {
26 // Most tests will request the server address
27 b = New(serverAddr + "/json/path")
28 })
30 Context("with a basic request", func() {
31 assertSuccessfulRequest(getBuilder, testHTTPRequest{
32 Method: "GET",
33 Header: baseHeaders,
34 Body: []byte{},
35 RequestURI: "/json/path",
36 })
37 })
39 Context("with a context", func() {
40 var ctx context.Context
41 var cancel context.CancelFunc
43 BeforeEach(func() {
44 ctx, cancel = context.WithCancel(context.Background())
45 b = b.WithContext(ctx)
46 })
48 AfterEach(func() {
49 cancel()
50 })
52 assertSuccessfulRequest(getBuilder, testHTTPRequest{
53 Method: "GET",
54 Header: baseHeaders,
55 Body: []byte{},
56 RequestURI: "/json/path",
57 })
59 Context("if the context is cancelled", func() {
60 BeforeEach(func() {
61 cancel()
62 })
64 assertRequestError(getBuilder, "context canceled")
65 })
66 })
68 Context("with a body", func() {
69 const body = "{\"some\": \"body\"}"
70 header := baseHeaders.Clone()
71 header.Set("Content-Length", fmt.Sprintf("%d", len(body)))
73 BeforeEach(func() {
74 buf := bytes.NewBuffer([]byte(body))
75 b = b.WithBody(buf)
76 })
78 assertSuccessfulRequest(getBuilder, testHTTPRequest{
79 Method: "GET",
80 Header: header,
81 Body: []byte(body),
82 RequestURI: "/json/path",
83 })
84 })
86 Context("with a method", func() {
87 Context("POST with a body", func() {
88 const body = "{\"some\": \"body\"}"
89 header := baseHeaders.Clone()
90 header.Set("Content-Length", fmt.Sprintf("%d", len(body)))
92 BeforeEach(func() {
93 buf := bytes.NewBuffer([]byte(body))
94 b = b.WithMethod("POST").WithBody(buf)
95 })
97 assertSuccessfulRequest(getBuilder, testHTTPRequest{
98 Method: "POST",
99 Header: header,
100 Body: []byte(body),
101 RequestURI: "/json/path",
102 })
103 })
105 Context("POST without a body", func() {
106 header := baseHeaders.Clone()
107 header.Set("Content-Length", "0")
109 BeforeEach(func() {
110 b = b.WithMethod("POST")
111 })
113 assertSuccessfulRequest(getBuilder, testHTTPRequest{
114 Method: "POST",
115 Header: header,
116 Body: []byte{},
117 RequestURI: "/json/path",
118 })
119 })
121 Context("OPTIONS", func() {
122 BeforeEach(func() {
123 b = b.WithMethod("OPTIONS")
124 })
126 assertSuccessfulRequest(getBuilder, testHTTPRequest{
127 Method: "OPTIONS",
128 Header: baseHeaders,
129 Body: []byte{},
130 RequestURI: "/json/path",
131 })
132 })
134 Context("INVALID-\\t-METHOD", func() {
135 BeforeEach(func() {
136 b = b.WithMethod("INVALID-\t-METHOD")
137 })
139 assertRequestError(getBuilder, "error creating request: net/http: invalid method \"INVALID-\\t-METHOD\"")
140 })
141 })
143 Context("with headers", func() {
144 Context("setting a header", func() {
145 header := baseHeaders.Clone()
146 header.Set("header", "value")
148 BeforeEach(func() {
149 b = b.SetHeader("header", "value")
150 })
152 assertSuccessfulRequest(getBuilder, testHTTPRequest{
153 Method: "GET",
154 Header: header,
155 Body: []byte{},
156 RequestURI: "/json/path",
157 })
159 Context("then replacing the headers", func() {
160 replacementHeaders := http.Header{
161 "Accept-Encoding": []string{"*"},
162 "User-Agent": []string{"test-agent"},
163 "Foo": []string{"bar, baz"},
164 }
166 BeforeEach(func() {
167 b = b.WithHeaders(replacementHeaders)
168 })
170 assertSuccessfulRequest(getBuilder, testHTTPRequest{
171 Method: "GET",
172 Header: replacementHeaders,
173 Body: []byte{},
174 RequestURI: "/json/path",
175 })
176 })
177 })
179 Context("replacing the header", func() {
180 replacementHeaders := http.Header{
181 "Accept-Encoding": []string{"*"},
182 "User-Agent": []string{"test-agent"},
183 "Foo": []string{"bar, baz"},
184 }
186 BeforeEach(func() {
187 b = b.WithHeaders(replacementHeaders)
188 })
190 assertSuccessfulRequest(getBuilder, testHTTPRequest{
191 Method: "GET",
192 Header: replacementHeaders,
193 Body: []byte{},
194 RequestURI: "/json/path",
195 })
197 Context("then setting a header", func() {
198 header := replacementHeaders.Clone()
199 header.Set("User-Agent", "different-agent")
201 BeforeEach(func() {
202 b = b.SetHeader("User-Agent", "different-agent")
203 })
205 assertSuccessfulRequest(getBuilder, testHTTPRequest{
206 Method: "GET",
207 Header: header,
208 Body: []byte{},
209 RequestURI: "/json/path",
210 })
211 })
212 })
213 })
215 Context("if the request has been completed and then modified", func() {
216 BeforeEach(func() {
217 result := b.Do()
218 Expect(result.Error()).ToNot(HaveOccurred())
220 b.WithMethod("POST")
221 })
223 Context("should not redo the request", func() {
224 assertSuccessfulRequest(getBuilder, testHTTPRequest{
225 Method: "GET",
226 Header: baseHeaders,
227 Body: []byte{},
228 RequestURI: "/json/path",
229 })
230 })
231 })
233 Context("when the requested page is not found", func() {
234 BeforeEach(func() {
235 b = New(serverAddr + "/not-found")
236 })
238 assertJSONError(getBuilder, "404 page not found")
239 })
241 Context("when the requested page is not valid JSON", func() {
242 BeforeEach(func() {
243 b = New(serverAddr + "/string/path")
244 })
246 assertJSONError(getBuilder, "invalid character 'O' looking for beginning of value")
247 })
248})
250func assertSuccessfulRequest(builder func() Builder, expectedRequest testHTTPRequest) {
251 Context("Do", func() {
252 var result Result
254 BeforeEach(func() {
255 result = builder().Do()
256 Expect(result.Error()).ToNot(HaveOccurred())
257 })
259 It("returns a successful status", func() {
260 Expect(result.StatusCode()).To(Equal(http.StatusOK))
261 })
263 It("made the expected request", func() {
264 actualRequest := testHTTPRequest{}
265 Expect(json.Unmarshal(result.Body(), &actualRequest)).To(Succeed())
267 Expect(actualRequest).To(Equal(expectedRequest))
268 })
269 })
271 Context("UnmarshalInto", func() {
272 var actualRequest testHTTPRequest
274 BeforeEach(func() {
275 Expect(builder().Do().UnmarshalInto(&actualRequest)).To(Succeed())
276 })
278 It("made the expected request", func() {
279 Expect(actualRequest).To(Equal(expectedRequest))
280 })
281 })
283 Context("UnmarshalJSON", func() {
284 var response *simplejson.Json
286 BeforeEach(func() {
287 var err error
288 response, err = builder().Do().UnmarshalJSON()
289 Expect(err).ToNot(HaveOccurred())
290 })
292 It("made the expected reqest", func() {
293 header := http.Header{}
294 for key, value := range response.Get("Header").MustMap() {
295 vs, ok := value.([]interface{})
296 Expect(ok).To(BeTrue())
297 svs := []string{}
298 for _, v := range vs {
299 sv, ok := v.(string)
300 Expect(ok).To(BeTrue())
301 svs = append(svs, sv)
302 }
303 header[key] = svs
304 }
306 // Other json unmarhsallers base64 decode byte slices automatically
307 body, err := base64.StdEncoding.DecodeString(response.Get("Body").MustString())
308 Expect(err).ToNot(HaveOccurred())
310 actualRequest := testHTTPRequest{
311 Method: response.Get("Method").MustString(),
312 Header: header,
313 Body: body,
314 RequestURI: response.Get("RequestURI").MustString(),
315 }
317 Expect(actualRequest).To(Equal(expectedRequest))
318 })
319 })
322func assertRequestError(builder func() Builder, errorMessage string) {
323 Context("Do", func() {
324 It("returns an error", func() {
325 result := builder().Do()
326 Expect(result.Error()).To(MatchError(ContainSubstring(errorMessage)))
327 })
328 })
330 Context("UnmarshalInto", func() {
331 It("returns an error", func() {
332 var actualRequest testHTTPRequest
333 err := builder().Do().UnmarshalInto(&actualRequest)
334 Expect(err).To(MatchError(ContainSubstring(errorMessage)))
336 // Should be empty
337 Expect(actualRequest).To(Equal(testHTTPRequest{}))
338 })
339 })
341 Context("UnmarshalJSON", func() {
342 It("returns an error", func() {
343 resp, err := builder().Do().UnmarshalJSON()
344 Expect(err).To(MatchError(ContainSubstring(errorMessage)))
345 Expect(resp).To(BeNil())
346 })
347 })
350func assertJSONError(builder func() Builder, errorMessage string) {
351 Context("Do", func() {
352 It("does not return an error", func() {
353 result := builder().Do()
354 Expect(result.Error()).To(BeNil())
355 })
356 })
358 Context("UnmarshalInto", func() {
359 It("returns an error", func() {
360 var actualRequest testHTTPRequest
361 err := builder().Do().UnmarshalInto(&actualRequest)
362 Expect(err).To(MatchError(ContainSubstring(errorMessage)))
364 // Should be empty
365 Expect(actualRequest).To(Equal(testHTTPRequest{}))
366 })
367 })
369 Context("UnmarshalJSON", func() {
370 It("returns an error", func() {
371 resp, err := builder().Do().UnmarshalJSON()
372 Expect(err).To(MatchError(ContainSubstring(errorMessage)))
373 Expect(resp).To(BeNil())
374 })
375 })