mux_test.go 22 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755
  1. // Copyright 2012 The Gorilla Authors. All rights reserved.
  2. // Use of this source code is governed by a BSD-style
  3. // license that can be found in the LICENSE file.
  4. package mux
  5. import (
  6. "fmt"
  7. "net/http"
  8. "testing"
  9. "github.com/gorilla/context"
  10. )
  11. type routeTest struct {
  12. title string // title of the test
  13. route *Route // the route being tested
  14. request *http.Request // a request to test the route
  15. vars map[string]string // the expected vars of the match
  16. host string // the expected host of the match
  17. path string // the expected path of the match
  18. shouldMatch bool // whether the request is expected to match the route at all
  19. }
  20. func TestHost(t *testing.T) {
  21. // newRequestHost a new request with a method, url, and host header
  22. newRequestHost := func(method, url, host string) *http.Request {
  23. req, err := http.NewRequest(method, url, nil)
  24. if err != nil {
  25. panic(err)
  26. }
  27. req.Host = host
  28. return req
  29. }
  30. tests := []routeTest{
  31. {
  32. title: "Host route match",
  33. route: new(Route).Host("aaa.bbb.ccc"),
  34. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  35. vars: map[string]string{},
  36. host: "aaa.bbb.ccc",
  37. path: "",
  38. shouldMatch: true,
  39. },
  40. {
  41. title: "Host route, wrong host in request URL",
  42. route: new(Route).Host("aaa.bbb.ccc"),
  43. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  44. vars: map[string]string{},
  45. host: "aaa.bbb.ccc",
  46. path: "",
  47. shouldMatch: false,
  48. },
  49. {
  50. title: "Host route with port, match",
  51. route: new(Route).Host("aaa.bbb.ccc:1234"),
  52. request: newRequest("GET", "http://aaa.bbb.ccc:1234/111/222/333"),
  53. vars: map[string]string{},
  54. host: "aaa.bbb.ccc:1234",
  55. path: "",
  56. shouldMatch: true,
  57. },
  58. {
  59. title: "Host route with port, wrong port in request URL",
  60. route: new(Route).Host("aaa.bbb.ccc:1234"),
  61. request: newRequest("GET", "http://aaa.bbb.ccc:9999/111/222/333"),
  62. vars: map[string]string{},
  63. host: "aaa.bbb.ccc:1234",
  64. path: "",
  65. shouldMatch: false,
  66. },
  67. {
  68. title: "Host route, match with host in request header",
  69. route: new(Route).Host("aaa.bbb.ccc"),
  70. request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc"),
  71. vars: map[string]string{},
  72. host: "aaa.bbb.ccc",
  73. path: "",
  74. shouldMatch: true,
  75. },
  76. {
  77. title: "Host route, wrong host in request header",
  78. route: new(Route).Host("aaa.bbb.ccc"),
  79. request: newRequestHost("GET", "/111/222/333", "aaa.222.ccc"),
  80. vars: map[string]string{},
  81. host: "aaa.bbb.ccc",
  82. path: "",
  83. shouldMatch: false,
  84. },
  85. // BUG {new(Route).Host("aaa.bbb.ccc:1234"), newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:1234"), map[string]string{}, "aaa.bbb.ccc:1234", "", true},
  86. {
  87. title: "Host route with port, wrong host in request header",
  88. route: new(Route).Host("aaa.bbb.ccc:1234"),
  89. request: newRequestHost("GET", "/111/222/333", "aaa.bbb.ccc:9999"),
  90. vars: map[string]string{},
  91. host: "aaa.bbb.ccc:1234",
  92. path: "",
  93. shouldMatch: false,
  94. },
  95. {
  96. title: "Host route with pattern, match",
  97. route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
  98. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  99. vars: map[string]string{"v1": "bbb"},
  100. host: "aaa.bbb.ccc",
  101. path: "",
  102. shouldMatch: true,
  103. },
  104. {
  105. title: "Host route with pattern, wrong host in request URL",
  106. route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc"),
  107. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  108. vars: map[string]string{"v1": "bbb"},
  109. host: "aaa.bbb.ccc",
  110. path: "",
  111. shouldMatch: false,
  112. },
  113. {
  114. title: "Host route with multiple patterns, match",
  115. route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
  116. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  117. vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
  118. host: "aaa.bbb.ccc",
  119. path: "",
  120. shouldMatch: true,
  121. },
  122. {
  123. title: "Host route with multiple patterns, wrong host in request URL",
  124. route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}"),
  125. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  126. vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc"},
  127. host: "aaa.bbb.ccc",
  128. path: "",
  129. shouldMatch: false,
  130. },
  131. }
  132. for _, test := range tests {
  133. testRoute(t, test)
  134. }
  135. }
  136. func TestPath(t *testing.T) {
  137. tests := []routeTest{
  138. {
  139. title: "Path route, match",
  140. route: new(Route).Path("/111/222/333"),
  141. request: newRequest("GET", "http://localhost/111/222/333"),
  142. vars: map[string]string{},
  143. host: "",
  144. path: "/111/222/333",
  145. shouldMatch: true,
  146. },
  147. {
  148. title: "Path route, wrong path in request in request URL",
  149. route: new(Route).Path("/111/222/333"),
  150. request: newRequest("GET", "http://localhost/1/2/3"),
  151. vars: map[string]string{},
  152. host: "",
  153. path: "/111/222/333",
  154. shouldMatch: false,
  155. },
  156. {
  157. title: "Path route with pattern, match",
  158. route: new(Route).Path("/111/{v1:[0-9]{3}}/333"),
  159. request: newRequest("GET", "http://localhost/111/222/333"),
  160. vars: map[string]string{"v1": "222"},
  161. host: "",
  162. path: "/111/222/333",
  163. shouldMatch: true,
  164. },
  165. {
  166. title: "Path route with pattern, URL in request does not match",
  167. route: new(Route).Path("/111/{v1:[0-9]{3}}/333"),
  168. request: newRequest("GET", "http://localhost/111/aaa/333"),
  169. vars: map[string]string{"v1": "222"},
  170. host: "",
  171. path: "/111/222/333",
  172. shouldMatch: false,
  173. },
  174. {
  175. title: "Path route with multiple patterns, match",
  176. route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
  177. request: newRequest("GET", "http://localhost/111/222/333"),
  178. vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"},
  179. host: "",
  180. path: "/111/222/333",
  181. shouldMatch: true,
  182. },
  183. {
  184. title: "Path route with multiple patterns, URL in request does not match",
  185. route: new(Route).Path("/{v1:[0-9]{3}}/{v2:[0-9]{3}}/{v3:[0-9]{3}}"),
  186. request: newRequest("GET", "http://localhost/111/aaa/333"),
  187. vars: map[string]string{"v1": "111", "v2": "222", "v3": "333"},
  188. host: "",
  189. path: "/111/222/333",
  190. shouldMatch: false,
  191. },
  192. }
  193. for _, test := range tests {
  194. testRoute(t, test)
  195. }
  196. }
  197. func TestPathPrefix(t *testing.T) {
  198. tests := []routeTest{
  199. {
  200. title: "PathPrefix route, match",
  201. route: new(Route).PathPrefix("/111"),
  202. request: newRequest("GET", "http://localhost/111/222/333"),
  203. vars: map[string]string{},
  204. host: "",
  205. path: "/111",
  206. shouldMatch: true,
  207. },
  208. {
  209. title: "PathPrefix route, URL prefix in request does not match",
  210. route: new(Route).PathPrefix("/111"),
  211. request: newRequest("GET", "http://localhost/1/2/3"),
  212. vars: map[string]string{},
  213. host: "",
  214. path: "/111",
  215. shouldMatch: false,
  216. },
  217. {
  218. title: "PathPrefix route with pattern, match",
  219. route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
  220. request: newRequest("GET", "http://localhost/111/222/333"),
  221. vars: map[string]string{"v1": "222"},
  222. host: "",
  223. path: "/111/222",
  224. shouldMatch: true,
  225. },
  226. {
  227. title: "PathPrefix route with pattern, URL prefix in request does not match",
  228. route: new(Route).PathPrefix("/111/{v1:[0-9]{3}}"),
  229. request: newRequest("GET", "http://localhost/111/aaa/333"),
  230. vars: map[string]string{"v1": "222"},
  231. host: "",
  232. path: "/111/222",
  233. shouldMatch: false,
  234. },
  235. {
  236. title: "PathPrefix route with multiple patterns, match",
  237. route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
  238. request: newRequest("GET", "http://localhost/111/222/333"),
  239. vars: map[string]string{"v1": "111", "v2": "222"},
  240. host: "",
  241. path: "/111/222",
  242. shouldMatch: true,
  243. },
  244. {
  245. title: "PathPrefix route with multiple patterns, URL prefix in request does not match",
  246. route: new(Route).PathPrefix("/{v1:[0-9]{3}}/{v2:[0-9]{3}}"),
  247. request: newRequest("GET", "http://localhost/111/aaa/333"),
  248. vars: map[string]string{"v1": "111", "v2": "222"},
  249. host: "",
  250. path: "/111/222",
  251. shouldMatch: false,
  252. },
  253. }
  254. for _, test := range tests {
  255. testRoute(t, test)
  256. }
  257. }
  258. func TestHostPath(t *testing.T) {
  259. tests := []routeTest{
  260. {
  261. title: "Host and Path route, match",
  262. route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
  263. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  264. vars: map[string]string{},
  265. host: "",
  266. path: "",
  267. shouldMatch: true,
  268. },
  269. {
  270. title: "Host and Path route, wrong host in request URL",
  271. route: new(Route).Host("aaa.bbb.ccc").Path("/111/222/333"),
  272. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  273. vars: map[string]string{},
  274. host: "",
  275. path: "",
  276. shouldMatch: false,
  277. },
  278. {
  279. title: "Host and Path route with pattern, match",
  280. route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
  281. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  282. vars: map[string]string{"v1": "bbb", "v2": "222"},
  283. host: "aaa.bbb.ccc",
  284. path: "/111/222/333",
  285. shouldMatch: true,
  286. },
  287. {
  288. title: "Host and Path route with pattern, URL in request does not match",
  289. route: new(Route).Host("aaa.{v1:[a-z]{3}}.ccc").Path("/111/{v2:[0-9]{3}}/333"),
  290. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  291. vars: map[string]string{"v1": "bbb", "v2": "222"},
  292. host: "aaa.bbb.ccc",
  293. path: "/111/222/333",
  294. shouldMatch: false,
  295. },
  296. {
  297. title: "Host and Path route with multiple patterns, match",
  298. route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
  299. request: newRequest("GET", "http://aaa.bbb.ccc/111/222/333"),
  300. vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
  301. host: "aaa.bbb.ccc",
  302. path: "/111/222/333",
  303. shouldMatch: true,
  304. },
  305. {
  306. title: "Host and Path route with multiple patterns, URL in request does not match",
  307. route: new(Route).Host("{v1:[a-z]{3}}.{v2:[a-z]{3}}.{v3:[a-z]{3}}").Path("/{v4:[0-9]{3}}/{v5:[0-9]{3}}/{v6:[0-9]{3}}"),
  308. request: newRequest("GET", "http://aaa.222.ccc/111/222/333"),
  309. vars: map[string]string{"v1": "aaa", "v2": "bbb", "v3": "ccc", "v4": "111", "v5": "222", "v6": "333"},
  310. host: "aaa.bbb.ccc",
  311. path: "/111/222/333",
  312. shouldMatch: false,
  313. },
  314. }
  315. for _, test := range tests {
  316. testRoute(t, test)
  317. }
  318. }
  319. func TestHeaders(t *testing.T) {
  320. // newRequestHeaders creates a new request with a method, url, and headers
  321. newRequestHeaders := func(method, url string, headers map[string]string) *http.Request {
  322. req, err := http.NewRequest(method, url, nil)
  323. if err != nil {
  324. panic(err)
  325. }
  326. for k, v := range headers {
  327. req.Header.Add(k, v)
  328. }
  329. return req
  330. }
  331. tests := []routeTest{
  332. {
  333. title: "Headers route, match",
  334. route: new(Route).Headers("foo", "bar", "baz", "ding"),
  335. request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "ding"}),
  336. vars: map[string]string{},
  337. host: "",
  338. path: "",
  339. shouldMatch: true,
  340. },
  341. {
  342. title: "Headers route, bad header values",
  343. route: new(Route).Headers("foo", "bar", "baz", "ding"),
  344. request: newRequestHeaders("GET", "http://localhost", map[string]string{"foo": "bar", "baz": "dong"}),
  345. vars: map[string]string{},
  346. host: "",
  347. path: "",
  348. shouldMatch: false,
  349. },
  350. }
  351. for _, test := range tests {
  352. testRoute(t, test)
  353. }
  354. }
  355. func TestMethods(t *testing.T) {
  356. tests := []routeTest{
  357. {
  358. title: "Methods route, match GET",
  359. route: new(Route).Methods("GET", "POST"),
  360. request: newRequest("GET", "http://localhost"),
  361. vars: map[string]string{},
  362. host: "",
  363. path: "",
  364. shouldMatch: true,
  365. },
  366. {
  367. title: "Methods route, match POST",
  368. route: new(Route).Methods("GET", "POST"),
  369. request: newRequest("POST", "http://localhost"),
  370. vars: map[string]string{},
  371. host: "",
  372. path: "",
  373. shouldMatch: true,
  374. },
  375. {
  376. title: "Methods route, bad method",
  377. route: new(Route).Methods("GET", "POST"),
  378. request: newRequest("PUT", "http://localhost"),
  379. vars: map[string]string{},
  380. host: "",
  381. path: "",
  382. shouldMatch: false,
  383. },
  384. }
  385. for _, test := range tests {
  386. testRoute(t, test)
  387. }
  388. }
  389. func TestQueries(t *testing.T) {
  390. tests := []routeTest{
  391. {
  392. title: "Queries route, match",
  393. route: new(Route).Queries("foo", "bar", "baz", "ding"),
  394. request: newRequest("GET", "http://localhost?foo=bar&baz=ding"),
  395. vars: map[string]string{},
  396. host: "",
  397. path: "",
  398. shouldMatch: true,
  399. },
  400. {
  401. title: "Queries route, bad query",
  402. route: new(Route).Queries("foo", "bar", "baz", "ding"),
  403. request: newRequest("GET", "http://localhost?foo=bar&baz=dong"),
  404. vars: map[string]string{},
  405. host: "",
  406. path: "",
  407. shouldMatch: false,
  408. },
  409. }
  410. for _, test := range tests {
  411. testRoute(t, test)
  412. }
  413. }
  414. func TestSchemes(t *testing.T) {
  415. tests := []routeTest{
  416. // Schemes
  417. {
  418. title: "Schemes route, match https",
  419. route: new(Route).Schemes("https", "ftp"),
  420. request: newRequest("GET", "https://localhost"),
  421. vars: map[string]string{},
  422. host: "",
  423. path: "",
  424. shouldMatch: true,
  425. },
  426. {
  427. title: "Schemes route, match ftp",
  428. route: new(Route).Schemes("https", "ftp"),
  429. request: newRequest("GET", "ftp://localhost"),
  430. vars: map[string]string{},
  431. host: "",
  432. path: "",
  433. shouldMatch: true,
  434. },
  435. {
  436. title: "Schemes route, bad scheme",
  437. route: new(Route).Schemes("https", "ftp"),
  438. request: newRequest("GET", "http://localhost"),
  439. vars: map[string]string{},
  440. host: "",
  441. path: "",
  442. shouldMatch: false,
  443. },
  444. }
  445. for _, test := range tests {
  446. testRoute(t, test)
  447. }
  448. }
  449. func TestMatcherFunc(t *testing.T) {
  450. m := func(r *http.Request, m *RouteMatch) bool {
  451. if r.URL.Host == "aaa.bbb.ccc" {
  452. return true
  453. }
  454. return false
  455. }
  456. tests := []routeTest{
  457. {
  458. title: "MatchFunc route, match",
  459. route: new(Route).MatcherFunc(m),
  460. request: newRequest("GET", "http://aaa.bbb.ccc"),
  461. vars: map[string]string{},
  462. host: "",
  463. path: "",
  464. shouldMatch: true,
  465. },
  466. {
  467. title: "MatchFunc route, non-match",
  468. route: new(Route).MatcherFunc(m),
  469. request: newRequest("GET", "http://aaa.222.ccc"),
  470. vars: map[string]string{},
  471. host: "",
  472. path: "",
  473. shouldMatch: false,
  474. },
  475. }
  476. for _, test := range tests {
  477. testRoute(t, test)
  478. }
  479. }
  480. func TestSubRouter(t *testing.T) {
  481. subrouter1 := new(Route).Host("{v1:[a-z]+}.google.com").Subrouter()
  482. subrouter2 := new(Route).PathPrefix("/foo/{v1}").Subrouter()
  483. tests := []routeTest{
  484. {
  485. route: subrouter1.Path("/{v2:[a-z]+}"),
  486. request: newRequest("GET", "http://aaa.google.com/bbb"),
  487. vars: map[string]string{"v1": "aaa", "v2": "bbb"},
  488. host: "aaa.google.com",
  489. path: "/bbb",
  490. shouldMatch: true,
  491. },
  492. {
  493. route: subrouter1.Path("/{v2:[a-z]+}"),
  494. request: newRequest("GET", "http://111.google.com/111"),
  495. vars: map[string]string{"v1": "aaa", "v2": "bbb"},
  496. host: "aaa.google.com",
  497. path: "/bbb",
  498. shouldMatch: false,
  499. },
  500. {
  501. route: subrouter2.Path("/baz/{v2}"),
  502. request: newRequest("GET", "http://localhost/foo/bar/baz/ding"),
  503. vars: map[string]string{"v1": "bar", "v2": "ding"},
  504. host: "",
  505. path: "/foo/bar/baz/ding",
  506. shouldMatch: true,
  507. },
  508. {
  509. route: subrouter2.Path("/baz/{v2}"),
  510. request: newRequest("GET", "http://localhost/foo/bar"),
  511. vars: map[string]string{"v1": "bar", "v2": "ding"},
  512. host: "",
  513. path: "/foo/bar/baz/ding",
  514. shouldMatch: false,
  515. },
  516. }
  517. for _, test := range tests {
  518. testRoute(t, test)
  519. }
  520. }
  521. func TestNamedRoutes(t *testing.T) {
  522. r1 := NewRouter()
  523. r1.NewRoute().Name("a")
  524. r1.NewRoute().Name("b")
  525. r1.NewRoute().Name("c")
  526. r2 := r1.NewRoute().Subrouter()
  527. r2.NewRoute().Name("d")
  528. r2.NewRoute().Name("e")
  529. r2.NewRoute().Name("f")
  530. r3 := r2.NewRoute().Subrouter()
  531. r3.NewRoute().Name("g")
  532. r3.NewRoute().Name("h")
  533. r3.NewRoute().Name("i")
  534. if r1.namedRoutes == nil || len(r1.namedRoutes) != 9 {
  535. t.Errorf("Expected 9 named routes, got %v", r1.namedRoutes)
  536. } else if r1.Get("i") == nil {
  537. t.Errorf("Subroute name not registered")
  538. }
  539. }
  540. func TestStrictSlash(t *testing.T) {
  541. var r *Router
  542. var req *http.Request
  543. var route *Route
  544. var match *RouteMatch
  545. var matched bool
  546. // StrictSlash should be ignored for path prefix.
  547. // So we register a route ending in slash but it doesn't attempt to add
  548. // the slash for a path not ending in slash.
  549. r = NewRouter()
  550. r.StrictSlash(true)
  551. route = r.NewRoute().PathPrefix("/static/")
  552. req, _ = http.NewRequest("GET", "http://localhost/static/logo.png", nil)
  553. match = new(RouteMatch)
  554. matched = r.Match(req, match)
  555. if !matched {
  556. t.Errorf("Should match request %q -- %v", req.URL.Path, getRouteTemplate(route))
  557. }
  558. if match.Handler != nil {
  559. t.Errorf("Should not redirect")
  560. }
  561. }
  562. // ----------------------------------------------------------------------------
  563. // Helpers
  564. // ----------------------------------------------------------------------------
  565. func getRouteTemplate(route *Route) string {
  566. host, path := "none", "none"
  567. if route.regexp != nil {
  568. if route.regexp.host != nil {
  569. host = route.regexp.host.template
  570. }
  571. if route.regexp.path != nil {
  572. path = route.regexp.path.template
  573. }
  574. }
  575. return fmt.Sprintf("Host: %v, Path: %v", host, path)
  576. }
  577. func testRoute(t *testing.T, test routeTest) {
  578. request := test.request
  579. route := test.route
  580. vars := test.vars
  581. shouldMatch := test.shouldMatch
  582. host := test.host
  583. path := test.path
  584. url := test.host + test.path
  585. var match RouteMatch
  586. ok := route.Match(request, &match)
  587. if ok != shouldMatch {
  588. msg := "Should match"
  589. if !shouldMatch {
  590. msg = "Should not match"
  591. }
  592. t.Errorf("(%v) %v:\nRoute: %#v\nRequest: %#v\nVars: %v\n", test.title, msg, route, request, vars)
  593. return
  594. }
  595. if shouldMatch {
  596. if test.vars != nil && !stringMapEqual(test.vars, match.Vars) {
  597. t.Errorf("(%v) Vars not equal: expected %v, got %v", test.title, vars, match.Vars)
  598. return
  599. }
  600. if host != "" {
  601. u, _ := test.route.URLHost(mapToPairs(match.Vars)...)
  602. if host != u.Host {
  603. t.Errorf("(%v) URLHost not equal: expected %v, got %v -- %v", test.title, host, u.Host, getRouteTemplate(route))
  604. return
  605. }
  606. }
  607. if path != "" {
  608. u, _ := route.URLPath(mapToPairs(match.Vars)...)
  609. if path != u.Path {
  610. t.Errorf("(%v) URLPath not equal: expected %v, got %v -- %v", test.title, path, u.Path, getRouteTemplate(route))
  611. return
  612. }
  613. }
  614. if url != "" {
  615. u, _ := route.URL(mapToPairs(match.Vars)...)
  616. if url != u.Host+u.Path {
  617. t.Errorf("(%v) URL not equal: expected %v, got %v -- %v", test.title, url, u.Host+u.Path, getRouteTemplate(route))
  618. return
  619. }
  620. }
  621. }
  622. }
  623. // Tests that the context is cleared or not cleared properly depending on
  624. // the configuration of the router
  625. func TestKeepContext(t *testing.T) {
  626. func1 := func(w http.ResponseWriter, r *http.Request) {}
  627. r := NewRouter()
  628. r.HandleFunc("/", func1).Name("func1")
  629. req, _ := http.NewRequest("GET", "http://localhost/", nil)
  630. context.Set(req, "t", 1)
  631. res := new(http.ResponseWriter)
  632. r.ServeHTTP(*res, req)
  633. if _, ok := context.GetOk(req, "t"); ok {
  634. t.Error("Context should have been cleared at end of request")
  635. }
  636. r.KeepContext = true
  637. req, _ = http.NewRequest("GET", "http://localhost/", nil)
  638. context.Set(req, "t", 1)
  639. r.ServeHTTP(*res, req)
  640. if _, ok := context.GetOk(req, "t"); !ok {
  641. t.Error("Context should NOT have been cleared at end of request")
  642. }
  643. }
  644. // https://plus.google.com/101022900381697718949/posts/eWy6DjFJ6uW
  645. func TestSubrouterHeader(t *testing.T) {
  646. expected := "func1 response"
  647. func1 := func(w http.ResponseWriter, r *http.Request) {
  648. fmt.Fprint(w, expected)
  649. }
  650. func2 := func(http.ResponseWriter, *http.Request) {}
  651. r := NewRouter()
  652. s := r.Headers("SomeSpecialHeader", "").Subrouter()
  653. s.HandleFunc("/", func1).Name("func1")
  654. r.HandleFunc("/", func2).Name("func2")
  655. req, _ := http.NewRequest("GET", "http://localhost/", nil)
  656. req.Header.Add("SomeSpecialHeader", "foo")
  657. match := new(RouteMatch)
  658. matched := r.Match(req, match)
  659. if !matched {
  660. t.Errorf("Should match request")
  661. }
  662. if match.Route.GetName() != "func1" {
  663. t.Errorf("Expecting func1 handler, got %s", match.Route.GetName())
  664. }
  665. resp := NewRecorder()
  666. match.Handler.ServeHTTP(resp, req)
  667. if resp.Body.String() != expected {
  668. t.Errorf("Expecting %q", expected)
  669. }
  670. }
  671. // mapToPairs converts a string map to a slice of string pairs
  672. func mapToPairs(m map[string]string) []string {
  673. var i int
  674. p := make([]string, len(m)*2)
  675. for k, v := range m {
  676. p[i] = k
  677. p[i+1] = v
  678. i += 2
  679. }
  680. return p
  681. }
  682. // stringMapEqual checks the equality of two string maps
  683. func stringMapEqual(m1, m2 map[string]string) bool {
  684. nil1 := m1 == nil
  685. nil2 := m2 == nil
  686. if nil1 != nil2 || len(m1) != len(m2) {
  687. return false
  688. }
  689. for k, v := range m1 {
  690. if v != m2[k] {
  691. return false
  692. }
  693. }
  694. return true
  695. }
  696. // newRequest is a helper function to create a new request with a method and url
  697. func newRequest(method, url string) *http.Request {
  698. req, err := http.NewRequest(method, url, nil)
  699. if err != nil {
  700. panic(err)
  701. }
  702. return req
  703. }