Routing Reference
MuxMaster dispatches HTTP requests using a radix tree (compressed prefix trie). Each HTTP method has its own tree. Route lookup is O(k) in the length of the URL path, independent of the total number of registered routes.
Table of Contents
- Registering Routes
- Path Pattern Syntax
- Pattern Priority and Conflicts
- HTTP Method Helpers
- ANY and Match
- Low-Level Registration
- Route Ordering and Middleware Timing
- Trailing Slash Behaviour
- Path Normalization
Registering Routes
The most common way to register a route is with one of the HTTP method helpers:
mux := muxmaster.New()
mux.GET("/users", listUsers)
mux.POST("/users", createUser)
mux.PUT("/users/:id", updateUser)
mux.PATCH("/users/:id", patchUser)
mux.DELETE("/users/:id", deleteUser)
mux.HEAD("/users/:id", headUser)
mux.OPTIONS("/users", optionsUsers)
mux.CONNECT("/tunnel", tunnel)
mux.TRACE("/trace", trace)
All helpers accept a http.HandlerFunc. To pass an http.Handler directly, use Handle.
Path Pattern Syntax
Patterns are strings that begin with /. Four types of segment are supported:
Static segments
A plain string matches exactly:
/ matches /
/users matches /users
/api/v1/health matches /api/v1/health
Named parameters (:name)
A segment starting with : captures one path segment (everything up to the next /):
/users/:id matches /users/42 → id = "42"
matches /users/alice → id = "alice"
no match /users/ (empty segment)
no match /users/42/posts (extra segment)
Multiple parameters in the same pattern:
/posts/:year/:month/:slug
Regex-constrained parameters ({name:pattern})
A segment of the form {name:regexp} captures the segment only if it matches the regular expression:
/users/{id:[0-9]+} matches /users/42 → id = "42"
no match /users/abc
no match /users/3.14
The regexp is anchored automatically — you do not need ^ or $. The full Go regexp syntax is supported.
Catch-all parameters (*name)
A segment starting with * captures the rest of the path, including slashes. It must appear at the end of the pattern:
/files/*filepath matches /files/img/logo.png → filepath = "/img/logo.png"
matches /files/a/b/c.txt → filepath = "/a/b/c.txt"
matches /files/ → filepath = "/"
The captured value always starts with /.
Pattern Priority and Conflicts
When multiple patterns could match the same URL, MuxMaster resolves the conflict with the following priority (highest first):
- Static segments — exact text always wins over parameters at the same position
- Named parameters —
:namewins over*catch-allat the same position - Catch-all — matches anything that nothing else matched
Example:
mux.GET("/users/me", getMe) // 1. static → /users/me
mux.GET("/users/:id", getUser) // 2. param → /users/42
mux.GET("/users/*all", catchAll) // 3. catch → /users/a/b/c
Registering two patterns that are ambiguous (e.g. two different named parameters at the same position) panics at startup to surface the conflict early.
HTTP Method Helpers
Each standard HTTP method has a direct helper on *Mux and on *Group:
| Method | Mux helper | Group helper |
|---|---|---|
| GET | mux.GET |
g.GET |
| HEAD | mux.HEAD |
g.HEAD |
| POST | mux.POST |
g.POST |
| PUT | mux.PUT |
g.PUT |
| PATCH | mux.PATCH |
g.PATCH |
| DELETE | mux.DELETE |
g.DELETE |
| OPTIONS | mux.OPTIONS |
g.OPTIONS |
| CONNECT | mux.CONNECT |
g.CONNECT |
| TRACE | mux.TRACE |
g.TRACE |
Each helper also has an error-returning variant (GETE, POSTE, PUTE, etc.) — see Error Handling.
ANY and Match
ANY
ANY registers the same handler for all standard HTTP methods (GET, HEAD, POST, PUT, PATCH, DELETE, OPTIONS, CONNECT, TRACE):
mux.ANY("/health", func(w http.ResponseWriter, r *http.Request) {
muxmaster.Text(w, http.StatusOK, "ok")
})
Match
Match registers the handler for a specific subset of methods:
mux.Match([]string{"GET", "HEAD"}, "/ping", pingHandler)
mux.Match([]string{"POST", "PUT"}, "/upload", uploadHandler)
Low-Level Registration
Handle and HandleFunc accept an explicit method string, which allows custom HTTP methods beyond the nine standard ones:
mux.Handle("PURGE", "/cache/*key", purgeCache)
mux.HandleFunc("REPORT", "/dav/*path", davReport)
HandleE is the error-returning equivalent:
mux.HandleE("PURGE", "/cache/:key", func(w http.ResponseWriter, r *http.Request) error {
key := muxmaster.PathParam(r, "key")
return cache.Invalidate(key)
})
Route Ordering and Middleware Timing
MuxMaster wraps middleware at registration time, not at request time. This means middleware is applied to the handler function at the moment GET, POST, Handle, etc. is called.
The practical consequence is that Use must be called before the routes it should wrap:
mux := muxmaster.New()
mux.GET("/public", publicHandler) // NOT wrapped by auth
mux.Use(requireAuth)
mux.GET("/private", privateHandler) // wrapped by auth
This design eliminates per-request middleware iteration. Combined with the radix tree and the tiered request bundle described in Performance, it allows static routes to dispatch with zero allocations and parameterised routes with a single fused allocation.
Trailing Slash Behaviour
RedirectTrailingSlash (default true) automatically handles the common discrepancy between /users and /users/:
- If a request arrives for
/users/and only/usersis registered, MuxMaster redirects to/users. - If a request arrives for
/usersand only/users/is registered, MuxMaster redirects to/users/.
The redirect uses the code set in RedirectCode (default 301).
To disable this and return 404 instead:
mux.RedirectTrailingSlash = false
Path Normalization
RedirectFixedPath (default true) normalizes the URL before matching:
- Removes duplicate slashes:
//users→/users - Resolves dot segments:
/a/../users→/users - If a match is found after normalization, issues a redirect to the clean URL
To use pre-routing path cleaning instead of a redirect (useful when you want the clean path without a round-trip), add the middleware:
mux.Pre(middleware.CleanPath)
CleanPath modifies the request in-place before the router sees it, so no redirect is issued.
Related Topics
- Path Parameters — reading and parsing parameter values
- Middleware — applying middleware globally or per route
- Groups — organizing routes into groups
- Configuration — all router options and their defaults
Upstream source
The radix-tree router and pattern semantics described above are implemented in mux.go and tree.go in the upstream repository.
Common questions
How do I match a path parameter in a route?
Declare it in the route pattern with a colon prefix and read it from the request inside the handler with mux.Param(r, "name"). For example /users/:id makes mux.Param(r, "id") return the matched segment.
What happens when a parameter contains a slash?
By default a :name segment matches one path component and stops at the next slash. To match the rest of the URL (including slashes) declare a catch-all parameter with the * prefix, for example /files/*path. There can be at most one catch-all per pattern and it must be the last segment.
How does MuxMaster resolve overlapping patterns?
Static segments win over :name parameters, and :name parameters win over *catchall segments — at every depth in the radix tree. The router rejects route registrations that would otherwise be ambiguous; the conflict is reported at registration time, not at request time.