]>
Commit | Line | Data |
---|---|---|
9b12e4fe JC |
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 | /* | |
6 | Package gorilla/mux implements a request router and dispatcher. | |
7 | ||
8 | The name mux stands for "HTTP request multiplexer". Like the standard | |
9 | http.ServeMux, mux.Router matches incoming requests against a list of | |
10 | registered routes and calls a handler for the route that matches the URL | |
11 | or other conditions. The main features are: | |
12 | ||
13 | * Requests can be matched based on URL host, path, path prefix, schemes, | |
14 | header and query values, HTTP methods or using custom matchers. | |
15 | * URL hosts and paths can have variables with an optional regular | |
16 | expression. | |
17 | * Registered URLs can be built, or "reversed", which helps maintaining | |
18 | references to resources. | |
19 | * Routes can be used as subrouters: nested routes are only tested if the | |
20 | parent route matches. This is useful to define groups of routes that | |
21 | share common conditions like a host, a path prefix or other repeated | |
22 | attributes. As a bonus, this optimizes request matching. | |
23 | * It implements the http.Handler interface so it is compatible with the | |
24 | standard http.ServeMux. | |
25 | ||
26 | Let's start registering a couple of URL paths and handlers: | |
27 | ||
28 | func main() { | |
29 | r := mux.NewRouter() | |
30 | r.HandleFunc("/", HomeHandler) | |
31 | r.HandleFunc("/products", ProductsHandler) | |
32 | r.HandleFunc("/articles", ArticlesHandler) | |
33 | http.Handle("/", r) | |
34 | } | |
35 | ||
36 | Here we register three routes mapping URL paths to handlers. This is | |
37 | equivalent to how http.HandleFunc() works: if an incoming request URL matches | |
38 | one of the paths, the corresponding handler is called passing | |
39 | (http.ResponseWriter, *http.Request) as parameters. | |
40 | ||
41 | Paths can have variables. They are defined using the format {name} or | |
42 | {name:pattern}. If a regular expression pattern is not defined, the matched | |
43 | variable will be anything until the next slash. For example: | |
44 | ||
45 | r := mux.NewRouter() | |
46 | r.HandleFunc("/products/{key}", ProductHandler) | |
47 | r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) | |
48 | r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) | |
49 | ||
50 | The names are used to create a map of route variables which can be retrieved | |
51 | calling mux.Vars(): | |
52 | ||
53 | vars := mux.Vars(request) | |
54 | category := vars["category"] | |
55 | ||
56 | And this is all you need to know about the basic usage. More advanced options | |
57 | are explained below. | |
58 | ||
59 | Routes can also be restricted to a domain or subdomain. Just define a host | |
60 | pattern to be matched. They can also have variables: | |
61 | ||
62 | r := mux.NewRouter() | |
63 | // Only matches if domain is "www.example.com". | |
64 | r.Host("www.example.com") | |
65 | // Matches a dynamic subdomain. | |
66 | r.Host("{subdomain:[a-z]+}.domain.com") | |
67 | ||
68 | There are several other matchers that can be added. To match path prefixes: | |
69 | ||
70 | r.PathPrefix("/products/") | |
71 | ||
72 | ...or HTTP methods: | |
73 | ||
74 | r.Methods("GET", "POST") | |
75 | ||
76 | ...or URL schemes: | |
77 | ||
78 | r.Schemes("https") | |
79 | ||
80 | ...or header values: | |
81 | ||
82 | r.Headers("X-Requested-With", "XMLHttpRequest") | |
83 | ||
84 | ...or query values: | |
85 | ||
86 | r.Queries("key", "value") | |
87 | ||
88 | ...or to use a custom matcher function: | |
89 | ||
90 | r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { | |
91 | return r.ProtoMajor == 0 | |
92 | }) | |
93 | ||
94 | ...and finally, it is possible to combine several matchers in a single route: | |
95 | ||
96 | r.HandleFunc("/products", ProductsHandler). | |
97 | Host("www.example.com"). | |
98 | Methods("GET"). | |
99 | Schemes("http") | |
100 | ||
101 | Setting the same matching conditions again and again can be boring, so we have | |
102 | a way to group several routes that share the same requirements. | |
103 | We call it "subrouting". | |
104 | ||
105 | For example, let's say we have several URLs that should only match when the | |
106 | host is "www.example.com". Create a route for that host and get a "subrouter" | |
107 | from it: | |
108 | ||
109 | r := mux.NewRouter() | |
110 | s := r.Host("www.example.com").Subrouter() | |
111 | ||
112 | Then register routes in the subrouter: | |
113 | ||
114 | s.HandleFunc("/products/", ProductsHandler) | |
115 | s.HandleFunc("/products/{key}", ProductHandler) | |
116 | s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) | |
117 | ||
118 | The three URL paths we registered above will only be tested if the domain is | |
119 | "www.example.com", because the subrouter is tested first. This is not | |
120 | only convenient, but also optimizes request matching. You can create | |
121 | subrouters combining any attribute matchers accepted by a route. | |
122 | ||
123 | Subrouters can be used to create domain or path "namespaces": you define | |
124 | subrouters in a central place and then parts of the app can register its | |
125 | paths relatively to a given subrouter. | |
126 | ||
127 | There's one more thing about subroutes. When a subrouter has a path prefix, | |
128 | the inner routes use it as base for their paths: | |
129 | ||
130 | r := mux.NewRouter() | |
131 | s := r.PathPrefix("/products").Subrouter() | |
132 | // "/products/" | |
133 | s.HandleFunc("/", ProductsHandler) | |
134 | // "/products/{key}/" | |
135 | s.HandleFunc("/{key}/", ProductHandler) | |
136 | // "/products/{key}/details" | |
137 | s.HandleFunc("/{key}/details", ProductDetailsHandler) | |
138 | ||
139 | Now let's see how to build registered URLs. | |
140 | ||
141 | Routes can be named. All routes that define a name can have their URLs built, | |
142 | or "reversed". We define a name calling Name() on a route. For example: | |
143 | ||
144 | r := mux.NewRouter() | |
145 | r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). | |
146 | Name("article") | |
147 | ||
148 | To build a URL, get the route and call the URL() method, passing a sequence of | |
149 | key/value pairs for the route variables. For the previous route, we would do: | |
150 | ||
151 | url, err := r.Get("article").URL("category", "technology", "id", "42") | |
152 | ||
153 | ...and the result will be a url.URL with the following path: | |
154 | ||
155 | "/articles/technology/42" | |
156 | ||
157 | This also works for host variables: | |
158 | ||
159 | r := mux.NewRouter() | |
160 | r.Host("{subdomain}.domain.com"). | |
161 | Path("/articles/{category}/{id:[0-9]+}"). | |
162 | HandlerFunc(ArticleHandler). | |
163 | Name("article") | |
164 | ||
165 | // url.String() will be "http://news.domain.com/articles/technology/42" | |
166 | url, err := r.Get("article").URL("subdomain", "news", | |
167 | "category", "technology", | |
168 | "id", "42") | |
169 | ||
170 | All variables defined in the route are required, and their values must | |
171 | conform to the corresponding patterns. These requirements guarantee that a | |
172 | generated URL will always match a registered route -- the only exception is | |
173 | for explicitly defined "build-only" routes which never match. | |
174 | ||
175 | Regex support also exists for matching Headers within a route. For example, we could do: | |
176 | ||
177 | r.HeadersRegexp("Content-Type", "application/(text|json)") | |
178 | ||
179 | ...and the route will match both requests with a Content-Type of `application/json` as well as | |
180 | `application/text` | |
181 | ||
182 | There's also a way to build only the URL host or path for a route: | |
183 | use the methods URLHost() or URLPath() instead. For the previous route, | |
184 | we would do: | |
185 | ||
186 | // "http://news.domain.com/" | |
187 | host, err := r.Get("article").URLHost("subdomain", "news") | |
188 | ||
189 | // "/articles/technology/42" | |
190 | path, err := r.Get("article").URLPath("category", "technology", "id", "42") | |
191 | ||
192 | And if you use subrouters, host and path defined separately can be built | |
193 | as well: | |
194 | ||
195 | r := mux.NewRouter() | |
196 | s := r.Host("{subdomain}.domain.com").Subrouter() | |
197 | s.Path("/articles/{category}/{id:[0-9]+}"). | |
198 | HandlerFunc(ArticleHandler). | |
199 | Name("article") | |
200 | ||
201 | // "http://news.domain.com/articles/technology/42" | |
202 | url, err := r.Get("article").URL("subdomain", "news", | |
203 | "category", "technology", | |
204 | "id", "42") | |
205 | */ | |
206 | package mux |