The github.com/gorilla/mux package contains another implementation of Handler that enhances the capabilities of the standard ServeMux:
- Better URL matching to handlers using any element from the URL, including schema, method, host, or query values.
- URL elements, such as host, paths, and query keys can have placeholders (which can also use regular expressions).
- Routes can be defined hierarchically with the help of subroutes, nested routes which test a part of the path.
- Handlers can be also used as middleware, before the main handler, for all paths or for a subset of paths.
Let's start with an example of matching using other path elements:
r := mux.NewRouter()
// only local requests
r.Host("localhost:3000")
// only when some header is present
r.Headers("X-Requested-With", "XMLHttpRequest")
only when a query parameter is specified
r.Queries("access_key", "0x20")
Variables are another really useful feature, that allow us to specify placeholders, and get their values with the auxiliary function, mux.Vars, as shown in the following example:
r := mux.NewRouter()
r.HandleFunc("/products/", ProductsHandler)
r.HandleFunc("/products/{key}/", ProductHandler)
r.HandleFunc("/products/{key}/details", ProductDetailsHandler)
...
// inside an handler
vars := mux.Vars(request)
key:= vars["key"]
Subrouter is another helpful function to group same prefixes routes. This allows us to simplify the previous code to the following code snippet:
r := mux.NewRouter() s := r.PathPrefix("/products").Subrouter() s.HandleFunc("/", ProductsHandler) s.HandleFunc("/{key}/", ProductHandler) s.HandleFunc("/{key}/details", ProductDetailsHandler)
Middleware is also very useful when combined with subroutes, to execute some common tasks as authentication and verification:
r := mux.NewRouter()
pub := r.PathPrefix("/public").Subrouter()
pub.HandleFunc("/login", LoginHandler)
priv := r.PathPrefix("/private").Subrouter()
priv.Use(AuthHandler)
priv.HandleFunc("/profile", ProfileHandler)
priv.HandleFunc("/logout", LogoutHandler)