@@ 2,9 2,9 @@
//
// The multiplexer in this package is capable of routing based on request method
// and a fixed rooted path (/favicon.ico) or subtree (/images/) which may
-// include typed path parameters and wildcards (see "URL Parameters").
+// include typed path parameters and wildcards.
//
-// m := mux.New(
+// serveMux := mux.New(
// mux.Handle(http.MethodGet, "/profile/{username string}", http.NotFoundHandler()),
// mux.HandleFunc(http.MethodGet, "/profile", http.RedirectHandler("/profile/me", http.StatusPermanentRedirect)),
// mux.Handle(http.MethodPost, "/logout", logoutHandler()),
@@ 31,9 31,6 @@
//
// /file/{p path}
//
-// To retrieve the value of named path parameters see the Param function and the
-// examples.
-//
// Two paths with different typed variable parameters (including static routes)
// in the same position are not allowed.
// Attempting to register any two of the following routes will panic:
@@ 43,4 40,53 @@
// /user/{float}/edit
// /user/{b string}/edit
// /user/me
+//
+// When a route is matched, the value of each named path parameter is stored on
+// the request context.
+// To retrieve the value of named path parameters from within a handler, the
+// Param function can be used.
+//
+// pinfo := mux.Param(req, "username")
+// fmt.Println("Got username:", pinfo.Raw)
+//
+// For more information, see the ParamInfo type and the examples.
+//
+// Normalization
+//
+// It's common to normalize routes on HTTP servers.
+// For example, a username may need to match the Username Case Mapped profile of
+// PRECIS (RFC 8265), or the name of an identifier may need to always be lower
+// cased.
+// This can be tedious and error prone even if you have enough information to
+// figure out what path components need to be replaced, and many HTTP routers
+// don't even give you enough information to match path components to their
+// original route parameters.
+// To make this easier, this package provides the Path and WithParam functions.
+// WithParam is used to attach a new context to the context tree with
+// replacement values for existing route parameters, and Path is used to
+// re-render the path from the original route using the request context.
+// If the resulting path is different from req.URL.Path, a redirect can be
+// issued or some other corrective action can be applied.
+//
+// serveMux := mux.New(
+// mux.Handle(http.MethodGet, "/profile/{username string}", func(w http.ResponseWriter, r *http.Request) {
+// username := mux.Param(r, "username")
+// // You probably want to use the Username Case Mapped profile from the
+// // golang.org/x/text/secure/precis package instead.
+// normalized := strings.ToLower(username.Raw)
+// if normalized != username.Raw {
+// r = mux.WithParam(r, username.Name, normalized)
+// newPath, err := mux.Path(r)
+// if err != nil {
+// panic(fmt.Errorf("mux_test: error creating canonicalized path: %w", err))
+// }
+// http.Redirect(w, r, newPath, http.StatusPermanentRedirect)
+// return
+// }
+//
+// fmt.Fprintln(w, "The canonical username is:", pinfo.Raw)
+// }),
+// )
+//
+// For more information, see the examples.
package mux // import "code.soquee.net/mux"
@@ 13,7 13,7 @@ import (
)
func Example_path() {
- m := mux.New(
+ serveMux := mux.New(
mux.HandleFunc("GET", "/sha256/{wildcard path}", func(w http.ResponseWriter, r *http.Request) {
val := mux.Param(r, "wildcard")
sum := sha256.Sum256([]byte(val.Raw))
@@ 21,7 21,7 @@ func Example_path() {
}),
)
- server := httptest.NewServer(m)
+ server := httptest.NewServer(serveMux)
resp, err := http.Get(server.URL + "/sha256/a/b")
if err != nil {
panic(err)
@@ 34,11 34,11 @@ func Example_path() {
}
func Example_normalization() {
- m := mux.New(
+ serveMux := mux.New(
mux.HandleFunc("GET", "/profile/{username string}/personal", func(w http.ResponseWriter, r *http.Request) {
username := mux.Param(r, "username")
// You probably want to use the Username Case Mapped profile from the
- // golang.org/x/text/secure/precis package instead of lowercasing.
+ // golang.org/x/text/secure/precis package instead.
normalized := strings.ToLower(username.Raw)
// If the username is not canonical, redirect.
@@ 57,7 57,7 @@ func Example_normalization() {
}),
)
- server := httptest.NewServer(m)
+ server := httptest.NewServer(serveMux)
defer server.Close()
resp, err := http.Get(server.URL + "/profile/Me/personal")