8 changed files with 621 additions and 88 deletions
-
5weed/Godeps/Godeps.json
-
24weed/vendor/github.com/gorilla/context/.travis.yml
-
23weed/vendor/github.com/gorilla/mux/.travis.yml
-
241weed/vendor/github.com/gorilla/mux/README.md
-
21weed/vendor/github.com/gorilla/mux/doc.go
-
148weed/vendor/github.com/gorilla/mux/mux.go
-
96weed/vendor/github.com/gorilla/mux/regexp.go
-
133weed/vendor/github.com/gorilla/mux/route.go
@ -1,9 +1,19 @@ |
|||
language: go |
|||
sudo: false |
|||
|
|||
go: |
|||
- 1.0 |
|||
- 1.1 |
|||
- 1.2 |
|||
- 1.3 |
|||
- 1.4 |
|||
- tip |
|||
matrix: |
|||
include: |
|||
- go: 1.3 |
|||
- go: 1.4 |
|||
- go: 1.5 |
|||
- go: 1.6 |
|||
- go: tip |
|||
|
|||
install: |
|||
- go get golang.org/x/tools/cmd/vet |
|||
|
|||
script: |
|||
- go get -t -v ./... |
|||
- diff -u <(echo -n) <(gofmt -d .) |
|||
- go tool vet . |
|||
- go test -v -race ./... |
|||
@ -1,7 +1,20 @@ |
|||
language: go |
|||
sudo: false |
|||
|
|||
go: |
|||
- 1.0 |
|||
- 1.1 |
|||
- 1.2 |
|||
- tip |
|||
matrix: |
|||
include: |
|||
- go: 1.2 |
|||
- go: 1.3 |
|||
- go: 1.4 |
|||
- go: 1.5 |
|||
- go: 1.6 |
|||
- go: tip |
|||
|
|||
install: |
|||
- go get golang.org/x/tools/cmd/vet |
|||
|
|||
script: |
|||
- go get -t -v ./... |
|||
- diff -u <(echo -n) <(gofmt -d .) |
|||
- go tool vet . |
|||
- go test -v -race ./... |
|||
@ -1,7 +1,242 @@ |
|||
mux |
|||
=== |
|||
[](https://travis-ci.org/gorilla/mux) |
|||
[](https://godoc.org/github.com/gorilla/mux) |
|||
[](https://travis-ci.org/gorilla/mux) |
|||
|
|||
gorilla/mux is a powerful URL router and dispatcher. |
|||
http://www.gorillatoolkit.org/pkg/mux |
|||
|
|||
Read the full documentation here: http://www.gorillatoolkit.org/pkg/mux |
|||
Package `gorilla/mux` implements a request router and dispatcher. |
|||
|
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
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()`: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
r := mux.NewRouter() |
|||
// Only matches if domain is "www.example.com". |
|||
r.Host("www.example.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: |
|||
|
|||
```go |
|||
r.PathPrefix("/products/") |
|||
``` |
|||
|
|||
...or HTTP methods: |
|||
|
|||
```go |
|||
r.Methods("GET", "POST") |
|||
``` |
|||
|
|||
...or URL schemes: |
|||
|
|||
```go |
|||
r.Schemes("https") |
|||
``` |
|||
|
|||
...or header values: |
|||
|
|||
```go |
|||
r.Headers("X-Requested-With", "XMLHttpRequest") |
|||
``` |
|||
|
|||
...or query values: |
|||
|
|||
```go |
|||
r.Queries("key", "value") |
|||
``` |
|||
|
|||
...or to use a custom matcher function: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
r.HandleFunc("/products", ProductsHandler). |
|||
Host("www.example.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.example.com`. Create a route for that host and get a "subrouter" from it: |
|||
|
|||
```go |
|||
r := mux.NewRouter() |
|||
s := r.Host("www.example.com").Subrouter() |
|||
``` |
|||
|
|||
Then register routes in the subrouter: |
|||
|
|||
```go |
|||
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.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. |
|||
|
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
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: |
|||
|
|||
```go |
|||
// "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: |
|||
|
|||
```go |
|||
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") |
|||
``` |
|||
|
|||
## Full Example |
|||
|
|||
Here's a complete, runnable example of a small `mux` based server: |
|||
|
|||
```go |
|||
package main |
|||
|
|||
import ( |
|||
"net/http" |
|||
|
|||
"github.com/gorilla/mux" |
|||
) |
|||
|
|||
func YourHandler(w http.ResponseWriter, r *http.Request) { |
|||
w.Write([]byte("Gorilla!\n")) |
|||
} |
|||
|
|||
func main() { |
|||
r := mux.NewRouter() |
|||
// Routes consist of a path and a handler function. |
|||
r.HandleFunc("/", YourHandler) |
|||
|
|||
// Bind to a port and pass our router in |
|||
http.ListenAndServe(":8000", r) |
|||
} |
|||
``` |
|||
|
|||
## License |
|||
|
|||
BSD licensed. See the LICENSE file for details. |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue