Documentation
¶
Overview ¶
Package mux implements a multiplexer for http requests. The multiplexer may replace http.ServeMux because it extends the pattern language by HTTP methods and wildcard variables. Those variables can be accessed by the selected HTTP request handlers, saving the handlers from parsing the path again. Those improvements are discussed in a Go language discussion.
The multiplexer is fully functional. It is not widely tested and has not been optimized. Please report any issues you may encounter in module repo
The multiplexer can be simply declared.
var m mux.Mux
The multiplexer supports the ServeHTTP method, so it can be used everywhere a net/http.Handler can be used.
The methods Mux.Handle and Mux.HandleFunc register a net/http.Handler or a handler function for a specific pattern. The patterns supported by net/http.ServeMux can be used without modification.
A new feature is the support for methods, which need to precede host/path pattern by a space.
m.Handle("GET example.org/images/", imagesHandler)
The methods GET, HEAD, POST, PATCH, PUT, CONNECT, OPTIONS and TRACE are supported.
The other new feature is the support for wildcard variable names, which can replace the method, host or segments in the path component.
m.Handle("{method} {host}/buckets/{bucketID}/objects/{objectID}", h)
Suffix wildcards are can be used additionally, which capture the rest of the request path.
m.Handle("/users/{userSpec...}", h)
If the wildcard doesn't define a variable name, it acts still as a wildcard but will not capture it. So following calls to Handle are valid.
m.Handle("{} {}/buckets/{bucketID}/objects/{}". h) m.Handle("{} {host}/users/{...}", h)
The multiplexer allows different variables at the same position.
m.Handle("/buckets/{bucket2ID}/objects/{objectID}", h2o) m.Handle("/buckets/{bucket1ID}/objects/{objectID}", h1o) m.Handle("/buckets/{bucket2ID}/meta/", h2m)
However the variables will be ordered in lexicographically order. The multiplexer will route the a request with path /buckets/1/objects/1 always to the handler h1o. The handler h2o will not be reachable. However a request with path /buckets/1/meta/green will be routed to h2m.
The order of the pattern resolution is independent of the order of the Handle calls. A consequence is that redundant patterns lead to panics, if they would simply overwrite the handlers the sequence of the callers would influence the resolution.
The multiplexer doesn't support two suffix wildcards with different variables. Following calls will lead to a panic of the second call.
m.Handle("/users/{userSpec...}", h1) m.Handle("/users/{uSpec...}", h2) // Call will panic!
The multiplexer keeps the redirect logic of a path /images to /images/ if only the second pattern has been registered. This is also valid for suffix wildcards as in /images/{imageSpec...}.
The multiplexer supports a special marker {$}. The pattern registered with
m.Handle("/{$}", h1)
will only resolve calls to a path with a single slash because
m.Handle("/", h2)
will resolve to all requests unless other patterns have been registered. The multiplexer always prefers the most specific pattern that matches.
The handler can access the wildcard variables by calling the Vars function on the provided request value. The returned map is always initialized, if no variables have been matched the map will be empty.
vmap := mux.Vars(request) log.Printf("bucketID: %s", vmap["bucketID"]) log.Printf("objectID: %s", vmap["objectID"])
If the path cannot be found the multiplexer returns 404 page not found. If the method is unsupported, the status returned is 405 method not allowed.
Example ¶
package main import ( "encoding/json" "fmt" "io" "log" "net/http" "net/http/httptest" "github.com/ulikunitz/mux" ) func main() { type out struct { Method string Path string VarMap map[string]string } h := func(w http.ResponseWriter, r *http.Request) { header := w.Header() header.Set("Content-Type", "application/json") out := out{ Method: r.Method, Path: r.URL.Path, VarMap: mux.Vars(r), } data, err := json.MarshalIndent(&out, "", " ") if err != nil { http.Error(w, fmt.Sprintf("error %s", err), http.StatusInternalServerError) return } _, err = w.Write(data) if err != nil { panic(fmt.Errorf("w.Write(data) error %s", err)) } } m := new(mux.Mux) m.HandleFunc("{method} /item/{itemNr}", h) m.HandleFunc("/foo/{remainder...}", h) ts := httptest.NewTLSServer(m) defer ts.Close() client := ts.Client() url := ts.URL + "/item/1" resp, err := client.Get(url) if err != nil { log.Fatalf("client.Get(%q) error %s", url, err) } defer resp.Body.Close() data, err := io.ReadAll(resp.Body) if err != nil { log.Fatalf("io.ReadAll(resp.Body) error %s", err) } fmt.Printf("%s", data) }
Output: { "Method": "GET", "Path": "/item/1", "VarMap": { "itemNr": "1", "method": "GET" } }
Index ¶
- Variables
- func Vars(r *http.Request) map[string]string
- type Mux
- func (mux *Mux) Handle(pattern string, handler http.Handler)
- func (mux *Mux) HandleFunc(pattern string, handler func(http.ResponseWriter, *http.Request))
- func (mux *Mux) HandlerReq(r *http.Request) (h http.Handler, pattern string, s *http.Request)
- func (mux *Mux) ServeHTTP(w http.ResponseWriter, r *http.Request)
Examples ¶
Constants ¶
This section is empty.
Variables ¶
var ErrPattern = errors.New("mux: invalid pattern")
ErrPattern indicates that an invalid pattern has been provided. The errors provided by the panics of the Mux.Handle and Mux.HandleFunc methods wrap this error.
Functions ¶
Types ¶
type Mux ¶
type Mux struct {
// contains filtered or unexported fields
}
Mux is the type for the multiplexer. It holds a tree resolving all patterns provided.
func (*Mux) Handle ¶
Handle registers the provided handler for the given pattern. The function might panic if the patterns contain errors or are redundant. The sequence of the Handle calls has no influence on the pattern resolution. (Note that this condition would be violated, if redundant patterns would not cause a panic.)
func (*Mux) HandleFunc ¶
HandleFunc registers the handler function handler with the given pattern. It calls Mux.Handle and supports the semantics for the pattern.
func (*Mux) HandlerReq ¶
HandlerReq returns the handler and possibly a new request. The return of the request is required because the variable segment map has to be attached to the context of the request.