1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package middleware
16
17 import (
18 stdcontext "context"
19 "errors"
20 "fmt"
21 "net/http"
22 "net/http/httptest"
23 "strings"
24 "testing"
25
26 apierrors "github.com/go-openapi/errors"
27 "github.com/go-openapi/loads"
28 "github.com/go-openapi/loads/fmts"
29 "github.com/go-openapi/runtime"
30 "github.com/go-openapi/runtime/internal/testing/petstore"
31 "github.com/go-openapi/runtime/middleware/untyped"
32 "github.com/stretchr/testify/assert"
33 "github.com/stretchr/testify/require"
34 )
35
36 type stubBindRequester struct {
37 }
38
39 func (s *stubBindRequester) BindRequest(*http.Request, *MatchedRoute) error {
40 return nil
41 }
42
43 type stubOperationHandler struct {
44 }
45
46 func (s *stubOperationHandler) ParameterModel() interface{} {
47 return nil
48 }
49
50 func (s *stubOperationHandler) Handle(_ interface{}) (interface{}, error) {
51 return map[string]interface{}{}, nil
52 }
53
54 func init() {
55 loads.AddLoader(fmts.YAMLMatcher, fmts.YAMLDoc)
56 }
57
58 func assertAPIError(t *testing.T, wantCode int, err error) {
59 t.Helper()
60
61 require.Error(t, err)
62
63 ce, ok := err.(*apierrors.CompositeError)
64 assert.True(t, ok)
65 assert.NotEmpty(t, ce.Errors)
66
67 ae, ok := ce.Errors[0].(apierrors.Error)
68 assert.True(t, ok)
69 assert.Equal(t, wantCode, int(ae.Code()))
70 }
71
72 func TestContentType_Issue264(t *testing.T) {
73 swspec, err := loads.Spec("../fixtures/bugs/264/swagger.yml")
74 require.NoError(t, err)
75
76 api := untyped.NewAPI(swspec)
77 api.RegisterConsumer(applicationJSON, runtime.JSONConsumer())
78 api.RegisterProducer(applicationJSON, runtime.JSONProducer())
79 api.RegisterOperation("delete", "/key/{id}", new(stubOperationHandler))
80
81 handler := Serve(swspec, api)
82 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodDelete, "/key/1", nil)
83 require.NoError(t, err)
84
85 recorder := httptest.NewRecorder()
86 handler.ServeHTTP(recorder, request)
87 assert.Equal(t, http.StatusOK, recorder.Code)
88 }
89
90 func TestContentType_Issue172(t *testing.T) {
91 swspec, err := loads.Spec("../fixtures/bugs/172/swagger.yml")
92 require.NoError(t, err)
93
94 api := untyped.NewAPI(swspec)
95 api.RegisterConsumer("application/vnd.cia.v1+json", runtime.JSONConsumer())
96 api.RegisterProducer("application/vnd.cia.v1+json", runtime.JSONProducer())
97 api.RegisterOperation("get", "/pets", new(stubOperationHandler))
98
99 handler := Serve(swspec, api)
100 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/pets", nil)
101 require.NoError(t, err)
102
103 request.Header.Add("Accept", "application/json+special")
104 recorder := httptest.NewRecorder()
105 handler.ServeHTTP(recorder, request)
106 assert.Equal(t, http.StatusNotAcceptable, recorder.Code)
107
108
109 request.Header.Add("Accept", applicationJSON)
110 recorder = httptest.NewRecorder()
111 handler.ServeHTTP(recorder, request)
112 assert.Equal(t, http.StatusOK, recorder.Code)
113 }
114
115 func TestContentType_Issue174(t *testing.T) {
116 swspec, err := loads.Spec("../fixtures/bugs/174/swagger.yml")
117 require.NoError(t, err)
118
119 api := untyped.NewAPI(swspec)
120 api.RegisterConsumer(applicationJSON, runtime.JSONConsumer())
121 api.RegisterProducer(applicationJSON, runtime.JSONProducer())
122 api.RegisterOperation("get", "/pets", new(stubOperationHandler))
123
124 handler := Serve(swspec, api)
125 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/pets", nil)
126 require.NoError(t, err)
127
128 recorder := httptest.NewRecorder()
129 handler.ServeHTTP(recorder, request)
130 assert.Equal(t, http.StatusOK, recorder.Code)
131 }
132
133 const (
134 testHost = "https://localhost:8080"
135
136
137 defaultSpecPath = "/swagger.json"
138 defaultSpecURL = testHost + defaultSpecPath
139
140 defaultUIURL = testHost + "/api/docs"
141 )
142
143 func TestServe(t *testing.T) {
144 spec, api := petstore.NewAPI(t)
145 handler := Serve(spec, api)
146
147 t.Run("serve spec document", func(t *testing.T) {
148 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultSpecURL, nil)
149 require.NoError(t, err)
150
151 request.Header.Add("Content-Type", runtime.JSONMime)
152 request.Header.Add("Accept", runtime.JSONMime)
153 recorder := httptest.NewRecorder()
154
155 handler.ServeHTTP(recorder, request)
156 assert.Equal(t, http.StatusOK, recorder.Code)
157 })
158
159 t.Run("should not find UI there", func(t *testing.T) {
160 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, testHost+"/swagger-ui", nil)
161 require.NoError(t, err)
162 recorder := httptest.NewRecorder()
163
164 handler.ServeHTTP(recorder, request)
165 assert.Equal(t, http.StatusNotFound, recorder.Code)
166 })
167
168 t.Run("should find UI here", func(t *testing.T) {
169 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultUIURL, nil)
170 require.NoError(t, err)
171 recorder := httptest.NewRecorder()
172
173 handler.ServeHTTP(recorder, request)
174 assert.Equal(t, http.StatusOK, recorder.Code)
175
176 htmlResponse := recorder.Body.String()
177 assert.Containsf(t, htmlResponse, "<title>Swagger Petstore</title>", "should default to the API's title")
178 assert.Containsf(t, htmlResponse, "<redoc", "should default to Redoc UI")
179 assert.Containsf(t, htmlResponse, "spec-url='/swagger.json'>", "should default to /swagger.json spec document")
180 })
181 }
182
183 func TestServeWithUIs(t *testing.T) {
184 spec, api := petstore.NewAPI(t)
185 ctx := NewContext(spec, api, nil)
186
187 const (
188 alternateSpecURL = testHost + "/specs/petstore.json"
189 alternateSpecPath = "/specs/petstore.json"
190 alternateUIURL = testHost + "/ui/docs"
191 )
192
193 uiOpts := []UIOption{
194 WithUIBasePath("ui"),
195 WithUIPath("docs"),
196 WithUISpecURL("/specs/petstore.json"),
197 }
198
199 t.Run("with APIHandler", func(t *testing.T) {
200 t.Run("with defaults", func(t *testing.T) {
201 handler := ctx.APIHandler(nil)
202
203 t.Run("should find UI", func(t *testing.T) {
204 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultUIURL, nil)
205 require.NoError(t, err)
206 recorder := httptest.NewRecorder()
207
208 handler.ServeHTTP(recorder, request)
209 assert.Equal(t, http.StatusOK, recorder.Code)
210
211 htmlResponse := recorder.Body.String()
212 assert.Containsf(t, htmlResponse, "<redoc", "should default to Redoc UI")
213 })
214
215 t.Run("should find spec", func(t *testing.T) {
216 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultSpecURL, nil)
217 require.NoError(t, err)
218 recorder := httptest.NewRecorder()
219
220 handler.ServeHTTP(recorder, request)
221 assert.Equal(t, http.StatusOK, recorder.Code)
222 })
223 })
224
225 t.Run("with options", func(t *testing.T) {
226 handler := ctx.APIHandler(nil, uiOpts...)
227
228 t.Run("should find UI", func(t *testing.T) {
229 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateUIURL, nil)
230 require.NoError(t, err)
231 recorder := httptest.NewRecorder()
232
233 handler.ServeHTTP(recorder, request)
234 assert.Equal(t, http.StatusOK, recorder.Code)
235
236 htmlResponse := recorder.Body.String()
237 assert.Contains(t, htmlResponse, fmt.Sprintf("<redoc spec-url='%s'></redoc>", alternateSpecPath))
238 })
239
240 t.Run("should find spec", func(t *testing.T) {
241 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateSpecURL, nil)
242 require.NoError(t, err)
243 recorder := httptest.NewRecorder()
244
245 handler.ServeHTTP(recorder, request)
246 assert.Equal(t, http.StatusOK, recorder.Code)
247 })
248 })
249 })
250
251 t.Run("with APIHandlerSwaggerUI", func(t *testing.T) {
252 t.Run("with defaults", func(t *testing.T) {
253 handler := ctx.APIHandlerSwaggerUI(nil)
254
255 t.Run("should find UI", func(t *testing.T) {
256 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultUIURL, nil)
257 require.NoError(t, err)
258 recorder := httptest.NewRecorder()
259
260 handler.ServeHTTP(recorder, request)
261 assert.Equal(t, http.StatusOK, recorder.Code)
262
263 htmlResponse := recorder.Body.String()
264 assert.Contains(t, htmlResponse, fmt.Sprintf(`url: '%s',`, strings.ReplaceAll(defaultSpecPath, `/`, `\/`)))
265 })
266
267 t.Run("should find spec", func(t *testing.T) {
268 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultSpecURL, nil)
269 require.NoError(t, err)
270 recorder := httptest.NewRecorder()
271
272 handler.ServeHTTP(recorder, request)
273 assert.Equal(t, http.StatusOK, recorder.Code)
274 })
275 })
276
277 t.Run("with options", func(t *testing.T) {
278 handler := ctx.APIHandlerSwaggerUI(nil, uiOpts...)
279
280 t.Run("should find UI", func(t *testing.T) {
281 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateUIURL, nil)
282 require.NoError(t, err)
283 recorder := httptest.NewRecorder()
284
285 handler.ServeHTTP(recorder, request)
286 assert.Equal(t, http.StatusOK, recorder.Code)
287
288 htmlResponse := recorder.Body.String()
289 assert.Contains(t, htmlResponse, fmt.Sprintf(`url: '%s',`, strings.ReplaceAll(alternateSpecPath, `/`, `\/`)))
290 })
291
292 t.Run("should find spec", func(t *testing.T) {
293 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateSpecURL, nil)
294 require.NoError(t, err)
295 recorder := httptest.NewRecorder()
296
297 handler.ServeHTTP(recorder, request)
298 assert.Equal(t, http.StatusOK, recorder.Code)
299 })
300 })
301 })
302
303 t.Run("with APIHandlerRapiDoc", func(t *testing.T) {
304 t.Run("with defaults", func(t *testing.T) {
305 handler := ctx.APIHandlerRapiDoc(nil)
306
307 t.Run("should find UI", func(t *testing.T) {
308 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultUIURL, nil)
309 require.NoError(t, err)
310 recorder := httptest.NewRecorder()
311
312 handler.ServeHTTP(recorder, request)
313 assert.Equal(t, http.StatusOK, recorder.Code)
314
315 htmlResponse := recorder.Body.String()
316 assert.Contains(t, htmlResponse, fmt.Sprintf("<rapi-doc spec-url=%q></rapi-doc>", defaultSpecPath))
317 })
318
319 t.Run("should find spec", func(t *testing.T) {
320 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, defaultSpecURL, nil)
321 require.NoError(t, err)
322 recorder := httptest.NewRecorder()
323
324 handler.ServeHTTP(recorder, request)
325 assert.Equal(t, http.StatusOK, recorder.Code)
326 })
327 })
328
329 t.Run("with options", func(t *testing.T) {
330 handler := ctx.APIHandlerRapiDoc(nil, uiOpts...)
331
332 t.Run("should find UI", func(t *testing.T) {
333 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateUIURL, nil)
334 require.NoError(t, err)
335 recorder := httptest.NewRecorder()
336
337 handler.ServeHTTP(recorder, request)
338 assert.Equal(t, http.StatusOK, recorder.Code)
339
340 htmlResponse := recorder.Body.String()
341 assert.Contains(t, htmlResponse, fmt.Sprintf("<rapi-doc spec-url=%q></rapi-doc>", alternateSpecPath))
342 })
343 t.Run("should find spec", func(t *testing.T) {
344 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, alternateSpecURL, nil)
345 require.NoError(t, err)
346 recorder := httptest.NewRecorder()
347
348 handler.ServeHTTP(recorder, request)
349 assert.Equal(t, http.StatusOK, recorder.Code)
350 })
351 })
352 })
353 }
354
355 func TestContextAuthorize(t *testing.T) {
356 spec, api := petstore.NewAPI(t)
357 ctx := NewContext(spec, api, nil)
358 ctx.router = DefaultRouter(spec, ctx.api)
359
360 request, err := runtime.JSONRequest(http.MethodGet, "/api/pets", nil)
361 require.NoError(t, err)
362 request = request.WithContext(stdcontext.Background())
363
364 ri, reqWithCtx, ok := ctx.RouteInfo(request)
365 assert.True(t, ok)
366 require.NotNil(t, reqWithCtx)
367
368 request = reqWithCtx
369
370 p, reqWithCtx, err := ctx.Authorize(request, ri)
371 require.Error(t, err)
372 assert.Nil(t, p)
373 assert.Nil(t, reqWithCtx)
374
375 v := request.Context().Value(ctxSecurityPrincipal)
376 assert.Nil(t, v)
377
378 request.SetBasicAuth("wrong", "wrong")
379 p, reqWithCtx, err = ctx.Authorize(request, ri)
380 require.Error(t, err)
381 assert.Nil(t, p)
382 assert.Nil(t, reqWithCtx)
383
384 v = request.Context().Value(ctxSecurityPrincipal)
385 assert.Nil(t, v)
386
387 request.SetBasicAuth("admin", "admin")
388 p, reqWithCtx, err = ctx.Authorize(request, ri)
389 require.NoError(t, err)
390 assert.Equal(t, "admin", p)
391 require.NotNil(t, reqWithCtx)
392
393
394 request = reqWithCtx
395
396 v, ok = request.Context().Value(ctxSecurityPrincipal).(string)
397 assert.True(t, ok)
398 assert.Equal(t, "admin", v)
399
400
401
402 request.SetBasicAuth("doesn't matter", "doesn't")
403 pp, reqCtx, rr := ctx.Authorize(request, ri)
404 assert.Equal(t, p, pp)
405 assert.Equal(t, err, rr)
406 assert.Equal(t, request, reqCtx)
407 }
408
409 func TestContextAuthorize_WithAuthorizer(t *testing.T) {
410 spec, api := petstore.NewAPI(t)
411 ctx := NewContext(spec, api, nil)
412 ctx.router = DefaultRouter(spec, ctx.api)
413
414 request, err := runtime.JSONRequest(http.MethodPost, "/api/pets", nil)
415 require.NoError(t, err)
416 request = request.WithContext(stdcontext.Background())
417
418 ri, reqWithCtx, ok := ctx.RouteInfo(request)
419 assert.True(t, ok)
420 require.NotNil(t, reqWithCtx)
421
422 request = reqWithCtx
423
424 request.SetBasicAuth("topuser", "topuser")
425 p, reqWithCtx, err := ctx.Authorize(request, ri)
426 assertAPIError(t, apierrors.InvalidTypeCode, err)
427 assert.Nil(t, p)
428 assert.Nil(t, reqWithCtx)
429
430 request.SetBasicAuth("admin", "admin")
431 p, reqWithCtx, err = ctx.Authorize(request, ri)
432 require.NoError(t, err)
433 assert.Equal(t, "admin", p)
434 require.NotNil(t, reqWithCtx)
435
436 request.SetBasicAuth("anyother", "anyother")
437 p, reqWithCtx, err = ctx.Authorize(request, ri)
438 require.Error(t, err)
439 ae, ok := err.(apierrors.Error)
440 assert.True(t, ok)
441 assert.Equal(t, http.StatusForbidden, int(ae.Code()))
442 assert.Nil(t, p)
443 assert.Nil(t, reqWithCtx)
444 }
445
446 func TestContextNegotiateContentType(t *testing.T) {
447 spec, api := petstore.NewAPI(t)
448 ctx := NewContext(spec, api, nil)
449 ctx.router = DefaultRouter(spec, ctx.api)
450
451 request, _ := http.NewRequestWithContext(stdcontext.Background(), http.MethodPost, "/api/pets", nil)
452
453 request.Header.Add("content-type", "text/html")
454
455 v := request.Context().Value(ctxBoundParams)
456 assert.Nil(t, v)
457
458 ri, request, _ := ctx.RouteInfo(request)
459
460 res := NegotiateContentType(request, ri.Produces, "text/plain")
461 assert.Equal(t, ri.Produces[0], res)
462 }
463
464 func TestContextBindValidRequest(t *testing.T) {
465 spec, api := petstore.NewAPI(t)
466 ctx := NewContext(spec, api, nil)
467 ctx.router = DefaultRouter(spec, ctx.api)
468
469
470 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodPost, "/api/pets", strings.NewReader(`{"name":"dog"}`))
471 require.NoError(t, err)
472 request.Header.Add("content-type", "/json")
473
474 ri, request, _ := ctx.RouteInfo(request)
475 assertAPIError(t, 400, ctx.BindValidRequest(request, ri, new(stubBindRequester)))
476
477
478 request, err = http.NewRequestWithContext(stdcontext.Background(), http.MethodPost, "/api/pets", strings.NewReader(`{"name":"dog"}`))
479 require.NoError(t, err)
480 request.Header.Add("content-type", "text/html")
481
482 ri, request, _ = ctx.RouteInfo(request)
483 assertAPIError(t, http.StatusUnsupportedMediaType, ctx.BindValidRequest(request, ri, new(stubBindRequester)))
484
485
486 request, err = http.NewRequestWithContext(stdcontext.Background(), http.MethodPost, "/api/pets", nil)
487 require.NoError(t, err)
488 request.Header.Add("Accept", "application/vnd.cia.v1+json")
489 request.Header.Add("content-type", applicationJSON)
490
491 ri, request, _ = ctx.RouteInfo(request)
492 assertAPIError(t, http.StatusNotAcceptable, ctx.BindValidRequest(request, ri, new(stubBindRequester)))
493 }
494
495 func TestContextBindValidRequest_Issue174(t *testing.T) {
496 spec, err := loads.Spec("../fixtures/bugs/174/swagger.yml")
497 require.NoError(t, err)
498
499 api := untyped.NewAPI(spec)
500 api.RegisterConsumer(applicationJSON, runtime.JSONConsumer())
501 api.RegisterProducer(applicationJSON, runtime.JSONProducer())
502 api.RegisterOperation("get", "/pets", new(stubOperationHandler))
503
504 ctx := NewContext(spec, api, nil)
505 ctx.router = DefaultRouter(spec, ctx.api)
506
507 request, _ := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/pets", nil)
508 ri, request, _ := ctx.RouteInfo(request)
509 require.NoError(t, ctx.BindValidRequest(request, ri, new(stubBindRequester)))
510 }
511
512 func TestContextBindAndValidate(t *testing.T) {
513 spec, api := petstore.NewAPI(t)
514 ctx := NewContext(spec, api, nil)
515 ctx.router = DefaultRouter(spec, ctx.api)
516
517 request, _ := http.NewRequestWithContext(stdcontext.Background(), http.MethodPost, "/api/pets", nil)
518 request.Header.Add("Accept", "*/*")
519 request.Header.Add("content-type", "text/html")
520 request.ContentLength = 1
521
522 v := request.Context().Value(ctxBoundParams)
523 assert.Nil(t, v)
524
525 ri, request, _ := ctx.RouteInfo(request)
526 data, request, result := ctx.BindAndValidate(request, ri)
527 assert.NotNil(t, data)
528 require.Error(t, result)
529
530 v, ok := request.Context().Value(ctxBoundParams).(*validation)
531 assert.True(t, ok)
532 assert.NotNil(t, v)
533
534 dd, rCtx, rr := ctx.BindAndValidate(request, ri)
535 assert.Equal(t, data, dd)
536 assert.Equal(t, result, rr)
537 assert.Equal(t, rCtx, request)
538 }
539
540 func TestContextRender(t *testing.T) {
541 ct := runtime.JSONMime
542 spec, api := petstore.NewAPI(t)
543 assert.NotNil(t, spec)
544 assert.NotNil(t, api)
545
546 ctx := NewContext(spec, api, nil)
547 ctx.router = DefaultRouter(spec, ctx.api)
548
549 request, _ := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/api/pets", nil)
550 request.Header.Set(runtime.HeaderAccept, ct)
551 ri, request, _ := ctx.RouteInfo(request)
552
553 recorder := httptest.NewRecorder()
554 ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"})
555 assert.Equal(t, http.StatusOK, recorder.Code)
556 assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String())
557
558 recorder = httptest.NewRecorder()
559 ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong"))
560 assert.Equal(t, 500, recorder.Code)
561
562
563
564
565
566 recorder = httptest.NewRecorder()
567 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/api/pets", nil)
568 require.NoError(t, err)
569 request.Header.Set(runtime.HeaderAccept, "text/xml")
570 assert.Panics(t, func() { ctx.Respond(recorder, request, []string{}, nil, map[string]interface{}{"name": "hello"}) })
571
572 request, err = http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/api/pets", nil)
573 require.NoError(t, err)
574 request.Header.Set(runtime.HeaderAccept, ct)
575 ri, request, _ = ctx.RouteInfo(request)
576
577 recorder = httptest.NewRecorder()
578 ctx.Respond(recorder, request, []string{ct}, ri, map[string]interface{}{"name": "hello"})
579 assert.Equal(t, http.StatusOK, recorder.Code)
580 assert.Equal(t, "{\"name\":\"hello\"}\n", recorder.Body.String())
581
582 recorder = httptest.NewRecorder()
583 ctx.Respond(recorder, request, []string{ct}, ri, errors.New("this went wrong"))
584 assert.Equal(t, 500, recorder.Code)
585
586
587
588
589
590
591
592
593 recorder = httptest.NewRecorder()
594 request, err = http.NewRequestWithContext(stdcontext.Background(), http.MethodDelete, "/api/pets/1", nil)
595 require.NoError(t, err)
596 ri, request, _ = ctx.RouteInfo(request)
597 ctx.Respond(recorder, request, ri.Produces, ri, nil)
598 assert.Equal(t, 204, recorder.Code)
599 }
600
601 func TestContextValidResponseFormat(t *testing.T) {
602 const ct = applicationJSON
603 spec, api := petstore.NewAPI(t)
604 ctx := NewContext(spec, api, nil)
605 ctx.router = DefaultRouter(spec, ctx.api)
606
607 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "http://localhost:8080", nil)
608 require.NoError(t, err)
609 request.Header.Set(runtime.HeaderAccept, ct)
610
611
612 cached, ok := request.Context().Value(ctxResponseFormat).(string)
613 assert.False(t, ok)
614 assert.Empty(t, cached)
615
616
617 mt, request := ctx.ResponseFormat(request, []string{ct})
618 assert.Equal(t, ct, mt)
619
620
621 cached, ok = request.Context().Value(ctxResponseFormat).(string)
622 assert.True(t, ok)
623 assert.Equal(t, ct, cached)
624
625
626 mt, _ = ctx.ResponseFormat(request, []string{ct})
627 assert.Equal(t, ct, mt)
628 }
629
630 func TestContextInvalidResponseFormat(t *testing.T) {
631 ct := "application/x-yaml"
632 other := "application/sgml"
633 spec, api := petstore.NewAPI(t)
634 ctx := NewContext(spec, api, nil)
635 ctx.router = DefaultRouter(spec, ctx.api)
636
637 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "http://localhost:8080", nil)
638 require.NoError(t, err)
639 request.Header.Set(runtime.HeaderAccept, ct)
640
641
642 cached, ok := request.Context().Value(ctxResponseFormat).(string)
643 assert.False(t, ok)
644 assert.Empty(t, cached)
645
646
647 mt, request := ctx.ResponseFormat(request, []string{other})
648 assert.Empty(t, mt)
649
650
651 cached, ok = request.Context().Value(ctxResponseFormat).(string)
652 assert.False(t, ok)
653 assert.Empty(t, cached)
654
655
656 mt, rCtx := ctx.ResponseFormat(request, []string{other})
657 assert.Empty(t, mt)
658 assert.Equal(t, request, rCtx)
659 }
660
661 func TestContextValidRoute(t *testing.T) {
662 spec, api := petstore.NewAPI(t)
663 ctx := NewContext(spec, api, nil)
664 ctx.router = DefaultRouter(spec, ctx.api)
665
666 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "/api/pets", nil)
667 require.NoError(t, err)
668
669
670 cached := request.Context().Value(ctxMatchedRoute)
671 assert.Nil(t, cached)
672
673 matched, rCtx, ok := ctx.RouteInfo(request)
674 assert.True(t, ok)
675 assert.NotNil(t, matched)
676 assert.NotNil(t, rCtx)
677 assert.NotEqual(t, request, rCtx)
678
679 request = rCtx
680
681
682 _, ok = request.Context().Value(ctxMatchedRoute).(*MatchedRoute)
683 assert.True(t, ok)
684
685 matched, rCtx, ok = ctx.RouteInfo(request)
686 assert.True(t, ok)
687 assert.NotNil(t, matched)
688 assert.Equal(t, request, rCtx)
689 }
690
691 func TestContextInvalidRoute(t *testing.T) {
692 spec, api := petstore.NewAPI(t)
693 ctx := NewContext(spec, api, nil)
694 ctx.router = DefaultRouter(spec, ctx.api)
695
696 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodDelete, "pets", nil)
697 require.NoError(t, err)
698
699
700 cached := request.Context().Value(ctxMatchedRoute)
701 assert.Nil(t, cached)
702
703 matched, rCtx, ok := ctx.RouteInfo(request)
704 assert.False(t, ok)
705 assert.Nil(t, matched)
706 assert.Nil(t, rCtx)
707
708
709 cached = request.Context().Value(ctxMatchedRoute)
710 assert.Nil(t, cached)
711
712 matched, rCtx, ok = ctx.RouteInfo(request)
713 assert.False(t, ok)
714 assert.Nil(t, matched)
715 assert.Nil(t, rCtx)
716 }
717
718 func TestContextValidContentType(t *testing.T) {
719 ct := applicationJSON
720 ctx := NewContext(nil, nil, nil)
721
722 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "http://localhost:8080", nil)
723 require.NoError(t, err)
724 request.Header.Set(runtime.HeaderContentType, ct)
725
726
727 cached := request.Context().Value(ctxContentType)
728 assert.Nil(t, cached)
729
730
731 mt, _, rCtx, err := ctx.ContentType(request)
732 require.NoError(t, err)
733 assert.Equal(t, ct, mt)
734 assert.NotNil(t, rCtx)
735 assert.NotEqual(t, request, rCtx)
736
737 request = rCtx
738
739
740 cached = request.Context().Value(ctxContentType)
741 assert.NotNil(t, cached)
742
743
744 mt, _, rCtx, err = ctx.ContentType(request)
745 require.NoError(t, err)
746 assert.Equal(t, ct, mt)
747 assert.Equal(t, request, rCtx)
748 }
749
750 func TestContextInvalidContentType(t *testing.T) {
751 ct := "application("
752 ctx := NewContext(nil, nil, nil)
753
754 request, err := http.NewRequestWithContext(stdcontext.Background(), http.MethodGet, "http://localhost:8080", nil)
755 require.NoError(t, err)
756 request.Header.Set(runtime.HeaderContentType, ct)
757
758
759 cached := request.Context().Value(ctxContentType)
760 assert.Nil(t, cached)
761
762
763 mt, _, rCtx, err := ctx.ContentType(request)
764 require.Error(t, err)
765 assert.Empty(t, mt)
766 assert.Nil(t, rCtx)
767
768
769 cached = request.Context().Value(ctxContentType)
770 assert.Nil(t, cached)
771
772
773 _, _, rCtx, err = ctx.ContentType(request)
774 require.Error(t, err)
775 assert.Nil(t, rCtx)
776 }
777
View as plain text