Tizen_4.0 base
[platform/upstream/docker-engine.git] / vendor / github.com / gorilla / mux / mux.go
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
5 package mux
6
7 import (
8         "errors"
9         "fmt"
10         "net/http"
11         "path"
12         "regexp"
13
14         "github.com/gorilla/context"
15 )
16
17 // NewRouter returns a new router instance.
18 func NewRouter() *Router {
19         return &Router{namedRoutes: make(map[string]*Route), KeepContext: false}
20 }
21
22 // Router registers routes to be matched and dispatches a handler.
23 //
24 // It implements the http.Handler interface, so it can be registered to serve
25 // requests:
26 //
27 //     var router = mux.NewRouter()
28 //
29 //     func main() {
30 //         http.Handle("/", router)
31 //     }
32 //
33 // Or, for Google App Engine, register it in a init() function:
34 //
35 //     func init() {
36 //         http.Handle("/", router)
37 //     }
38 //
39 // This will send all incoming requests to the router.
40 type Router struct {
41         // Configurable Handler to be used when no route matches.
42         NotFoundHandler http.Handler
43         // Parent route, if this is a subrouter.
44         parent parentRoute
45         // Routes to be matched, in order.
46         routes []*Route
47         // Routes by name for URL building.
48         namedRoutes map[string]*Route
49         // See Router.StrictSlash(). This defines the flag for new routes.
50         strictSlash bool
51         // If true, do not clear the request context after handling the request
52         KeepContext bool
53 }
54
55 // Match matches registered routes against the request.
56 func (r *Router) Match(req *http.Request, match *RouteMatch) bool {
57         for _, route := range r.routes {
58                 if route.Match(req, match) {
59                         return true
60                 }
61         }
62
63         // Closest match for a router (includes sub-routers)
64         if r.NotFoundHandler != nil {
65                 match.Handler = r.NotFoundHandler
66                 return true
67         }
68         return false
69 }
70
71 // ServeHTTP dispatches the handler registered in the matched route.
72 //
73 // When there is a match, the route variables can be retrieved calling
74 // mux.Vars(request).
75 func (r *Router) ServeHTTP(w http.ResponseWriter, req *http.Request) {
76         // Clean path to canonical form and redirect.
77         if p := cleanPath(req.URL.Path); p != req.URL.Path {
78
79                 // Added 3 lines (Philip Schlump) - It was dropping the query string and #whatever from query.
80                 // This matches with fix in go 1.2 r.c. 4 for same problem.  Go Issue:
81                 // http://code.google.com/p/go/issues/detail?id=5252
82                 url := *req.URL
83                 url.Path = p
84                 p = url.String()
85
86                 w.Header().Set("Location", p)
87                 w.WriteHeader(http.StatusMovedPermanently)
88                 return
89         }
90         var match RouteMatch
91         var handler http.Handler
92         if r.Match(req, &match) {
93                 handler = match.Handler
94                 setVars(req, match.Vars)
95                 setCurrentRoute(req, match.Route)
96         }
97         if handler == nil {
98                 handler = http.NotFoundHandler()
99         }
100         if !r.KeepContext {
101                 defer context.Clear(req)
102         }
103         handler.ServeHTTP(w, req)
104 }
105
106 // Get returns a route registered with the given name.
107 func (r *Router) Get(name string) *Route {
108         return r.getNamedRoutes()[name]
109 }
110
111 // GetRoute returns a route registered with the given name. This method
112 // was renamed to Get() and remains here for backwards compatibility.
113 func (r *Router) GetRoute(name string) *Route {
114         return r.getNamedRoutes()[name]
115 }
116
117 // StrictSlash defines the trailing slash behavior for new routes. The initial
118 // value is false.
119 //
120 // When true, if the route path is "/path/", accessing "/path" will redirect
121 // to the former and vice versa. In other words, your application will always
122 // see the path as specified in the route.
123 //
124 // When false, if the route path is "/path", accessing "/path/" will not match
125 // this route and vice versa.
126 //
127 // Special case: when a route sets a path prefix using the PathPrefix() method,
128 // strict slash is ignored for that route because the redirect behavior can't
129 // be determined from a prefix alone. However, any subrouters created from that
130 // route inherit the original StrictSlash setting.
131 func (r *Router) StrictSlash(value bool) *Router {
132         r.strictSlash = value
133         return r
134 }
135
136 // ----------------------------------------------------------------------------
137 // parentRoute
138 // ----------------------------------------------------------------------------
139
140 // getNamedRoutes returns the map where named routes are registered.
141 func (r *Router) getNamedRoutes() map[string]*Route {
142         if r.namedRoutes == nil {
143                 if r.parent != nil {
144                         r.namedRoutes = r.parent.getNamedRoutes()
145                 } else {
146                         r.namedRoutes = make(map[string]*Route)
147                 }
148         }
149         return r.namedRoutes
150 }
151
152 // getRegexpGroup returns regexp definitions from the parent route, if any.
153 func (r *Router) getRegexpGroup() *routeRegexpGroup {
154         if r.parent != nil {
155                 return r.parent.getRegexpGroup()
156         }
157         return nil
158 }
159
160 func (r *Router) buildVars(m map[string]string) map[string]string {
161         if r.parent != nil {
162                 m = r.parent.buildVars(m)
163         }
164         return m
165 }
166
167 // ----------------------------------------------------------------------------
168 // Route factories
169 // ----------------------------------------------------------------------------
170
171 // NewRoute registers an empty route.
172 func (r *Router) NewRoute() *Route {
173         route := &Route{parent: r, strictSlash: r.strictSlash}
174         r.routes = append(r.routes, route)
175         return route
176 }
177
178 // Handle registers a new route with a matcher for the URL path.
179 // See Route.Path() and Route.Handler().
180 func (r *Router) Handle(path string, handler http.Handler) *Route {
181         return r.NewRoute().Path(path).Handler(handler)
182 }
183
184 // HandleFunc registers a new route with a matcher for the URL path.
185 // See Route.Path() and Route.HandlerFunc().
186 func (r *Router) HandleFunc(path string, f func(http.ResponseWriter,
187         *http.Request)) *Route {
188         return r.NewRoute().Path(path).HandlerFunc(f)
189 }
190
191 // Headers registers a new route with a matcher for request header values.
192 // See Route.Headers().
193 func (r *Router) Headers(pairs ...string) *Route {
194         return r.NewRoute().Headers(pairs...)
195 }
196
197 // Host registers a new route with a matcher for the URL host.
198 // See Route.Host().
199 func (r *Router) Host(tpl string) *Route {
200         return r.NewRoute().Host(tpl)
201 }
202
203 // MatcherFunc registers a new route with a custom matcher function.
204 // See Route.MatcherFunc().
205 func (r *Router) MatcherFunc(f MatcherFunc) *Route {
206         return r.NewRoute().MatcherFunc(f)
207 }
208
209 // Methods registers a new route with a matcher for HTTP methods.
210 // See Route.Methods().
211 func (r *Router) Methods(methods ...string) *Route {
212         return r.NewRoute().Methods(methods...)
213 }
214
215 // Path registers a new route with a matcher for the URL path.
216 // See Route.Path().
217 func (r *Router) Path(tpl string) *Route {
218         return r.NewRoute().Path(tpl)
219 }
220
221 // PathPrefix registers a new route with a matcher for the URL path prefix.
222 // See Route.PathPrefix().
223 func (r *Router) PathPrefix(tpl string) *Route {
224         return r.NewRoute().PathPrefix(tpl)
225 }
226
227 // Queries registers a new route with a matcher for URL query values.
228 // See Route.Queries().
229 func (r *Router) Queries(pairs ...string) *Route {
230         return r.NewRoute().Queries(pairs...)
231 }
232
233 // Schemes registers a new route with a matcher for URL schemes.
234 // See Route.Schemes().
235 func (r *Router) Schemes(schemes ...string) *Route {
236         return r.NewRoute().Schemes(schemes...)
237 }
238
239 // BuildVarsFunc registers a new route with a custom function for modifying
240 // route variables before building a URL.
241 func (r *Router) BuildVarsFunc(f BuildVarsFunc) *Route {
242         return r.NewRoute().BuildVarsFunc(f)
243 }
244
245 // Walk walks the router and all its sub-routers, calling walkFn for each route
246 // in the tree. The routes are walked in the order they were added. Sub-routers
247 // are explored depth-first.
248 func (r *Router) Walk(walkFn WalkFunc) error {
249         return r.walk(walkFn, []*Route{})
250 }
251
252 // SkipRouter is used as a return value from WalkFuncs to indicate that the
253 // router that walk is about to descend down to should be skipped.
254 var SkipRouter = errors.New("skip this router")
255
256 // WalkFunc is the type of the function called for each route visited by Walk.
257 // At every invocation, it is given the current route, and the current router,
258 // and a list of ancestor routes that lead to the current route.
259 type WalkFunc func(route *Route, router *Router, ancestors []*Route) error
260
261 func (r *Router) walk(walkFn WalkFunc, ancestors []*Route) error {
262         for _, t := range r.routes {
263                 if t.regexp == nil || t.regexp.path == nil || t.regexp.path.template == "" {
264                         continue
265                 }
266
267                 err := walkFn(t, r, ancestors)
268                 if err == SkipRouter {
269                         continue
270                 }
271                 for _, sr := range t.matchers {
272                         if h, ok := sr.(*Router); ok {
273                                 err := h.walk(walkFn, ancestors)
274                                 if err != nil {
275                                         return err
276                                 }
277                         }
278                 }
279                 if h, ok := t.handler.(*Router); ok {
280                         ancestors = append(ancestors, t)
281                         err := h.walk(walkFn, ancestors)
282                         if err != nil {
283                                 return err
284                         }
285                         ancestors = ancestors[:len(ancestors)-1]
286                 }
287         }
288         return nil
289 }
290
291 // ----------------------------------------------------------------------------
292 // Context
293 // ----------------------------------------------------------------------------
294
295 // RouteMatch stores information about a matched route.
296 type RouteMatch struct {
297         Route   *Route
298         Handler http.Handler
299         Vars    map[string]string
300 }
301
302 type contextKey int
303
304 const (
305         varsKey contextKey = iota
306         routeKey
307 )
308
309 // Vars returns the route variables for the current request, if any.
310 func Vars(r *http.Request) map[string]string {
311         if rv := context.Get(r, varsKey); rv != nil {
312                 return rv.(map[string]string)
313         }
314         return nil
315 }
316
317 // CurrentRoute returns the matched route for the current request, if any.
318 // This only works when called inside the handler of the matched route
319 // because the matched route is stored in the request context which is cleared
320 // after the handler returns, unless the KeepContext option is set on the
321 // Router.
322 func CurrentRoute(r *http.Request) *Route {
323         if rv := context.Get(r, routeKey); rv != nil {
324                 return rv.(*Route)
325         }
326         return nil
327 }
328
329 func setVars(r *http.Request, val interface{}) {
330         if val != nil {
331                 context.Set(r, varsKey, val)
332         }
333 }
334
335 func setCurrentRoute(r *http.Request, val interface{}) {
336         if val != nil {
337                 context.Set(r, routeKey, val)
338         }
339 }
340
341 // ----------------------------------------------------------------------------
342 // Helpers
343 // ----------------------------------------------------------------------------
344
345 // cleanPath returns the canonical path for p, eliminating . and .. elements.
346 // Borrowed from the net/http package.
347 func cleanPath(p string) string {
348         if p == "" {
349                 return "/"
350         }
351         if p[0] != '/' {
352                 p = "/" + p
353         }
354         np := path.Clean(p)
355         // path.Clean removes trailing slash except for root;
356         // put the trailing slash back if necessary.
357         if p[len(p)-1] == '/' && np != "/" {
358                 np += "/"
359         }
360         return np
361 }
362
363 // uniqueVars returns an error if two slices contain duplicated strings.
364 func uniqueVars(s1, s2 []string) error {
365         for _, v1 := range s1 {
366                 for _, v2 := range s2 {
367                         if v1 == v2 {
368                                 return fmt.Errorf("mux: duplicated route variable %q", v2)
369                         }
370                 }
371         }
372         return nil
373 }
374
375 // checkPairs returns the count of strings passed in, and an error if
376 // the count is not an even number.
377 func checkPairs(pairs ...string) (int, error) {
378         length := len(pairs)
379         if length%2 != 0 {
380                 return length, fmt.Errorf(
381                         "mux: number of parameters must be multiple of 2, got %v", pairs)
382         }
383         return length, nil
384 }
385
386 // mapFromPairsToString converts variadic string parameters to a
387 // string to string map.
388 func mapFromPairsToString(pairs ...string) (map[string]string, error) {
389         length, err := checkPairs(pairs...)
390         if err != nil {
391                 return nil, err
392         }
393         m := make(map[string]string, length/2)
394         for i := 0; i < length; i += 2 {
395                 m[pairs[i]] = pairs[i+1]
396         }
397         return m, nil
398 }
399
400 // mapFromPairsToRegex converts variadic string paramers to a
401 // string to regex map.
402 func mapFromPairsToRegex(pairs ...string) (map[string]*regexp.Regexp, error) {
403         length, err := checkPairs(pairs...)
404         if err != nil {
405                 return nil, err
406         }
407         m := make(map[string]*regexp.Regexp, length/2)
408         for i := 0; i < length; i += 2 {
409                 regex, err := regexp.Compile(pairs[i+1])
410                 if err != nil {
411                         return nil, err
412                 }
413                 m[pairs[i]] = regex
414         }
415         return m, nil
416 }
417
418 // matchInArray returns true if the given string value is in the array.
419 func matchInArray(arr []string, value string) bool {
420         for _, v := range arr {
421                 if v == value {
422                         return true
423                 }
424         }
425         return false
426 }
427
428 // matchMapWithString returns true if the given key/value pairs exist in a given map.
429 func matchMapWithString(toCheck map[string]string, toMatch map[string][]string, canonicalKey bool) bool {
430         for k, v := range toCheck {
431                 // Check if key exists.
432                 if canonicalKey {
433                         k = http.CanonicalHeaderKey(k)
434                 }
435                 if values := toMatch[k]; values == nil {
436                         return false
437                 } else if v != "" {
438                         // If value was defined as an empty string we only check that the
439                         // key exists. Otherwise we also check for equality.
440                         valueExists := false
441                         for _, value := range values {
442                                 if v == value {
443                                         valueExists = true
444                                         break
445                                 }
446                         }
447                         if !valueExists {
448                                 return false
449                         }
450                 }
451         }
452         return true
453 }
454
455 // matchMapWithRegex returns true if the given key/value pairs exist in a given map compiled against
456 // the given regex
457 func matchMapWithRegex(toCheck map[string]*regexp.Regexp, toMatch map[string][]string, canonicalKey bool) bool {
458         for k, v := range toCheck {
459                 // Check if key exists.
460                 if canonicalKey {
461                         k = http.CanonicalHeaderKey(k)
462                 }
463                 if values := toMatch[k]; values == nil {
464                         return false
465                 } else if v != nil {
466                         // If value was defined as an empty string we only check that the
467                         // key exists. Otherwise we also check for equality.
468                         valueExists := false
469                         for _, value := range values {
470                                 if v.MatchString(value) {
471                                         valueExists = true
472                                         break
473                                 }
474                         }
475                         if !valueExists {
476                                 return false
477                         }
478                 }
479         }
480         return true
481 }