internal/netx/path.go and
provides two operations:
ValidatePathPatternchecks whether a pattern is valid; andMatchPathPatternchecks whether a request path matches that pattern.
Valid patterns
A pattern must:- be non-empty; and
- start with
/.
/ when you want to match a path subtree:
* or ? do not create wildcard behavior. Unless the
pattern ends in /, the entire pattern is compared as a literal path.
Matching rules
Exact paths
A pattern that does not end in/ matches only the same path:
| Pattern | Matches | Does not match |
|---|---|---|
/api/items | /api/items | /api/items/, /api/items/1 |
/health | /health | /healthz |
/api/items and /api/items/ are
different exact paths.
Subtrees
A pattern ending in/ matches paths that begin with that pattern:
/api and its children, define separate patterns.
The root path
/ is handled specially because different resource types use it differently:
| Caller | Root behavior |
|---|---|
Route.Allow | / matches only / |
| Plugin HTTP route | / matches only / |
| Static directory mount | / matches every absolute path |
RootPathExact. Static mounts use
RootPathSubtree, so a static directory mounted at / can serve paths below
the root.
Choosing between matching patterns
When several patterns match a path, Arupa selects the longest matching pattern. It does not merge the rules or group lists from all matching patterns. For example, given these host access rules:/api/admin/users matches both patterns, but /api/admin/ wins because it is
longer. Only the root group rule is evaluated for that request.
This same longest-pattern rule is used when the plugin router selects an HTTP
route or a static mount.
Host access rules
Route.Allow matches the request’s URL path before the request reaches a host
handler or plugin handler. Configuration validation applies the same pattern
rules described above. See Access control
for how the selected route’s group list is evaluated against the authenticated
user.
The query string is not part of path matching. For example, a request for
/api/items?limit=10 is matched using /api/items.
Plugin HTTP routes
Plugins use the same path patterns when they register HTTP routes. After the router selects the longest matching path pattern, it selects a handler by HTTP method:- an explicitly declared method such as
GETorPOSTis matched case-insensitively after normalization; - an empty method is a handler for any method; and
- an explicit method takes precedence over an empty-method handler for the selected path.
405 Method Not Allowed and includes the available methods in the Allow response header.
Routes with the same path and conflicting methods cannot be registered by
different plugins. A methodless route conflicts with every method at that same
path.
Static mounts
Static directory mounts use subtree matching. The Kernel normalizes a directory mount to a pattern ending in/, so a mount configured at /assets serves the
/assets/ subtree.
Static file mounts use exact matching and must not end in /. A static file
mount at /favicon.ico therefore serves that path only.
Static mounts and plugin HTTP routes are both considered by the plugin router.
The router chooses the longest matching pattern; when a static mount and HTTP
route have the same matching length, the static mount is selected.