1 changed files with 199 additions and 2 deletions
@ -1,7 +1,204 @@ |
|||||||
mux |
mux |
||||||
=== |
=== |
||||||
|
[](https://godoc.org/github.com/gorilla/securecookie) |
||||||
[](https://travis-ci.org/gorilla/mux) |
[](https://travis-ci.org/gorilla/mux) |
||||||
|
|
||||||
gorilla/mux is a powerful URL router and dispatcher. |
Package gorilla/mux implements a request router and dispatcher. |
||||||
|
|
||||||
Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux |
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: |
||||||
|
|
||||||
|
* Requests can be matched based on URL host, path, path prefix, schemes, |
||||||
|
header and query values, HTTP methods or using custom matchers. |
||||||
|
* URL hosts and paths can have variables with an optional regular |
||||||
|
expression. |
||||||
|
* Registered URLs can be built, or "reversed", which helps maintaining |
||||||
|
references to resources. |
||||||
|
* 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. |
||||||
|
* It implements the http.Handler interface so it is compatible with the |
||||||
|
standard http.ServeMux. |
||||||
|
|
||||||
|
Let's start registering a couple of URL paths and handlers: |
||||||
|
|
||||||
|
func main() { |
||||||
|
r := mux.NewRouter() |
||||||
|
r.HandleFunc("/", HomeHandler) |
||||||
|
r.HandleFunc("/products", ProductsHandler) |
||||||
|
r.HandleFunc("/articles", ArticlesHandler) |
||||||
|
http.Handle("/", r) |
||||||
|
} |
||||||
|
|
||||||
|
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. |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
r.HandleFunc("/products/{key}", ProductHandler) |
||||||
|
r.HandleFunc("/articles/{category}/", ArticlesCategoryHandler) |
||||||
|
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler) |
||||||
|
|
||||||
|
The names are used to create a map of route variables which can be retrieved |
||||||
|
calling mux.Vars(): |
||||||
|
|
||||||
|
vars := mux.Vars(request) |
||||||
|
category := vars["category"] |
||||||
|
|
||||||
|
And this is all you need to know about the basic usage. More advanced options |
||||||
|
are explained below. |
||||||
|
|
||||||
|
Routes can also be restricted to a domain or subdomain. Just define a host |
||||||
|
pattern to be matched. They can also have variables: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
// Only matches if domain is "www.domain.com". |
||||||
|
r.Host("www.domain.com") |
||||||
|
// Matches a dynamic subdomain. |
||||||
|
r.Host("{subdomain:[a-z]+}.domain.com") |
||||||
|
|
||||||
|
There are several other matchers that can be added. To match path prefixes: |
||||||
|
|
||||||
|
r.PathPrefix("/products/") |
||||||
|
|
||||||
|
...or HTTP methods: |
||||||
|
|
||||||
|
r.Methods("GET", "POST") |
||||||
|
|
||||||
|
...or URL schemes: |
||||||
|
|
||||||
|
r.Schemes("https") |
||||||
|
|
||||||
|
...or header values: |
||||||
|
|
||||||
|
r.Headers("X-Requested-With", "XMLHttpRequest") |
||||||
|
|
||||||
|
...or query values: |
||||||
|
|
||||||
|
r.Queries("key", "value") |
||||||
|
|
||||||
|
...or to use a custom matcher function: |
||||||
|
|
||||||
|
r.MatcherFunc(func(r *http.Request, rm *RouteMatch) bool { |
||||||
|
return r.ProtoMajor == 0 |
||||||
|
}) |
||||||
|
|
||||||
|
...and finally, it is possible to combine several matchers in a single route: |
||||||
|
|
||||||
|
r.HandleFunc("/products", ProductsHandler). |
||||||
|
Host("www.domain.com"). |
||||||
|
Methods("GET"). |
||||||
|
Schemes("http") |
||||||
|
|
||||||
|
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". |
||||||
|
|
||||||
|
For example, let's say we have several URLs that should only match when the |
||||||
|
host is "www.domain.com". Create a route for that host and get a "subrouter" |
||||||
|
from it: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
s := r.Host("www.domain.com").Subrouter() |
||||||
|
|
||||||
|
Then register routes in the subrouter: |
||||||
|
|
||||||
|
s.HandleFunc("/products/", ProductsHandler) |
||||||
|
s.HandleFunc("/products/{key}", ProductHandler) |
||||||
|
s.HandleFunc("/articles/{category}/{id:[0-9]+}"), ArticleHandler) |
||||||
|
|
||||||
|
The three URL paths we registered above will only be tested if the domain is |
||||||
|
"www.domain.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. |
||||||
|
|
||||||
|
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. |
||||||
|
|
||||||
|
There's one more thing about subroutes. When a subrouter has a path prefix, |
||||||
|
the inner routes use it as base for their paths: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
s := r.PathPrefix("/products").Subrouter() |
||||||
|
// "/products/" |
||||||
|
s.HandleFunc("/", ProductsHandler) |
||||||
|
// "/products/{key}/" |
||||||
|
s.HandleFunc("/{key}/", ProductHandler) |
||||||
|
// "/products/{key}/details" |
||||||
|
s.HandleFunc("/{key}/details", ProductDetailsHandler) |
||||||
|
|
||||||
|
Now let's see how to build registered URLs. |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
r.HandleFunc("/articles/{category}/{id:[0-9]+}", ArticleHandler). |
||||||
|
Name("article") |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
url, err := r.Get("article").URL("category", "technology", "id", "42") |
||||||
|
|
||||||
|
...and the result will be a url.URL with the following path: |
||||||
|
|
||||||
|
"/articles/technology/42" |
||||||
|
|
||||||
|
This also works for host variables: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
r.Host("{subdomain}.domain.com"). |
||||||
|
Path("/articles/{category}/{id:[0-9]+}"). |
||||||
|
HandlerFunc(ArticleHandler). |
||||||
|
Name("article") |
||||||
|
|
||||||
|
// url.String() will be "http://news.domain.com/articles/technology/42" |
||||||
|
url, err := r.Get("article").URL("subdomain", "news", |
||||||
|
"category", "technology", |
||||||
|
"id", "42") |
||||||
|
|
||||||
|
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. |
||||||
|
|
||||||
|
Regex support also exists for matching Headers within a route. For example, we could do: |
||||||
|
|
||||||
|
r.HeadersRegexp("Content-Type", "application/(text|json)") |
||||||
|
|
||||||
|
...and the route will match both requests with a Content-Type of `application/json` as well as |
||||||
|
`application/text` |
||||||
|
|
||||||
|
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: |
||||||
|
|
||||||
|
// "http://news.domain.com/" |
||||||
|
host, err := r.Get("article").URLHost("subdomain", "news") |
||||||
|
|
||||||
|
// "/articles/technology/42" |
||||||
|
path, err := r.Get("article").URLPath("category", "technology", "id", "42") |
||||||
|
|
||||||
|
And if you use subrouters, host and path defined separately can be built |
||||||
|
as well: |
||||||
|
|
||||||
|
r := mux.NewRouter() |
||||||
|
s := r.Host("{subdomain}.domain.com").Subrouter() |
||||||
|
s.Path("/articles/{category}/{id:[0-9]+}"). |
||||||
|
HandlerFunc(ArticleHandler). |
||||||
|
Name("article") |
||||||
|
|
||||||
|
// "http://news.domain.com/articles/technology/42" |
||||||
|
url, err := r.Get("article").URL("subdomain", "news", |
||||||
|
"category", "technology", |
||||||
|
"id", "42") |
||||||
|
|||||||
Loading…
Reference in new issue