On this page

Configuration Reference

All configuration is done by setting fields on *Mux after calling muxmaster.New(). Every field has a sensible default suitable for production use.

Table of Contents


Router Behaviour

RedirectTrailingSlash

mux.RedirectTrailingSlash = true // default

Automatically redirects requests with a trailing slash mismatch:

  • GET /users/ → 301 redirect to /users (when /users is registered but not /users/)
  • GET /users → 301 redirect to /users/ (when /users/ is registered but not /users)

The redirect code is controlled by RedirectCode.

Set to false to return 404 in both cases instead of redirecting.


RedirectFixedPath

mux.RedirectFixedPath = true // default

Cleans the request path and issues a redirect if a match is found after cleaning:

  • Removes extra slashes: GET //users → 301 to /users
  • Resolves dots: GET /a/../users → 301 to /users

This prevents duplicate-content issues where /users and //users serve identical content under different URLs.

Set to false to return 404 for malformed paths instead of redirecting.


HandleMethodNotAllowed

mux.HandleMethodNotAllowed = true // default

When true, and the URL matches a registered route but not for the requested method, MuxMaster responds with 405 Method Not Allowed and sets the Allow header to the list of allowed methods.

When false, such requests receive a 404 Not Found instead.

The response handler can be customized via mux.MethodNotAllowed.


HandleOPTIONS

mux.HandleOPTIONS = true // default

Automatically responds to OPTIONS requests with the list of allowed HTTP methods in the Allow header. The default response body is empty with status 200.

To customize the OPTIONS response globally:

mux.GlobalOPTIONS = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    w.Header().Set("Access-Control-Allow-Methods", w.Header().Get("Allow"))
    w.WriteHeader(http.StatusNoContent)
})

Set to false if you handle OPTIONS manually (e.g. through the CORS middleware).


RedirectCode

mux.RedirectCode = http.StatusMovedPermanently // default: 301

The HTTP status code used for redirects triggered by RedirectTrailingSlash and RedirectFixedPath. Common values:

Code Constant Semantics
301 http.StatusMovedPermanently Permanent redirect (cached)
302 http.StatusFound Temporary redirect (not cached)
307 http.StatusTemporaryRedirect Temporary, preserves method
308 http.StatusPermanentRedirect Permanent, preserves method

Use 307 or 308 if you need POST requests to be redirected without the browser changing the method to GET.


Path Matching

CaseInsensitive

mux.CaseInsensitive = false // default

When true, route matching ignores case in path segments. A request for /Users/42 matches a route registered as /users/:id.

Note: this does not issue a redirect; the original URL is preserved in the response.


UseRawPath

mux.UseRawPath = false // default

