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