Skip to content

Commit 90276c2

Browse files
committed
net/http: document new ServeMux patterns
Updates #61410. Change-Id: Ib9dd8ebca43cec6e27c6fdfcf01ee6a1539c2fa0 Reviewed-on: https://go-review.googlesource.com/c/go/+/530481 Reviewed-by: Eli Bendersky <[email protected]> Run-TryBot: Jonathan Amsterdam <[email protected]> Reviewed-by: Alan Donovan <[email protected]> Reviewed-by: Damien Neil <[email protected]> TryBot-Result: Gopher Robot <[email protected]>
1 parent 95ef1e7 commit 90276c2

File tree

1 file changed

+112
-30
lines changed

1 file changed

+112
-30
lines changed

src/net/http/server.go

Lines changed: 112 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -2306,44 +2306,123 @@ func RedirectHandler(url string, code int) Handler {
23062306
return &redirectHandler{url, code}
23072307
}
23082308

2309-
// TODO(jba): rewrite the following doc for enhanced patterns (proposal
2310-
// https://go.dev/issue/61410).
2311-
23122309
// ServeMux is an HTTP request multiplexer.
23132310
// It matches the URL of each incoming request against a list of registered
23142311
// patterns and calls the handler for the pattern that
23152312
// most closely matches the URL.
23162313
//
2317-
// Patterns name fixed, rooted paths, like "/favicon.ico",
2318-
// or rooted subtrees, like "/images/" (note the trailing slash).
2319-
// Longer patterns take precedence over shorter ones, so that
2320-
// if there are handlers registered for both "/images/"
2321-
// and "/images/thumbnails/", the latter handler will be
2322-
// called for paths beginning with "/images/thumbnails/" and the
2323-
// former will receive requests for any other paths in the
2324-
// "/images/" subtree.
2325-
//
2326-
// Note that since a pattern ending in a slash names a rooted subtree,
2327-
// the pattern "/" matches all paths not matched by other registered
2328-
// patterns, not just the URL with Path == "/".
2329-
//
2330-
// If a subtree has been registered and a request is received naming the
2331-
// subtree root without its trailing slash, ServeMux redirects that
2332-
// request to the subtree root (adding the trailing slash). This behavior can
2333-
// be overridden with a separate registration for the path without
2334-
// the trailing slash. For example, registering "/images/" causes ServeMux
2314+
// # Patterns
2315+
//
2316+
// Patterns can match the method, host and path of a request.
2317+
// Some examples:
2318+
//
2319+
// - "/index.html" matches the path "/index.html" for any host and method.
2320+
// - "GET /static/" matches a GET request whose path begins with "/static/".
2321+
// - "example.com/" matches any request to the host "example.com".
2322+
// - "example.com/{$}" matches requests with host "example.com" and path "/".
2323+
// - "/b/{bucket}/o/{objectname...}" matches paths whose first segment is "b"
2324+
// and whose third segment is "o". The name "bucket" denotes the second
2325+
// segment and "objectname" denotes the remainder of the path.
2326+
//
2327+
// In general, a pattern looks like
2328+
//
2329+
// [METHOD ][HOST]/[PATH]
2330+
//
2331+
// All three parts are optional; "/" is a valid pattern.
2332+
// If METHOD is present, it must be followed by a single space.
2333+
//
2334+
// Literal (that is, non-wildcard) parts of a pattern match
2335+
// the corresponding parts of a request case-sensitively.
2336+
//
2337+
// A pattern with no method matches every method. A pattern
2338+
// with the method GET matches both GET and HEAD requests.
2339+
// Otherwise, the method must match exactly.
2340+
//
2341+
// A pattern with no host matches every host.
2342+
// A pattern with a host matches URLs on that host only.
2343+
//
2344+
// A path can include wildcard segments of the form {NAME} or {NAME...}.
2345+
// For example, "/b/{bucket}/o/{objectname...}".
2346+
// The wildcard name must be a valid Go identifier.
2347+
// Wildcards must be full path segments: they must be preceded by a slash and followed by
2348+
// either a slash or the end of the string.
2349+
// For example, "/b_{bucket}" is not a valid pattern.
2350+
//
2351+
// Normally a wildcard matches only a single path segment,
2352+
// ending at the next literal slash (not %2F) in the request URL.
2353+
// But if the "..." is present, then the wildcard matches the remainder of the URL path, including slashes.
2354+
// (Therefore it is invalid for a "..." wildcard to appear anywhere but at the end of a pattern.)
2355+
// The match for a wildcard can be obtained by calling [Request.PathValue] with the wildcard's name.
2356+
// A trailing slash in a path acts as an anonymous "..." wildcard.
2357+
//
2358+
// The special wildcard {$} matches only the end of the URL.
2359+
// For example, the pattern "/{$}" matches only the path "/",
2360+
// whereas the pattern "/" matches every path.
2361+
//
2362+
// For matching, both pattern paths and incoming request paths are unescaped segment by segment.
2363+
// So, for example, the path "/a%2Fb/100%25" is treated as having two segments, "a/b" and "100%".
2364+
// The pattern "/a%2fb/" matches it, but the pattern "/a/b/" does not.
2365+
//
2366+
// # Precedence
2367+
//
2368+
// If two or more patterns match a request, then the most specific pattern takes precedence.
2369+
// A pattern P1 is more specific than P2 if P1 matches a strict subset of P2’s requests;
2370+
// that is, if P2 matches all the requests of P1 and more.
2371+
// If neither is more specific, then the patterns conflict.
2372+
// There is one exception to this rule, for backwards compatibility:
2373+
// if two patterns would otherwise conflict and one has a host while the other does not,
2374+
// then the pattern with the host takes precedence.
2375+
// If a pattern passed [ServeMux.Handle] or [ServeMux.HandleFunc] conflicts with
2376+
// another pattern that is already registered, those functions panic.
2377+
//
2378+
// As an example of the general rule, "/images/thumbnails/" is more specific than "/images/",
2379+
// so both can be registered.
2380+
// The former matches paths beginning with "/images/thumbnails/"
2381+
// and the latter will match any other path in the "/images/" subtree.
2382+
//
2383+
// As another example, consider the patterns "GET /" and "/index.html":
2384+
// both match a GET request for "/index.html", but the former pattern
2385+
// matches all other GET and HEAD requests, while the latter matches any
2386+
// request for "/index.html" that uses a different method.
2387+
// The patterns conflict.
2388+
//
2389+
// # Trailing-slash redirection
2390+
//
2391+
// Consider a ServeMux with a handler for a subtree, registered using a trailing slash or "..." wildcard.
2392+
// If the ServeMux receives a request for the subtree root without a trailing slash,
2393+
// it redirects the request by adding the trailing slash.
2394+
// This behavior can be overridden with a separate registration for the path without
2395+
// the trailing slash or "..." wildcard. For example, registering "/images/" causes ServeMux
23352396
// to redirect a request for "/images" to "/images/", unless "/images" has
23362397
// been registered separately.
23372398
//
2338-
// Patterns may optionally begin with a host name, restricting matches to
2339-
// URLs on that host only. Host-specific patterns take precedence over
2340-
// general patterns, so that a handler might register for the two patterns
2341-
// "/codesearch" and "codesearch.google.com/" without also taking over
2342-
// requests for "http://www.google.com/".
2399+
// # Request sanitizing
23432400
//
23442401
// ServeMux also takes care of sanitizing the URL request path and the Host
23452402
// header, stripping the port number and redirecting any request containing . or
2346-
// .. elements or repeated slashes to an equivalent, cleaner URL.
2403+
// .. segments or repeated slashes to an equivalent, cleaner URL.
2404+
//
2405+
// # Compatibility
2406+
//
2407+
// The pattern syntax and matching behavior of ServeMux changed significantly
2408+
// in Go 1.22. To restore the old behavior, set the GODEBUG environment variable
2409+
// to "httpmuxgo121=1". This setting is read once, at program startup; changes
2410+
// during execution will be ignored.
2411+
//
2412+
// The backwards-incompatible changes include:
2413+
// - Wildcards are just ordinary literal path segments in 1.21.
2414+
// For example, the pattern "/{x}" will match only that path in 1.21,
2415+
// but will match any one-segment path in 1.22.
2416+
// - In 1.21, no pattern was rejected, unless it was empty or conflicted with an existing pattern.
2417+
// In 1.22, syntactically invalid patterns will cause [ServeMux.Handle] and [ServeMux.HandleFunc] to panic.
2418+
// For example, in 1.21, the patterns "/{" and "/a{x}" match themselves,
2419+
// but in 1.22 they are invalid and will cause a panic when registered.
2420+
// - In 1.22, each segment of a pattern is unescaped; this was not done in 1.21.
2421+
// For example, in 1.22 the pattern "/%61" matches the path "/a" ("%61" being the URL escape sequence for "a"),
2422+
// but in 1.21 it would match only the path "/%2561" (where "%25" is the escape for the percent sign).
2423+
// - When matching patterns to paths, in 1.22 each segment of the path is unescaped; in 1.21, the entire path is unescaped.
2424+
// This change mostly affects how paths with %2F escapes adjacent to slashes are treated.
2425+
// See https://go.dev/issue/21955 for details.
23472426
type ServeMux struct {
23482427
mu sync.RWMutex
23492428
tree routingNode
@@ -2570,7 +2649,7 @@ func (mux *ServeMux) matchingMethods(host, path string) []string {
25702649
return methods
25712650
}
25722651

2573-
// TODO: replace with maps.Keys when it is defined.
2652+
// TODO(jba): replace with maps.Keys when it is defined.
25742653
func mapKeys[K comparable, V any](m map[K]V) []K {
25752654
var ks []K
25762655
for k := range m {
@@ -2598,11 +2677,12 @@ func (mux *ServeMux) ServeHTTP(w ResponseWriter, r *Request) {
25982677
h.ServeHTTP(w, r)
25992678
}
26002679

2601-
// The four functions below all call register so that callerLocation
2680+
// The four functions below all call ServeMux.register so that callerLocation
26022681
// always refers to user code.
26032682

26042683
// Handle registers the handler for the given pattern.
2605-
// If a handler already exists for pattern, Handle panics.
2684+
// If the given pattern conflicts, with one that is already registered, Handle
2685+
// panics.
26062686
func (mux *ServeMux) Handle(pattern string, handler Handler) {
26072687
if use121 {
26082688
mux.mux121.handle(pattern, handler)
@@ -2611,6 +2691,8 @@ func (mux *ServeMux) Handle(pattern string, handler Handler) {
26112691
}
26122692

26132693
// HandleFunc registers the handler function for the given pattern.
2694+
// If the given pattern conflicts, with one that is already registered, HandleFunc
2695+
// panics.
26142696
func (mux *ServeMux) HandleFunc(pattern string, handler func(ResponseWriter, *Request)) {
26152697
if use121 {
26162698
mux.mux121.handleFunc(pattern, handler)

0 commit comments

Comments
 (0)