Match order
Two tiers, one pass, no backtracking.
Route patterns compile to segment lists at start-up, and matching happens in two tiers.
- Patterns with no dynamic segments resolve through a hash lookup.
- Everything else walks a list pre-sorted by specificity.
Specificity
The sort is by three rules, applied in order:
- More segments beats fewer.
- A literal segment beats a parameter.
- A catch-all sorts last.
The first structural match is therefore the most specific one, and the router never backtracks.
/posts/new literal, depth 2
/posts/[id] parameter, depth 2
/posts/[...rest] catch-allA request for /posts/new matches the literal route. A request for /posts/42 falls to the parameter. A request for /posts/42/edit reaches the catch-all.
Methods and status codes
When a path matches but no handler accepts the request method, the response is 405 with an Allow header listing the methods that are accepted. When nothing matches at all, the response is 404.
Because method masks merge across files that share a path, an Allow header stays accurate even when GET and POST for one address live in two different modules.
Seeing the compiled order
cataract routesThe command prints the table in exactly the order the router will try it, which makes "why did this request hit that file?" a question you answer by reading, not by instrumenting.
Handlers are virtual methods
Each route compiles to its own Handler subclass with a handle method, registered into the router at start-up. Per-route compile-time state — the layout to call, the stylesheets to link, whether the page throws — is baked into that class rather than resolved per request.