mux.go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354
  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. "path"
  9. "github.com/gorilla/context"
  10. )
  11. // NewRouter returns a new router instance.
  12. func NewRouter() *Router {
  13. return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
  14. }
  15. // Router registers routes to be matched and dispatches a handler.
  16. //
  17. // It implements the http.Handler interface, so it can be registered to serve
  18. // requests:
  19. //
  20. // var router = mux.NewRouter()
  21. //
  22. // func main() {
  23. // http.Handle("/", router)
  24. // }
  25. //
  26. // Or, for Google App Engine, register it in a init() function:
  27. //
  28. // func init() {
  29. // http.Handle("/", router)
  30. // }
  31. //
  32. // This will send all incoming requests to the router.
  33. type Router struct {
  34. // Configurable Handler to be used when no route matches.
  35. NotFoundHandler http.Handler
  36. // Parent route, if this is a subrouter.
  37. parent parentRoute
  38. // Routes to be matched, in order.
  39. routes []*Route
  40. // Routes by name for URL building.
  41. namedRoutes map[string]*Route
  42. // See Router.StrictSlash(). This defines the flag for new routes.
  43. strictSlash bool
  44. // If true, do not clear the request context after handling the request
  45. KeepContext bool
  46. }
  47. // Match matches registered routes against the request.
  48. func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
  49. for _, route := range r.routes {
  50. if route.Match(req, match) {
  51. return true
  52. }
  53. }
  54. return false
  55. }
  56. // ServeHTTP dispatches the handler registered in the matched route.
  57. //
  58. // When there is a match, the route variables can be retrieved calling
  59. // mux.Vars(request).
  60. func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
  61. // Clean path to canonical form and redirect.
  62. if p := cleanPath(req.URL.Path); p != req.URL.Path {
  63. // Added 3 lines (Philip Schlump) - It was droping the query string and #whatever from query.
  64. // This matches with fix in go 1.2 r.c. 4 for same problem. Go Issue:
  65. // http://code.google.com/p/go/issues/detail?id=5252
  66. url := *req.URL
  67. url.Path = p
  68. p = url.String()
  69. w.Header().Set("Location", p)
  70. w.WriteHeader(http.StatusMovedPermanently)
  71. return
  72. }
  73. var match RouteMatch
  74. var handler http.Handler
  75. if r.Match(req, &match) {
  76. handler = match.Handler
  77. setVars(req, match.Vars)
  78. setCurrentRoute(req, match.Route)
  79. }
  80. if handler == nil {
  81. handler = r.NotFoundHandler
  82. if handler == nil {
  83. handler = http.NotFoundHandler()
  84. }
  85. }
  86. if !r.KeepContext {
  87. defer context.Clear(req)
  88. }
  89. handler.ServeHTTP(w, req)
  90. }
  91. // Get returns a route registered with the given name.
  92. func (r *Router) Get(name string) *Route {
  93. return r.getNamedRoutes()[name]
  94. }
  95. // GetRoute returns a route registered with the given name. This method
  96. // was renamed to Get() and remains here for backwards compatibility.
  97. func (r *Router) GetRoute(name string) *Route {
  98. return r.getNamedRoutes()[name]
  99. }
  100. // StrictSlash defines the trailing slash behavior for new routes. The initial
  101. // value is false.
  102. //
  103. // When true, if the route path is "/path/", accessing "/path" will redirect
  104. // to the former and vice versa. In other words, your application will always
  105. // see the path as specified in the route.
  106. //
  107. // When false, if the route path is "/path", accessing "/path/" will not match
  108. // this route and vice versa.
  109. //
  110. // Special case: when a route sets a path prefix using the PathPrefix() method,
  111. // strict slash is ignored for that route because the redirect behavior can't
  112. // be determined from a prefix alone. However, any subrouters created from that
  113. // route inherit the original StrictSlash setting.
  114. func (r *Router) StrictSlash(value bool) *Router {
  115. r.strictSlash = value
  116. return r
  117. }
  118. // ----------------------------------------------------------------------------
  119. // parentRoute
  120. // ----------------------------------------------------------------------------
  121. // getNamedRoutes returns the map where named routes are registered.
  122. func (r *Router) getNamedRoutes() map[string]*Route {
  123. if r.namedRoutes == nil {
  124. if r.parent != nil {
  125. r.namedRoutes = r.parent.getNamedRoutes()
  126. } else {
  127. r.namedRoutes = make(map[string]*Route)
  128. }
  129. }
  130. return r.namedRoutes
  131. }
  132. // getRegexpGroup returns regexp definitions from the parent route, if any.
  133. func (r *Router) getRegexpGroup() *routeRegexpGroup {
  134. if r.parent != nil {
  135. return r.parent.getRegexpGroup()
  136. }
  137. return nil
  138. }
  139. // ----------------------------------------------------------------------------
  140. // Route factories
  141. // ----------------------------------------------------------------------------
  142. // NewRoute registers an empty route.
  143. func (r *Router) NewRoute() *Route {
  144. route := &Route{parent: r, strictSlash: r.strictSlash}
  145. r.routes = append(r.routes, route)
  146. return route
  147. }
  148. // Handle registers a new route with a matcher for the URL path.
  149. // See Route.Path() and Route.Handler().
  150. func (r *Router) Handle(path string, handler http.Handler) *Route {
  151. return r.NewRoute().Path(path).Handler(handler)
  152. }
  153. // HandleFunc registers a new route with a matcher for the URL path.
  154. // See Route.Path() and Route.HandlerFunc().
  155. func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
  156. *http.Request)) *Route {
  157. return r.NewRoute().Path(path).HandlerFunc(f)
  158. }
  159. // Headers registers a new route with a matcher for request header values.
  160. // See Route.Headers().
  161. func (r *Router) Headers(pairs ...string) *Route {
  162. return r.NewRoute().Headers(pairs...)
  163. }
  164. // Host registers a new route with a matcher for the URL host.
  165. // See Route.Host().
  166. func (r *Router) Host(tpl string) *Route {
  167. return r.NewRoute().Host(tpl)
  168. }
  169. // MatcherFunc registers a new route with a custom matcher function.
  170. // See Route.MatcherFunc().
  171. func (r *Router) MatcherFunc(f MatcherFunc) *Route {
  172. return r.NewRoute().MatcherFunc(f)
  173. }
  174. // Methods registers a new route with a matcher for HTTP methods.
  175. // See Route.Methods().
  176. func (r *Router) Methods(methods ...string) *Route {
  177. return r.NewRoute().Methods(methods...)
  178. }
  179. // Path registers a new route with a matcher for the URL path.
  180. // See Route.Path().
  181. func (r *Router) Path(tpl string) *Route {
  182. return r.NewRoute().Path(tpl)
  183. }
  184. // PathPrefix registers a new route with a matcher for the URL path prefix.
  185. // See Route.PathPrefix().
  186. func (r *Router) PathPrefix(tpl string) *Route {
  187. return r.NewRoute().PathPrefix(tpl)
  188. }
  189. // Queries registers a new route with a matcher for URL query values.
  190. // See Route.Queries().
  191. func (r *Router) Queries(pairs ...string) *Route {
  192. return r.NewRoute().Queries(pairs...)
  193. }
  194. // Schemes registers a new route with a matcher for URL schemes.
  195. // See Route.Schemes().
  196. func (r *Router) Schemes(schemes ...string) *Route {
  197. return r.NewRoute().Schemes(schemes...)
  198. }
  199. // ----------------------------------------------------------------------------
  200. // Context
  201. // ----------------------------------------------------------------------------
  202. // RouteMatch stores information about a matched route.
  203. type RouteMatch struct {
  204. Route *Route
  205. Handler http.Handler
  206. Vars map[string]string
  207. }
  208. type contextKey int
  209. const (
  210. varsKey contextKey = iota
  211. routeKey
  212. )
  213. // Vars returns the route variables for the current request, if any.
  214. func Vars(r *http.Request) map[string]string {
  215. if rv := context.Get(r, varsKey); rv != nil {
  216. return rv.(map[string]string)
  217. }
  218. return nil
  219. }
  220. // CurrentRoute returns the matched route for the current request, if any.
  221. func CurrentRoute(r *http.Request) *Route {
  222. if rv := context.Get(r, routeKey); rv != nil {
  223. return rv.(*Route)
  224. }
  225. return nil
  226. }
  227. func setVars(r *http.Request, val interface{}) {
  228. context.Set(r, varsKey, val)
  229. }
  230. func setCurrentRoute(r *http.Request, val interface{}) {
  231. context.Set(r, routeKey, val)
  232. }
  233. // ----------------------------------------------------------------------------
  234. // Helpers
  235. // ----------------------------------------------------------------------------
  236. // cleanPath returns the canonical path for p, eliminating . and .. elements.
  237. // Borrowed from the net/http package.
  238. func cleanPath(p string) string {
  239. if p == "" {
  240. return "/"
  241. }
  242. if p[0] != '/' {
  243. p = "/" + p
  244. }
  245. np := path.Clean(p)
  246. // path.Clean removes trailing slash except for root;
  247. // put the trailing slash back if necessary.
  248. if p[len(p)-1] == '/' && np != "/" {
  249. np += "/"
  250. }
  251. return np
  252. }
  253. // uniqueVars returns an error if two slices contain duplicated strings.
  254. func uniqueVars(s1, s2 []string) error {
  255. for _, v1 := range s1 {
  256. for _, v2 := range s2 {
  257. if v1 == v2 {
  258. return fmt.Errorf("mux: duplicated route variable %q", v2)
  259. }
  260. }
  261. }
  262. return nil
  263. }
  264. // mapFromPairs converts variadic string parameters to a string map.
  265. func mapFromPairs(pairs ...string) (map[string]string, error) {
  266. length := len(pairs)
  267. if length%2 != 0 {
  268. return nil, fmt.Errorf(
  269. "mux: number of parameters must be multiple of 2, got %v", pairs)
  270. }
  271. m := make(map[string]string, length/2)
  272. for i := 0; i < length; i += 2 {
  273. m[pairs[i]] = pairs[i+1]
  274. }
  275. return m, nil
  276. }
  277. // matchInArray returns true if the given string value is in the array.
  278. func matchInArray(arr []string, value string) bool {
  279. for _, v := range arr {
  280. if v == value {
  281. return true
  282. }
  283. }
  284. return false
  285. }
  286. // matchMap returns true if the given key/value pairs exist in a given map.
  287. func matchMap(toCheck map[string]string, toMatch map[string][]string,
  288. canonicalKey bool) bool {
  289. for k, v := range toCheck {
  290. // Check if key exists.
  291. if canonicalKey {
  292. k = http.CanonicalHeaderKey(k)
  293. }
  294. if values := toMatch[k]; values == nil {
  295. return false
  296. } else if v != "" {
  297. // If value was defined as an empty string we only check that the
  298. // key exists. Otherwise we also check for equality.
  299. valueExists := false
  300. for _, value := range values {
  301. if v == value {
  302. valueExists = true
  303. break
  304. }
  305. }
  306. if !valueExists {
  307. return false
  308. }
  309. }
  310. }
  311. return true
  312. }