routes_test.go 7.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261
  1. // Copyright 2014 Manu Martinez-Almeida. All rights reserved.
  2. // Use of this source code is governed by a MIT style
  3. // license that can be found in the LICENSE file.
  4. package gin
  5. import (
  6. "fmt"
  7. "io/ioutil"
  8. "net/http"
  9. "net/http/httptest"
  10. "os"
  11. "path"
  12. "testing"
  13. "github.com/stretchr/testify/assert"
  14. )
  15. func performRequest(r http.Handler, method, path string) *httptest.ResponseRecorder {
  16. req, _ := http.NewRequest(method, path, nil)
  17. w := httptest.NewRecorder()
  18. r.ServeHTTP(w, req)
  19. return w
  20. }
  21. func testRouteOK(method string, t *testing.T) {
  22. passed := false
  23. r := New()
  24. r.Handle(method, "/test", HandlersChain{func(c *Context) {
  25. passed = true
  26. }})
  27. w := performRequest(r, method, "/test")
  28. assert.True(t, passed)
  29. assert.Equal(t, w.Code, http.StatusOK)
  30. }
  31. // TestSingleRouteOK tests that POST route is correctly invoked.
  32. func testRouteNotOK(method string, t *testing.T) {
  33. passed := false
  34. router := New()
  35. router.Handle(method, "/test_2", HandlersChain{func(c *Context) {
  36. passed = true
  37. }})
  38. w := performRequest(router, method, "/test")
  39. assert.False(t, passed)
  40. assert.Equal(t, w.Code, http.StatusNotFound)
  41. }
  42. // TestSingleRouteOK tests that POST route is correctly invoked.
  43. func testRouteNotOK2(method string, t *testing.T) {
  44. passed := false
  45. router := New()
  46. var methodRoute string
  47. if method == "POST" {
  48. methodRoute = "GET"
  49. } else {
  50. methodRoute = "POST"
  51. }
  52. router.Handle(methodRoute, "/test", HandlersChain{func(c *Context) {
  53. passed = true
  54. }})
  55. w := performRequest(router, method, "/test")
  56. assert.False(t, passed)
  57. assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
  58. }
  59. func TestRouterGroupRouteOK(t *testing.T) {
  60. testRouteOK("POST", t)
  61. testRouteOK("DELETE", t)
  62. testRouteOK("PATCH", t)
  63. testRouteOK("PUT", t)
  64. testRouteOK("OPTIONS", t)
  65. testRouteOK("HEAD", t)
  66. }
  67. // TestSingleRouteOK tests that POST route is correctly invoked.
  68. func TestRouteNotOK(t *testing.T) {
  69. testRouteNotOK("POST", t)
  70. testRouteNotOK("DELETE", t)
  71. testRouteNotOK("PATCH", t)
  72. testRouteNotOK("PUT", t)
  73. testRouteNotOK("OPTIONS", t)
  74. testRouteNotOK("HEAD", t)
  75. }
  76. // TestSingleRouteOK tests that POST route is correctly invoked.
  77. func TestRouteNotOK2(t *testing.T) {
  78. testRouteNotOK2("POST", t)
  79. testRouteNotOK2("DELETE", t)
  80. testRouteNotOK2("PATCH", t)
  81. testRouteNotOK2("PUT", t)
  82. testRouteNotOK2("OPTIONS", t)
  83. testRouteNotOK2("HEAD", t)
  84. }
  85. // TestContextParamsGet tests that a parameter can be parsed from the URL.
  86. func TestRouteParamsByName(t *testing.T) {
  87. name := ""
  88. lastName := ""
  89. wild := ""
  90. router := New()
  91. router.GET("/test/:name/:last_name/*wild", func(c *Context) {
  92. name = c.Params.ByName("name")
  93. lastName = c.Params.ByName("last_name")
  94. wild = c.Params.ByName("wild")
  95. assert.Equal(t, name, c.ParamValue("name"))
  96. assert.Equal(t, lastName, c.ParamValue("last_name"))
  97. assert.Equal(t, name, c.DefaultParamValue("name", "nothing"))
  98. assert.Equal(t, lastName, c.DefaultParamValue("last_name", "nothing"))
  99. assert.Equal(t, c.DefaultParamValue("noKey", "default"), "default")
  100. })
  101. w := performRequest(router, "GET", "/test/john/smith/is/super/great")
  102. assert.Equal(t, w.Code, 200)
  103. assert.Equal(t, name, "john")
  104. assert.Equal(t, lastName, "smith")
  105. assert.Equal(t, wild, "/is/super/great")
  106. }
  107. // TestHandleStaticFile - ensure the static file handles properly
  108. func TestRouteStaticFile(t *testing.T) {
  109. // SETUP file
  110. testRoot, _ := os.Getwd()
  111. f, err := ioutil.TempFile(testRoot, "")
  112. if err != nil {
  113. t.Error(err)
  114. }
  115. defer os.Remove(f.Name())
  116. filePath := path.Join("/", path.Base(f.Name()))
  117. f.WriteString("Gin Web Framework")
  118. f.Close()
  119. // SETUP gin
  120. router := New()
  121. router.Static("./", testRoot)
  122. w := performRequest(router, "GET", filePath)
  123. assert.Equal(t, w.Code, 200)
  124. assert.Equal(t, w.Body.String(), "Gin Web Framework")
  125. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
  126. }
  127. // TestHandleStaticDir - ensure the root/sub dir handles properly
  128. func TestRouteStaticDir(t *testing.T) {
  129. router := New()
  130. router.Static("/", "./")
  131. w := performRequest(router, "GET", "/")
  132. assert.Equal(t, w.Code, 200)
  133. assert.Contains(t, w.Body.String(), "gin.go")
  134. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
  135. }
  136. // TestHandleHeadToDir - ensure the root/sub dir handles properly
  137. func TestRouteHeadToDir(t *testing.T) {
  138. router := New()
  139. router.Static("/", "./")
  140. w := performRequest(router, "HEAD", "/")
  141. assert.Equal(t, w.Code, 200)
  142. assert.Contains(t, w.Body.String(), "gin.go")
  143. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
  144. }
  145. func TestRouterMiddlewareAndStatic(t *testing.T) {
  146. router := New()
  147. static := router.Group("/", func(c *Context) {
  148. c.Writer.Header().Add("Last-Modified", "Mon, 02 Jan 2006 15:04:05 MST")
  149. c.Writer.Header().Add("Expires", "Mon, 02 Jan 2006 15:04:05 MST")
  150. c.Writer.Header().Add("X-GIN", "Gin Framework")
  151. })
  152. static.Static("/", "./")
  153. w := performRequest(router, "GET", "/")
  154. assert.Equal(t, w.Code, 200)
  155. assert.Contains(t, w.Body.String(), "gin.go")
  156. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
  157. assert.NotEqual(t, w.HeaderMap.Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST")
  158. assert.Equal(t, w.HeaderMap.Get("Expires"), "Mon, 02 Jan 2006 15:04:05 MST")
  159. assert.Equal(t, w.HeaderMap.Get("x-GIN"), "Gin Framework")
  160. }
  161. func TestRouteNotAllowed(t *testing.T) {
  162. router := New()
  163. router.POST("/path", func(c *Context) {})
  164. w := performRequest(router, "GET", "/path")
  165. assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
  166. router.NoMethod(func(c *Context) {
  167. c.String(http.StatusTeapot, "responseText")
  168. })
  169. w = performRequest(router, "GET", "/path")
  170. assert.Equal(t, w.Body.String(), "responseText")
  171. assert.Equal(t, w.Code, http.StatusTeapot)
  172. }
  173. func TestRouterNotFound(t *testing.T) {
  174. router := New()
  175. router.GET("/path", func(c *Context) {})
  176. router.GET("/dir/", func(c *Context) {})
  177. router.GET("/", func(c *Context) {})
  178. testRoutes := []struct {
  179. route string
  180. code int
  181. header string
  182. }{
  183. {"/path/", 301, "map[Location:[/path]]"}, // TSR -/
  184. {"/dir", 301, "map[Location:[/dir/]]"}, // TSR +/
  185. {"", 301, "map[Location:[/]]"}, // TSR +/
  186. {"/PATH", 301, "map[Location:[/path]]"}, // Fixed Case
  187. {"/DIR/", 301, "map[Location:[/dir/]]"}, // Fixed Case
  188. {"/PATH/", 301, "map[Location:[/path]]"}, // Fixed Case -/
  189. {"/DIR", 301, "map[Location:[/dir/]]"}, // Fixed Case +/
  190. {"/../path", 301, "map[Location:[/path]]"}, // CleanPath
  191. {"/nope", 404, ""}, // NotFound
  192. }
  193. for _, tr := range testRoutes {
  194. w := performRequest(router, "GET", tr.route)
  195. assert.Equal(t, w.Code, tr.code)
  196. if w.Code != 404 {
  197. assert.Equal(t, fmt.Sprint(w.Header()), tr.header)
  198. }
  199. }
  200. // Test custom not found handler
  201. var notFound bool
  202. router.NoRoute(func(c *Context) {
  203. c.AbortWithStatus(404)
  204. notFound = true
  205. })
  206. w := performRequest(router, "GET", "/nope")
  207. assert.Equal(t, w.Code, 404)
  208. assert.True(t, notFound)
  209. // Test other method than GET (want 307 instead of 301)
  210. router.PATCH("/path", func(c *Context) {})
  211. w = performRequest(router, "PATCH", "/path/")
  212. assert.Equal(t, w.Code, 307)
  213. assert.Equal(t, fmt.Sprint(w.Header()), "map[Location:[/path]]")
  214. // Test special case where no node for the prefix "/" exists
  215. router = New()
  216. router.GET("/a", func(c *Context) {})
  217. w = performRequest(router, "GET", "/")
  218. assert.Equal(t, w.Code, 404)
  219. }