1
2
3
4
5 package gin
6
7 import (
8 "fmt"
9 "net/http"
10 "net/http/httptest"
11 "os"
12 "path/filepath"
13 "testing"
14
15 "github.com/stretchr/testify/assert"
16 )
17
18 type header struct {
19 Key string
20 Value string
21 }
22
23
24 func PerformRequest(r http.Handler, method, path string, headers ...header) *httptest.ResponseRecorder {
25 req := httptest.NewRequest(method, path, nil)
26 for _, h := range headers {
27 req.Header.Add(h.Key, h.Value)
28 }
29 w := httptest.NewRecorder()
30 r.ServeHTTP(w, req)
31 return w
32 }
33
34 func testRouteOK(method string, t *testing.T) {
35 passed := false
36 passedAny := false
37 r := New()
38 r.Any("/test2", func(c *Context) {
39 passedAny = true
40 })
41 r.Handle(method, "/test", func(c *Context) {
42 passed = true
43 })
44
45 w := PerformRequest(r, method, "/test")
46 assert.True(t, passed)
47 assert.Equal(t, http.StatusOK, w.Code)
48
49 PerformRequest(r, method, "/test2")
50 assert.True(t, passedAny)
51 }
52
53
54 func testRouteNotOK(method string, t *testing.T) {
55 passed := false
56 router := New()
57 router.Handle(method, "/test_2", func(c *Context) {
58 passed = true
59 })
60
61 w := PerformRequest(router, method, "/test")
62
63 assert.False(t, passed)
64 assert.Equal(t, http.StatusNotFound, w.Code)
65 }
66
67
68 func testRouteNotOK2(method string, t *testing.T) {
69 passed := false
70 router := New()
71 router.HandleMethodNotAllowed = true
72 var methodRoute string
73 if method == http.MethodPost {
74 methodRoute = http.MethodGet
75 } else {
76 methodRoute = http.MethodPost
77 }
78 router.Handle(methodRoute, "/test", func(c *Context) {
79 passed = true
80 })
81
82 w := PerformRequest(router, method, "/test")
83
84 assert.False(t, passed)
85 assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
86 }
87
88 func TestRouterMethod(t *testing.T) {
89 router := New()
90 router.PUT("/hey2", func(c *Context) {
91 c.String(http.StatusOK, "sup2")
92 })
93
94 router.PUT("/hey", func(c *Context) {
95 c.String(http.StatusOK, "called")
96 })
97
98 router.PUT("/hey3", func(c *Context) {
99 c.String(http.StatusOK, "sup3")
100 })
101
102 w := PerformRequest(router, http.MethodPut, "/hey")
103
104 assert.Equal(t, http.StatusOK, w.Code)
105 assert.Equal(t, "called", w.Body.String())
106 }
107
108 func TestRouterGroupRouteOK(t *testing.T) {
109 testRouteOK(http.MethodGet, t)
110 testRouteOK(http.MethodPost, t)
111 testRouteOK(http.MethodPut, t)
112 testRouteOK(http.MethodPatch, t)
113 testRouteOK(http.MethodHead, t)
114 testRouteOK(http.MethodOptions, t)
115 testRouteOK(http.MethodDelete, t)
116 testRouteOK(http.MethodConnect, t)
117 testRouteOK(http.MethodTrace, t)
118 }
119
120 func TestRouteNotOK(t *testing.T) {
121 testRouteNotOK(http.MethodGet, t)
122 testRouteNotOK(http.MethodPost, t)
123 testRouteNotOK(http.MethodPut, t)
124 testRouteNotOK(http.MethodPatch, t)
125 testRouteNotOK(http.MethodHead, t)
126 testRouteNotOK(http.MethodOptions, t)
127 testRouteNotOK(http.MethodDelete, t)
128 testRouteNotOK(http.MethodConnect, t)
129 testRouteNotOK(http.MethodTrace, t)
130 }
131
132 func TestRouteNotOK2(t *testing.T) {
133 testRouteNotOK2(http.MethodGet, t)
134 testRouteNotOK2(http.MethodPost, t)
135 testRouteNotOK2(http.MethodPut, t)
136 testRouteNotOK2(http.MethodPatch, t)
137 testRouteNotOK2(http.MethodHead, t)
138 testRouteNotOK2(http.MethodOptions, t)
139 testRouteNotOK2(http.MethodDelete, t)
140 testRouteNotOK2(http.MethodConnect, t)
141 testRouteNotOK2(http.MethodTrace, t)
142 }
143
144 func TestRouteRedirectTrailingSlash(t *testing.T) {
145 router := New()
146 router.RedirectFixedPath = false
147 router.RedirectTrailingSlash = true
148 router.GET("/path", func(c *Context) {})
149 router.GET("/path2/", func(c *Context) {})
150 router.POST("/path3", func(c *Context) {})
151 router.PUT("/path4/", func(c *Context) {})
152
153 w := PerformRequest(router, http.MethodGet, "/path/")
154 assert.Equal(t, "/path", w.Header().Get("Location"))
155 assert.Equal(t, http.StatusMovedPermanently, w.Code)
156
157 w = PerformRequest(router, http.MethodGet, "/path2")
158 assert.Equal(t, "/path2/", w.Header().Get("Location"))
159 assert.Equal(t, http.StatusMovedPermanently, w.Code)
160
161 w = PerformRequest(router, http.MethodPost, "/path3/")
162 assert.Equal(t, "/path3", w.Header().Get("Location"))
163 assert.Equal(t, http.StatusTemporaryRedirect, w.Code)
164
165 w = PerformRequest(router, http.MethodPut, "/path4")
166 assert.Equal(t, "/path4/", w.Header().Get("Location"))
167 assert.Equal(t, http.StatusTemporaryRedirect, w.Code)
168
169 w = PerformRequest(router, http.MethodGet, "/path")
170 assert.Equal(t, http.StatusOK, w.Code)
171
172 w = PerformRequest(router, http.MethodGet, "/path2/")
173 assert.Equal(t, http.StatusOK, w.Code)
174
175 w = PerformRequest(router, http.MethodPost, "/path3")
176 assert.Equal(t, http.StatusOK, w.Code)
177
178 w = PerformRequest(router, http.MethodPut, "/path4/")
179 assert.Equal(t, http.StatusOK, w.Code)
180
181 w = PerformRequest(router, http.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "/api"})
182 assert.Equal(t, "/api/path2/", w.Header().Get("Location"))
183 assert.Equal(t, 301, w.Code)
184
185 w = PerformRequest(router, http.MethodGet, "/path2/", header{Key: "X-Forwarded-Prefix", Value: "/api/"})
186 assert.Equal(t, 200, w.Code)
187
188 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "../../api#?"})
189 assert.Equal(t, "/api/path", w.Header().Get("Location"))
190 assert.Equal(t, 301, w.Code)
191
192 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "../../api"})
193 assert.Equal(t, "/api/path", w.Header().Get("Location"))
194 assert.Equal(t, 301, w.Code)
195
196 w = PerformRequest(router, http.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "../../api"})
197 assert.Equal(t, "/api/path2/", w.Header().Get("Location"))
198 assert.Equal(t, 301, w.Code)
199
200 w = PerformRequest(router, http.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "/../../api"})
201 assert.Equal(t, "/api/path2/", w.Header().Get("Location"))
202 assert.Equal(t, 301, w.Code)
203
204 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "api/../../"})
205 assert.Equal(t, "//path", w.Header().Get("Location"))
206 assert.Equal(t, 301, w.Code)
207
208 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "api/../../../"})
209 assert.Equal(t, "/path", w.Header().Get("Location"))
210 assert.Equal(t, 301, w.Code)
211
212 w = PerformRequest(router, http.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "../../gin-gonic.com"})
213 assert.Equal(t, "/gin-goniccom/path2/", w.Header().Get("Location"))
214 assert.Equal(t, 301, w.Code)
215
216 w = PerformRequest(router, http.MethodGet, "/path2", header{Key: "X-Forwarded-Prefix", Value: "/../../gin-gonic.com"})
217 assert.Equal(t, "/gin-goniccom/path2/", w.Header().Get("Location"))
218 assert.Equal(t, 301, w.Code)
219
220 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "https://gin-gonic.com/#"})
221 assert.Equal(t, "https/gin-goniccom/https/gin-goniccom/path", w.Header().Get("Location"))
222 assert.Equal(t, 301, w.Code)
223
224 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "#api"})
225 assert.Equal(t, "api/api/path", w.Header().Get("Location"))
226 assert.Equal(t, 301, w.Code)
227
228 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "/nor-mal/#?a=1"})
229 assert.Equal(t, "/nor-mal/a1/path", w.Header().Get("Location"))
230 assert.Equal(t, 301, w.Code)
231
232 w = PerformRequest(router, http.MethodGet, "/path/", header{Key: "X-Forwarded-Prefix", Value: "/nor-mal/%2e%2e/"})
233 assert.Equal(t, "/nor-mal/2e2e/path", w.Header().Get("Location"))
234 assert.Equal(t, 301, w.Code)
235
236 router.RedirectTrailingSlash = false
237
238 w = PerformRequest(router, http.MethodGet, "/path/")
239 assert.Equal(t, http.StatusNotFound, w.Code)
240 w = PerformRequest(router, http.MethodGet, "/path2")
241 assert.Equal(t, http.StatusNotFound, w.Code)
242 w = PerformRequest(router, http.MethodPost, "/path3/")
243 assert.Equal(t, http.StatusNotFound, w.Code)
244 w = PerformRequest(router, http.MethodPut, "/path4")
245 assert.Equal(t, http.StatusNotFound, w.Code)
246 }
247
248 func TestRouteRedirectFixedPath(t *testing.T) {
249 router := New()
250 router.RedirectFixedPath = true
251 router.RedirectTrailingSlash = false
252
253 router.GET("/path", func(c *Context) {})
254 router.GET("/Path2", func(c *Context) {})
255 router.POST("/PATH3", func(c *Context) {})
256 router.POST("/Path4/", func(c *Context) {})
257
258 w := PerformRequest(router, http.MethodGet, "/PATH")
259 assert.Equal(t, "/path", w.Header().Get("Location"))
260 assert.Equal(t, http.StatusMovedPermanently, w.Code)
261
262 w = PerformRequest(router, http.MethodGet, "/path2")
263 assert.Equal(t, "/Path2", w.Header().Get("Location"))
264 assert.Equal(t, http.StatusMovedPermanently, w.Code)
265
266 w = PerformRequest(router, http.MethodPost, "/path3")
267 assert.Equal(t, "/PATH3", w.Header().Get("Location"))
268 assert.Equal(t, http.StatusTemporaryRedirect, w.Code)
269
270 w = PerformRequest(router, http.MethodPost, "/path4")
271 assert.Equal(t, "/Path4/", w.Header().Get("Location"))
272 assert.Equal(t, http.StatusTemporaryRedirect, w.Code)
273 }
274
275
276 func TestRouteParamsByName(t *testing.T) {
277 name := ""
278 lastName := ""
279 wild := ""
280 router := New()
281 router.GET("/test/:name/:last_name/*wild", func(c *Context) {
282 name = c.Params.ByName("name")
283 lastName = c.Params.ByName("last_name")
284 var ok bool
285 wild, ok = c.Params.Get("wild")
286
287 assert.True(t, ok)
288 assert.Equal(t, name, c.Param("name"))
289 assert.Equal(t, lastName, c.Param("last_name"))
290
291 assert.Empty(t, c.Param("wtf"))
292 assert.Empty(t, c.Params.ByName("wtf"))
293
294 wtf, ok := c.Params.Get("wtf")
295 assert.Empty(t, wtf)
296 assert.False(t, ok)
297 })
298
299 w := PerformRequest(router, http.MethodGet, "/test/john/smith/is/super/great")
300
301 assert.Equal(t, http.StatusOK, w.Code)
302 assert.Equal(t, "john", name)
303 assert.Equal(t, "smith", lastName)
304 assert.Equal(t, "/is/super/great", wild)
305 }
306
307
308 func TestRouteParamsByNameWithExtraSlash(t *testing.T) {
309 name := ""
310 lastName := ""
311 wild := ""
312 router := New()
313 router.RemoveExtraSlash = true
314 router.GET("/test/:name/:last_name/*wild", func(c *Context) {
315 name = c.Params.ByName("name")
316 lastName = c.Params.ByName("last_name")
317 var ok bool
318 wild, ok = c.Params.Get("wild")
319
320 assert.True(t, ok)
321 assert.Equal(t, name, c.Param("name"))
322 assert.Equal(t, lastName, c.Param("last_name"))
323
324 assert.Empty(t, c.Param("wtf"))
325 assert.Empty(t, c.Params.ByName("wtf"))
326
327 wtf, ok := c.Params.Get("wtf")
328 assert.Empty(t, wtf)
329 assert.False(t, ok)
330 })
331
332 w := PerformRequest(router, http.MethodGet, "//test//john//smith//is//super//great")
333
334 assert.Equal(t, http.StatusOK, w.Code)
335 assert.Equal(t, "john", name)
336 assert.Equal(t, "smith", lastName)
337 assert.Equal(t, "/is/super/great", wild)
338 }
339
340
341 func TestRouteStaticFile(t *testing.T) {
342
343 testRoot, _ := os.Getwd()
344 f, err := os.CreateTemp(testRoot, "")
345 if err != nil {
346 t.Error(err)
347 }
348 defer os.Remove(f.Name())
349 _, err = f.WriteString("Gin Web Framework")
350 assert.NoError(t, err)
351 f.Close()
352
353 dir, filename := filepath.Split(f.Name())
354
355
356 router := New()
357 router.Static("/using_static", dir)
358 router.StaticFile("/result", f.Name())
359
360 w := PerformRequest(router, http.MethodGet, "/using_static/"+filename)
361 w2 := PerformRequest(router, http.MethodGet, "/result")
362
363 assert.Equal(t, w, w2)
364 assert.Equal(t, http.StatusOK, w.Code)
365 assert.Equal(t, "Gin Web Framework", w.Body.String())
366 assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
367
368 w3 := PerformRequest(router, http.MethodHead, "/using_static/"+filename)
369 w4 := PerformRequest(router, http.MethodHead, "/result")
370
371 assert.Equal(t, w3, w4)
372 assert.Equal(t, http.StatusOK, w3.Code)
373 }
374
375
376 func TestRouteStaticFileFS(t *testing.T) {
377
378 testRoot, _ := os.Getwd()
379 f, err := os.CreateTemp(testRoot, "")
380 if err != nil {
381 t.Error(err)
382 }
383 defer os.Remove(f.Name())
384 _, err = f.WriteString("Gin Web Framework")
385 assert.NoError(t, err)
386 f.Close()
387
388 dir, filename := filepath.Split(f.Name())
389
390 router := New()
391 router.Static("/using_static", dir)
392 router.StaticFileFS("/result_fs", filename, Dir(dir, false))
393
394 w := PerformRequest(router, http.MethodGet, "/using_static/"+filename)
395 w2 := PerformRequest(router, http.MethodGet, "/result_fs")
396
397 assert.Equal(t, w, w2)
398 assert.Equal(t, http.StatusOK, w.Code)
399 assert.Equal(t, "Gin Web Framework", w.Body.String())
400 assert.Equal(t, "text/plain; charset=utf-8", w.Header().Get("Content-Type"))
401
402 w3 := PerformRequest(router, http.MethodHead, "/using_static/"+filename)
403 w4 := PerformRequest(router, http.MethodHead, "/result_fs")
404
405 assert.Equal(t, w3, w4)
406 assert.Equal(t, http.StatusOK, w3.Code)
407 }
408
409
410 func TestRouteStaticListingDir(t *testing.T) {
411 router := New()
412 router.StaticFS("/", Dir("./", true))
413
414 w := PerformRequest(router, http.MethodGet, "/")
415
416 assert.Equal(t, http.StatusOK, w.Code)
417 assert.Contains(t, w.Body.String(), "gin.go")
418 assert.Equal(t, "text/html; charset=utf-8", w.Header().Get("Content-Type"))
419 }
420
421
422 func TestRouteStaticNoListing(t *testing.T) {
423 router := New()
424 router.Static("/", "./")
425
426 w := PerformRequest(router, http.MethodGet, "/")
427
428 assert.Equal(t, http.StatusNotFound, w.Code)
429 assert.NotContains(t, w.Body.String(), "gin.go")
430 }
431
432 func TestRouterMiddlewareAndStatic(t *testing.T) {
433 router := New()
434 static := router.Group("/", func(c *Context) {
435 c.Writer.Header().Add("Last-Modified", "Mon, 02 Jan 2006 15:04:05 MST")
436 c.Writer.Header().Add("Expires", "Mon, 02 Jan 2006 15:04:05 MST")
437 c.Writer.Header().Add("X-GIN", "Gin Framework")
438 })
439 static.Static("/", "./")
440
441 w := PerformRequest(router, http.MethodGet, "/gin.go")
442
443 assert.Equal(t, http.StatusOK, w.Code)
444 assert.Contains(t, w.Body.String(), "package gin")
445
446
447 assert.NotEqual(t, "", w.Header().Get("Content-Type"))
448 assert.NotEqual(t, w.Header().Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST")
449 assert.Equal(t, "Mon, 02 Jan 2006 15:04:05 MST", w.Header().Get("Expires"))
450 assert.Equal(t, "Gin Framework", w.Header().Get("x-GIN"))
451 }
452
453 func TestRouteNotAllowedEnabled(t *testing.T) {
454 router := New()
455 router.HandleMethodNotAllowed = true
456 router.POST("/path", func(c *Context) {})
457 w := PerformRequest(router, http.MethodGet, "/path")
458 assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
459
460 router.NoMethod(func(c *Context) {
461 c.String(http.StatusTeapot, "responseText")
462 })
463 w = PerformRequest(router, http.MethodGet, "/path")
464 assert.Equal(t, "responseText", w.Body.String())
465 assert.Equal(t, http.StatusTeapot, w.Code)
466 }
467
468 func TestRouteNotAllowedEnabled2(t *testing.T) {
469 router := New()
470 router.HandleMethodNotAllowed = true
471
472 router.addRoute(http.MethodPost, "/", HandlersChain{func(_ *Context) {}})
473 router.GET("/path2", func(c *Context) {})
474 w := PerformRequest(router, http.MethodPost, "/path2")
475 assert.Equal(t, http.StatusMethodNotAllowed, w.Code)
476 }
477
478 func TestRouteNotAllowedDisabled(t *testing.T) {
479 router := New()
480 router.HandleMethodNotAllowed = false
481 router.POST("/path", func(c *Context) {})
482 w := PerformRequest(router, http.MethodGet, "/path")
483 assert.Equal(t, http.StatusNotFound, w.Code)
484
485 router.NoMethod(func(c *Context) {
486 c.String(http.StatusTeapot, "responseText")
487 })
488 w = PerformRequest(router, http.MethodGet, "/path")
489 assert.Equal(t, "404 page not found", w.Body.String())
490 assert.Equal(t, http.StatusNotFound, w.Code)
491 }
492
493 func TestRouterNotFoundWithRemoveExtraSlash(t *testing.T) {
494 router := New()
495 router.RemoveExtraSlash = true
496 router.GET("/path", func(c *Context) {})
497 router.GET("/", func(c *Context) {})
498
499 testRoutes := []struct {
500 route string
501 code int
502 location string
503 }{
504 {"/../path", http.StatusOK, ""},
505 {"/nope", http.StatusNotFound, ""},
506 }
507 for _, tr := range testRoutes {
508 w := PerformRequest(router, "GET", tr.route)
509 assert.Equal(t, tr.code, w.Code)
510 if w.Code != http.StatusNotFound {
511 assert.Equal(t, tr.location, fmt.Sprint(w.Header().Get("Location")))
512 }
513 }
514 }
515
516 func TestRouterNotFound(t *testing.T) {
517 router := New()
518 router.RedirectFixedPath = true
519 router.GET("/path", func(c *Context) {})
520 router.GET("/dir/", func(c *Context) {})
521 router.GET("/", func(c *Context) {})
522
523 testRoutes := []struct {
524 route string
525 code int
526 location string
527 }{
528 {"/path/", http.StatusMovedPermanently, "/path"},
529 {"/dir", http.StatusMovedPermanently, "/dir/"},
530 {"/PATH", http.StatusMovedPermanently, "/path"},
531 {"/DIR/", http.StatusMovedPermanently, "/dir/"},
532 {"/PATH/", http.StatusMovedPermanently, "/path"},
533 {"/DIR", http.StatusMovedPermanently, "/dir/"},
534 {"/../path", http.StatusMovedPermanently, "/path"},
535 {"/nope", http.StatusNotFound, ""},
536 }
537 for _, tr := range testRoutes {
538 w := PerformRequest(router, http.MethodGet, tr.route)
539 assert.Equal(t, tr.code, w.Code)
540 if w.Code != http.StatusNotFound {
541 assert.Equal(t, tr.location, fmt.Sprint(w.Header().Get("Location")))
542 }
543 }
544
545
546 var notFound bool
547 router.NoRoute(func(c *Context) {
548 c.AbortWithStatus(http.StatusNotFound)
549 notFound = true
550 })
551 w := PerformRequest(router, http.MethodGet, "/nope")
552 assert.Equal(t, http.StatusNotFound, w.Code)
553 assert.True(t, notFound)
554
555
556 router.PATCH("/path", func(c *Context) {})
557 w = PerformRequest(router, http.MethodPatch, "/path/")
558 assert.Equal(t, http.StatusTemporaryRedirect, w.Code)
559 assert.Equal(t, "map[Location:[/path]]", fmt.Sprint(w.Header()))
560
561
562 router = New()
563 router.GET("/a", func(c *Context) {})
564 w = PerformRequest(router, http.MethodGet, "/")
565 assert.Equal(t, http.StatusNotFound, w.Code)
566
567
568 router = New()
569 router.NoRoute(func(c *Context) {
570 if c.Request.RequestURI == "/login" {
571 c.String(200, "login")
572 }
573 })
574 router.GET("/logout", func(c *Context) {
575 c.String(200, "logout")
576 })
577 w = PerformRequest(router, http.MethodGet, "/login")
578 assert.Equal(t, "login", w.Body.String())
579 w = PerformRequest(router, http.MethodGet, "/logout")
580 assert.Equal(t, "logout", w.Body.String())
581 }
582
583 func TestRouterStaticFSNotFound(t *testing.T) {
584 router := New()
585 router.StaticFS("/", http.FileSystem(http.Dir("/thisreallydoesntexist/")))
586 router.NoRoute(func(c *Context) {
587 c.String(404, "non existent")
588 })
589
590 w := PerformRequest(router, http.MethodGet, "/nonexistent")
591 assert.Equal(t, "non existent", w.Body.String())
592
593 w = PerformRequest(router, http.MethodHead, "/nonexistent")
594 assert.Equal(t, "non existent", w.Body.String())
595 }
596
597 func TestRouterStaticFSFileNotFound(t *testing.T) {
598 router := New()
599
600 router.StaticFS("/", http.FileSystem(http.Dir(".")))
601
602 assert.NotPanics(t, func() {
603 PerformRequest(router, http.MethodGet, "/nonexistent")
604 })
605 }
606
607
608 func TestMiddlewareCalledOnceByRouterStaticFSNotFound(t *testing.T) {
609 router := New()
610
611
612 middlewareCalledNum := 0
613 router.Use(func(c *Context) {
614 middlewareCalledNum++
615 })
616
617 router.StaticFS("/", http.FileSystem(http.Dir("/thisreallydoesntexist/")))
618
619
620 PerformRequest(router, http.MethodGet, "/nonexistent")
621 assert.Equal(t, 1, middlewareCalledNum)
622
623
624 PerformRequest(router, http.MethodHead, "/nonexistent")
625 assert.Equal(t, 2, middlewareCalledNum)
626 }
627
628 func TestRouteRawPath(t *testing.T) {
629 route := New()
630 route.UseRawPath = true
631
632 route.POST("/project/:name/build/:num", func(c *Context) {
633 name := c.Params.ByName("name")
634 num := c.Params.ByName("num")
635
636 assert.Equal(t, name, c.Param("name"))
637 assert.Equal(t, num, c.Param("num"))
638
639 assert.Equal(t, "Some/Other/Project", name)
640 assert.Equal(t, "222", num)
641 })
642
643 w := PerformRequest(route, http.MethodPost, "/project/Some%2FOther%2FProject/build/222")
644 assert.Equal(t, http.StatusOK, w.Code)
645 }
646
647 func TestRouteRawPathNoUnescape(t *testing.T) {
648 route := New()
649 route.UseRawPath = true
650 route.UnescapePathValues = false
651
652 route.POST("/project/:name/build/:num", func(c *Context) {
653 name := c.Params.ByName("name")
654 num := c.Params.ByName("num")
655
656 assert.Equal(t, name, c.Param("name"))
657 assert.Equal(t, num, c.Param("num"))
658
659 assert.Equal(t, "Some%2FOther%2FProject", name)
660 assert.Equal(t, "333", num)
661 })
662
663 w := PerformRequest(route, http.MethodPost, "/project/Some%2FOther%2FProject/build/333")
664 assert.Equal(t, http.StatusOK, w.Code)
665 }
666
667 func TestRouteServeErrorWithWriteHeader(t *testing.T) {
668 route := New()
669 route.Use(func(c *Context) {
670 c.Status(421)
671 c.Next()
672 })
673
674 w := PerformRequest(route, http.MethodGet, "/NotFound")
675 assert.Equal(t, 421, w.Code)
676 assert.Equal(t, 0, w.Body.Len())
677 }
678
679 func TestRouteContextHoldsFullPath(t *testing.T) {
680 router := New()
681
682
683 routes := []string{
684 "/simple",
685 "/project/:name",
686 "/",
687 "/news/home",
688 "/news",
689 "/simple-two/one",
690 "/simple-two/one-two",
691 "/project/:name/build/*params",
692 "/project/:name/bui",
693 "/user/:id/status",
694 "/user/:id",
695 "/user/:id/profile",
696 }
697
698 for _, route := range routes {
699 actualRoute := route
700 router.GET(route, func(c *Context) {
701
702 assert.Equal(t, actualRoute, c.FullPath())
703 c.AbortWithStatus(http.StatusOK)
704 })
705 }
706
707 for _, route := range routes {
708 w := PerformRequest(router, http.MethodGet, route)
709 assert.Equal(t, http.StatusOK, w.Code)
710 }
711
712
713 router.Use(func(c *Context) {
714
715 assert.Equal(t, "", c.FullPath())
716 })
717
718 w := PerformRequest(router, http.MethodGet, "/not-found")
719 assert.Equal(t, http.StatusNotFound, w.Code)
720 }
721
722 func TestEngineHandleMethodNotAllowedCornerCase(t *testing.T) {
723 r := New()
724 r.HandleMethodNotAllowed = true
725
726 base := r.Group("base")
727 base.GET("/metrics", handlerTest1)
728
729 v1 := base.Group("v1")
730
731 v1.GET("/:id/devices", handlerTest1)
732 v1.GET("/user/:id/groups", handlerTest1)
733
734 v1.GET("/orgs/:id", handlerTest1)
735 v1.DELETE("/orgs/:id", handlerTest1)
736
737 w := PerformRequest(r, "GET", "/base/v1/user/groups")
738 assert.Equal(t, http.StatusNotFound, w.Code)
739 }
740
View as plain text