routes_test.go 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441
  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/filepath"
  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. passedAny := false
  24. r := New()
  25. r.Any("/test2", func(c *Context) {
  26. passedAny = true
  27. })
  28. r.Handle(method, "/test", func(c *Context) {
  29. passed = true
  30. })
  31. w := performRequest(r, method, "/test")
  32. assert.True(t, passed)
  33. assert.Equal(t, w.Code, http.StatusOK)
  34. performRequest(r, method, "/test2")
  35. assert.True(t, passedAny)
  36. }
  37. // TestSingleRouteOK tests that POST route is correctly invoked.
  38. func testRouteNotOK(method string, t *testing.T) {
  39. passed := false
  40. router := New()
  41. router.Handle(method, "/test_2", func(c *Context) {
  42. passed = true
  43. })
  44. w := performRequest(router, method, "/test")
  45. assert.False(t, passed)
  46. assert.Equal(t, w.Code, http.StatusNotFound)
  47. }
  48. // TestSingleRouteOK tests that POST route is correctly invoked.
  49. func testRouteNotOK2(method string, t *testing.T) {
  50. passed := false
  51. router := New()
  52. router.HandleMethodNotAllowed = true
  53. var methodRoute string
  54. if method == "POST" {
  55. methodRoute = "GET"
  56. } else {
  57. methodRoute = "POST"
  58. }
  59. router.Handle(methodRoute, "/test", func(c *Context) {
  60. passed = true
  61. })
  62. w := performRequest(router, method, "/test")
  63. assert.False(t, passed)
  64. assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
  65. }
  66. func TestRouterMethod(t *testing.T) {
  67. router := New()
  68. router.PUT("/hey2", func(c *Context) {
  69. c.String(200, "sup2")
  70. })
  71. router.PUT("/hey", func(c *Context) {
  72. c.String(200, "called")
  73. })
  74. router.PUT("/hey3", func(c *Context) {
  75. c.String(200, "sup3")
  76. })
  77. w := performRequest(router, "PUT", "/hey")
  78. assert.Equal(t, w.Code, 200)
  79. assert.Equal(t, w.Body.String(), "called")
  80. }
  81. func TestRouterGroupRouteOK(t *testing.T) {
  82. testRouteOK("GET", t)
  83. testRouteOK("POST", t)
  84. testRouteOK("PUT", t)
  85. testRouteOK("PATCH", t)
  86. testRouteOK("HEAD", t)
  87. testRouteOK("OPTIONS", t)
  88. testRouteOK("DELETE", t)
  89. testRouteOK("CONNECT", t)
  90. testRouteOK("TRACE", t)
  91. }
  92. func TestRouteNotOK(t *testing.T) {
  93. testRouteNotOK("GET", t)
  94. testRouteNotOK("POST", t)
  95. testRouteNotOK("PUT", t)
  96. testRouteNotOK("PATCH", t)
  97. testRouteNotOK("HEAD", t)
  98. testRouteNotOK("OPTIONS", t)
  99. testRouteNotOK("DELETE", t)
  100. testRouteNotOK("CONNECT", t)
  101. testRouteNotOK("TRACE", t)
  102. }
  103. func TestRouteNotOK2(t *testing.T) {
  104. testRouteNotOK2("GET", t)
  105. testRouteNotOK2("POST", t)
  106. testRouteNotOK2("PUT", t)
  107. testRouteNotOK2("PATCH", t)
  108. testRouteNotOK2("HEAD", t)
  109. testRouteNotOK2("OPTIONS", t)
  110. testRouteNotOK2("DELETE", t)
  111. testRouteNotOK2("CONNECT", t)
  112. testRouteNotOK2("TRACE", t)
  113. }
  114. func TestRouteRedirectTrailingSlash(t *testing.T) {
  115. router := New()
  116. router.RedirectFixedPath = false
  117. router.RedirectTrailingSlash = true
  118. router.GET("/path", func(c *Context) {})
  119. router.GET("/path2/", func(c *Context) {})
  120. router.POST("/path3", func(c *Context) {})
  121. router.PUT("/path4/", func(c *Context) {})
  122. w := performRequest(router, "GET", "/path/")
  123. assert.Equal(t, w.Header().Get("Location"), "/path")
  124. assert.Equal(t, w.Code, 301)
  125. w = performRequest(router, "GET", "/path2")
  126. assert.Equal(t, w.Header().Get("Location"), "/path2/")
  127. assert.Equal(t, w.Code, 301)
  128. w = performRequest(router, "POST", "/path3/")
  129. assert.Equal(t, w.Header().Get("Location"), "/path3")
  130. assert.Equal(t, w.Code, 307)
  131. w = performRequest(router, "PUT", "/path4")
  132. assert.Equal(t, w.Header().Get("Location"), "/path4/")
  133. assert.Equal(t, w.Code, 307)
  134. w = performRequest(router, "GET", "/path")
  135. assert.Equal(t, w.Code, 200)
  136. w = performRequest(router, "GET", "/path2/")
  137. assert.Equal(t, w.Code, 200)
  138. w = performRequest(router, "POST", "/path3")
  139. assert.Equal(t, w.Code, 200)
  140. w = performRequest(router, "PUT", "/path4/")
  141. assert.Equal(t, w.Code, 200)
  142. router.RedirectTrailingSlash = false
  143. w = performRequest(router, "GET", "/path/")
  144. assert.Equal(t, w.Code, 404)
  145. w = performRequest(router, "GET", "/path2")
  146. assert.Equal(t, w.Code, 404)
  147. w = performRequest(router, "POST", "/path3/")
  148. assert.Equal(t, w.Code, 404)
  149. w = performRequest(router, "PUT", "/path4")
  150. assert.Equal(t, w.Code, 404)
  151. }
  152. func TestRouteRedirectFixedPath(t *testing.T) {
  153. router := New()
  154. router.RedirectFixedPath = true
  155. router.RedirectTrailingSlash = false
  156. router.GET("/path", func(c *Context) {})
  157. router.GET("/Path2", func(c *Context) {})
  158. router.POST("/PATH3", func(c *Context) {})
  159. router.POST("/Path4/", func(c *Context) {})
  160. w := performRequest(router, "GET", "/PATH")
  161. assert.Equal(t, w.Header().Get("Location"), "/path")
  162. assert.Equal(t, w.Code, 301)
  163. w = performRequest(router, "GET", "/path2")
  164. assert.Equal(t, w.Header().Get("Location"), "/Path2")
  165. assert.Equal(t, w.Code, 301)
  166. w = performRequest(router, "POST", "/path3")
  167. assert.Equal(t, w.Header().Get("Location"), "/PATH3")
  168. assert.Equal(t, w.Code, 307)
  169. w = performRequest(router, "POST", "/path4")
  170. assert.Equal(t, w.Header().Get("Location"), "/Path4/")
  171. assert.Equal(t, w.Code, 307)
  172. }
  173. // TestContextParamsGet tests that a parameter can be parsed from the URL.
  174. func TestRouteParamsByName(t *testing.T) {
  175. name := ""
  176. lastName := ""
  177. wild := ""
  178. router := New()
  179. router.GET("/test/:name/:last_name/*wild", func(c *Context) {
  180. name = c.Params.ByName("name")
  181. lastName = c.Params.ByName("last_name")
  182. var ok bool
  183. wild, ok = c.Params.Get("wild")
  184. assert.True(t, ok)
  185. assert.Equal(t, name, c.Param("name"))
  186. assert.Equal(t, name, c.Param("name"))
  187. assert.Equal(t, lastName, c.Param("last_name"))
  188. assert.Empty(t, c.Param("wtf"))
  189. assert.Empty(t, c.Params.ByName("wtf"))
  190. wtf, ok := c.Params.Get("wtf")
  191. assert.Empty(t, wtf)
  192. assert.False(t, ok)
  193. })
  194. w := performRequest(router, "GET", "/test/john/smith/is/super/great")
  195. assert.Equal(t, w.Code, 200)
  196. assert.Equal(t, name, "john")
  197. assert.Equal(t, lastName, "smith")
  198. assert.Equal(t, wild, "/is/super/great")
  199. }
  200. // TestHandleStaticFile - ensure the static file handles properly
  201. func TestRouteStaticFile(t *testing.T) {
  202. // SETUP file
  203. testRoot, _ := os.Getwd()
  204. f, err := ioutil.TempFile(testRoot, "")
  205. if err != nil {
  206. t.Error(err)
  207. }
  208. defer os.Remove(f.Name())
  209. f.WriteString("Gin Web Framework")
  210. f.Close()
  211. dir, filename := filepath.Split(f.Name())
  212. // SETUP gin
  213. router := New()
  214. router.Static("/using_static", dir)
  215. router.StaticFile("/result", f.Name())
  216. w := performRequest(router, "GET", "/using_static/"+filename)
  217. w2 := performRequest(router, "GET", "/result")
  218. assert.Equal(t, w, w2)
  219. assert.Equal(t, w.Code, 200)
  220. assert.Equal(t, w.Body.String(), "Gin Web Framework")
  221. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
  222. w3 := performRequest(router, "HEAD", "/using_static/"+filename)
  223. w4 := performRequest(router, "HEAD", "/result")
  224. assert.Equal(t, w3, w4)
  225. assert.Equal(t, w3.Code, 200)
  226. }
  227. // TestHandleStaticDir - ensure the root/sub dir handles properly
  228. func TestRouteStaticListingDir(t *testing.T) {
  229. router := New()
  230. router.StaticFS("/", Dir("./", true))
  231. w := performRequest(router, "GET", "/")
  232. assert.Equal(t, w.Code, 200)
  233. assert.Contains(t, w.Body.String(), "gin.go")
  234. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/html; charset=utf-8")
  235. }
  236. // TestHandleHeadToDir - ensure the root/sub dir handles properly
  237. func TestRouteStaticNoListing(t *testing.T) {
  238. router := New()
  239. router.Static("/", "./")
  240. w := performRequest(router, "GET", "/")
  241. assert.Equal(t, w.Code, 404)
  242. assert.NotContains(t, w.Body.String(), "gin.go")
  243. }
  244. func TestRouterMiddlewareAndStatic(t *testing.T) {
  245. router := New()
  246. static := router.Group("/", func(c *Context) {
  247. c.Writer.Header().Add("Last-Modified", "Mon, 02 Jan 2006 15:04:05 MST")
  248. c.Writer.Header().Add("Expires", "Mon, 02 Jan 2006 15:04:05 MST")
  249. c.Writer.Header().Add("X-GIN", "Gin Framework")
  250. })
  251. static.Static("/", "./")
  252. w := performRequest(router, "GET", "/gin.go")
  253. assert.Equal(t, w.Code, 200)
  254. assert.Contains(t, w.Body.String(), "package gin")
  255. assert.Equal(t, w.HeaderMap.Get("Content-Type"), "text/plain; charset=utf-8")
  256. assert.NotEqual(t, w.HeaderMap.Get("Last-Modified"), "Mon, 02 Jan 2006 15:04:05 MST")
  257. assert.Equal(t, w.HeaderMap.Get("Expires"), "Mon, 02 Jan 2006 15:04:05 MST")
  258. assert.Equal(t, w.HeaderMap.Get("x-GIN"), "Gin Framework")
  259. }
  260. func TestRouteNotAllowedEnabled(t *testing.T) {
  261. router := New()
  262. router.HandleMethodNotAllowed = true
  263. router.POST("/path", func(c *Context) {})
  264. w := performRequest(router, "GET", "/path")
  265. assert.Equal(t, w.Code, http.StatusMethodNotAllowed)
  266. router.NoMethod(func(c *Context) {
  267. c.String(http.StatusTeapot, "responseText")
  268. })
  269. w = performRequest(router, "GET", "/path")
  270. assert.Equal(t, w.Body.String(), "responseText")
  271. assert.Equal(t, w.Code, http.StatusTeapot)
  272. }
  273. func TestRouteNotAllowedDisabled(t *testing.T) {
  274. router := New()
  275. router.HandleMethodNotAllowed = false
  276. router.POST("/path", func(c *Context) {})
  277. w := performRequest(router, "GET", "/path")
  278. assert.Equal(t, w.Code, 404)
  279. router.NoMethod(func(c *Context) {
  280. c.String(http.StatusTeapot, "responseText")
  281. })
  282. w = performRequest(router, "GET", "/path")
  283. assert.Equal(t, w.Body.String(), "404 page not found")
  284. assert.Equal(t, w.Code, 404)
  285. }
  286. func TestRouterNotFound(t *testing.T) {
  287. router := New()
  288. router.RedirectFixedPath = true
  289. router.GET("/path", func(c *Context) {})
  290. router.GET("/dir/", func(c *Context) {})
  291. router.GET("/", func(c *Context) {})
  292. testRoutes := []struct {
  293. route string
  294. code int
  295. header string
  296. }{
  297. {"/path/", 301, "map[Location:[/path]]"}, // TSR -/
  298. {"/dir", 301, "map[Location:[/dir/]]"}, // TSR +/
  299. {"", 301, "map[Location:[/]]"}, // TSR +/
  300. {"/PATH", 301, "map[Location:[/path]]"}, // Fixed Case
  301. {"/DIR/", 301, "map[Location:[/dir/]]"}, // Fixed Case
  302. {"/PATH/", 301, "map[Location:[/path]]"}, // Fixed Case -/
  303. {"/DIR", 301, "map[Location:[/dir/]]"}, // Fixed Case +/
  304. {"/../path", 301, "map[Location:[/path]]"}, // CleanPath
  305. {"/nope", 404, ""}, // NotFound
  306. }
  307. for _, tr := range testRoutes {
  308. w := performRequest(router, "GET", tr.route)
  309. assert.Equal(t, w.Code, tr.code)
  310. if w.Code != 404 {
  311. assert.Equal(t, fmt.Sprint(w.Header()), tr.header)
  312. }
  313. }
  314. // Test custom not found handler
  315. var notFound bool
  316. router.NoRoute(func(c *Context) {
  317. c.AbortWithStatus(404)
  318. notFound = true
  319. })
  320. w := performRequest(router, "GET", "/nope")
  321. assert.Equal(t, w.Code, 404)
  322. assert.True(t, notFound)
  323. // Test other method than GET (want 307 instead of 301)
  324. router.PATCH("/path", func(c *Context) {})
  325. w = performRequest(router, "PATCH", "/path/")
  326. assert.Equal(t, w.Code, 307)
  327. assert.Equal(t, fmt.Sprint(w.Header()), "map[Location:[/path]]")
  328. // Test special case where no node for the prefix "/" exists
  329. router = New()
  330. router.GET("/a", func(c *Context) {})
  331. w = performRequest(router, "GET", "/")
  332. assert.Equal(t, w.Code, 404)
  333. }
  334. func TestRouteRawPath(t *testing.T) {
  335. route := New()
  336. route.UseRawPath = true
  337. route.POST("/project/:name/build/:num", func(c *Context) {
  338. name := c.Params.ByName("name")
  339. num := c.Params.ByName("num")
  340. assert.Equal(t, c.Param("name"), name)
  341. assert.Equal(t, c.Param("num"), num)
  342. assert.Equal(t, "Some/Other/Project", name)
  343. assert.Equal(t, "222", num)
  344. })
  345. w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/222")
  346. assert.Equal(t, w.Code, 200)
  347. }
  348. func TestRouteRawPathNoUnescape(t *testing.T) {
  349. route := New()
  350. route.UseRawPath = true
  351. route.UnescapePathValues = false
  352. route.POST("/project/:name/build/:num", func(c *Context) {
  353. name := c.Params.ByName("name")
  354. num := c.Params.ByName("num")
  355. assert.Equal(t, c.Param("name"), name)
  356. assert.Equal(t, c.Param("num"), num)
  357. assert.Equal(t, "Some%2FOther%2FProject", name)
  358. assert.Equal(t, "333", num)
  359. })
  360. w := performRequest(route, "POST", "/project/Some%2FOther%2FProject/build/333")
  361. assert.Equal(t, w.Code, 200)
  362. }