When true, MuxMaster uses r.URL.RawPath for route matching instead of r.URL.Path. This matters when path values contain percent-encoded slashes (%2F):

  • r.URL.Path: /files/a%2Fb is decoded to /files/a/b and would match /files/*filepath with filepath = "/a/b" (two separate segments)
  • r.URL.RawPath: /files/a%2Fb is kept as-is and matches /files/*filepath with filepath = "/a%2Fb" (treated as a single segment)

Enable this only if your application legitimately uses encoded slashes in URL paths.


UnescapePathValues

mux.UnescapePathValues = false // default

When true, path parameter values are percent-decoded before being returned by PathParam and ParamsFromContext.

For example, with the route /search/:query and the URL /search/hello%20world:

  • false: PathParam(r, "query") returns "hello%20world"
  • true: PathParam(r, "query") returns "hello world"

Performance Opt-ins (v1.1.0)

Two flags introduced in v1.1.0 recycle the per-request bundle through sync.Pools and bring the parameterised hot path down to zero allocations. Both flags default to false; both impose a strict handler-lifetime contract. The full contract, the failure modes, and an audit checklist for an existing codebase are at Maximum performance.

PoolRequestBundle

mux.PoolRequestBundle = false // default

When true, MuxMaster recycles the fused requestCtx + *http.Request bundle through three tier-matched sync.Pools (1 / 2 / 3+ parameters). The bundle is fully zeroed on Put so the next request cannot observe stale state.

Contract: handlers must not retain *http.Request past return — never capture r in a goroutine that outlives the handler. See the audit checklist before enabling on an existing codebase.

Forward compatibility: MuxMaster detects the unexported ctx field of http.Request at init via reflection (hasReqCtxField). On a future Go release that renames or removes the field, PoolRequestBundle = true is silently ignored and the router falls back to r.WithContext(...), preserving correctness over speed.

PoolFastParams

mux.PoolFastParams = false // default

When true, MuxMaster recycles the Params slice handed to FastHandler routes through three tier-matched sync.Pools (1 / 2 / 3 parameters). The pool stores *[N]Param so Put is itself zero-allocation.

Contract: FastHandler callbacks must not retain the Params slice or any Param element past return.

The two flags are independent — enable either, both, or neither.


Custom Handlers

NotFound

mux.NotFound = myNotFoundHandler

Called when no route matches the request path. Defaults to http.NotFound (plain-text 404).

mux.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    muxmaster.JSON(w, http.StatusNotFound, map[string]string{
        "error": "not found",
        "path":  r.URL.Path,
    })
})

MethodNotAllowed

mux.MethodNotAllowed = myMethodNotAllowedHandler

Called when the path matches a route but not for the requested HTTP method. The Allow header is set to the list of allowed methods before this handler is called.

mux.MethodNotAllowed = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    muxmaster.JSON(w, http.StatusMethodNotAllowed, map[string]string{
        "error":   "method not allowed",
        "allowed": w.Header().Get("Allow"),
    })
})

Only active when HandleMethodNotAllowed is true.


GlobalOPTIONS

mux.GlobalOPTIONS = myOptionsHandler

Called for every auto-handled OPTIONS request. The Allow header is already set when this handler runs.

Only active when HandleOPTIONS is true.


PanicHandler

mux.PanicHandler = func(w http.ResponseWriter, r *http.Request, rcv any) { ... }

If set, catches panics in downstream handlers and calls this function instead of letting the panic propagate. Receives the value passed to panic() as rcv.

mux.PanicHandler = func(w http.ResponseWriter, r *http.Request, rcv any) {
    log.Printf("panic: %v", rcv)
    http.Error(w, "Internal Server Error", http.StatusInternalServerError)
}

ErrorHandler

mux.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) { ... }

Called for every HandlerFuncE that returns a non-nil error. See Error Handling for details.


Complete Example

mux := muxmaster.New()

// Routing behaviour
mux.RedirectTrailingSlash  = true
mux.RedirectFixedPath      = true
mux.HandleMethodNotAllowed = true
mux.HandleOPTIONS          = true
mux.RedirectCode           = http.StatusMovedPermanently

// Path matching
mux.CaseInsensitive       = false
mux.UseRawPath            = false
mux.UnescapePathValues    = false

// Custom error responses (JSON)
mux.NotFound = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    muxmaster.JSON(w, http.StatusNotFound, map[string]string{"error": "not found"})
})

mux.MethodNotAllowed = http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
    muxmaster.JSON(w, http.StatusMethodNotAllowed, map[string]string{
        "error":   "method not allowed",
        "allowed": w.Header().Get("Allow"),
    })
})

mux.PanicHandler = func(w http.ResponseWriter, r *http.Request, rcv any) {
    log.Printf("panic: %v\n%s", rcv, debug.Stack())
    muxmaster.JSON(w, http.StatusInternalServerError, map[string]string{
        "error": "internal server error",
    })
}

mux.ErrorHandler = func(w http.ResponseWriter, r *http.Request, err error) {
    code := http.StatusInternalServerError
    var he muxmaster.HTTPError
    if errors.As(err, &he) {
        code = he.StatusCode()
    } else {
        log.Printf("unhandled error: %v", err)
    }
    muxmaster.JSON(w, code, map[string]string{"error": err.Error()})
}

See Also

  • Routing — trailing slash and path normalization in more detail
  • Error Handling — custom error handler patterns
  • Middleware — CleanPath and StripSlashes as alternatives to redirect-based normalization

Upstream source

The Mux struct, its option functions, and the trailing-slash and path-cleaning semantics referenced above are implemented in mux.go in the upstream repository.

Common questions

How do I configure MuxMaster's trailing-slash policy?

Pass mux.WithStrictSlash(false) (or set Config.StrictSlash to false) so the router treats /foo and /foo/ as the same route. The default is true, which serves a 301 redirect from one form to the other to keep search-engine signals concentrated on a single canonical URL.

How do I customise the not-found response?

Set mux.Config.NotFoundHandler to any http.Handler (or pass mux.WithNotFoundHandler at construction). The handler runs when no registered pattern matches the request URL; it sees the original request unchanged and is responsible for writing both the status code and the body.

How do I enforce a maximum request size at the router level?

There is no router-level body limit — the runtime exposes http.MaxBytesReader for that purpose. Wrap the handler chain (or attach a middleware that wraps r.Body in http.MaxBytesReader) to enforce a per-route or per-method cap before any business logic runs.