Immutable
release. Only release title and notes can be modified.
This release adds an opt-in tree-based route matcher. Enable it with router.matcher: 'tree'. The linear matcher remains the default. The tree matcher preserves registration order unless you configure precedence: 'specificity'.
Our benchmarks used 1,000 registered routes. The full-stack HTTP cases matched the last registered route:
| Workload | Before (req/s) | After (req/s) | Change | p50 before | p50 after |
|---|---|---|---|---|---|
| Dynamic route | 38,249.6 | 75,385.6 | +97.1% | 29 ms | 9 ms |
| Wildcard route | 39,414.4 | 75,552.0 | +91.7% | 28 ms | 9 ms |
Each result is from five rounds, with a 3-second warmup, a 5-second measurement window, 100 connections, and a pipeline depth of 10.
Matcher-only benchmarks reported these speedups:
| Scenario | Speedup |
|---|---|
| Dynamic route at the end | 18× |
| Dynamic route miss | 22.8× |
| Deep dynamic route | 12.1× |
| Wildcard route at the end | 18.4× |
| 1,000 overlapping regex matchers | 1.19× |
These results cover specific workloads, not every route pattern. The PR notes that its full-stack static-route benchmark had not been rerun against the final implementation.
This release also fixes three request and response edge cases.
- Requests behind trusted proxies now use the first
X-Forwarded-Hostvalue. - Redirects without an explicit query-string option follow the server configuration, while
falsedisables forwarding. - Sending a native
Responsepreserves all itsSet-Cookieheaders and appends them to cookies already set on the response.