Repository navigation
Action Controller 9.0.0
Action Controller 9.0.0 adds composable applications, replacement-base mounts and shared HTTP/OpenAPI/MCP catalogs.
New capabilities
- Serve a controller subtree through
App::Base.handler, an independentHTTP::Handler. Route misses continue downstream; matched actions retain their response, including intentional 404s. - Select application roots with
AC::Server.compose(...), or create independentAC::Compositioninstances. Each server flattens its placements into one routing table. - Mount controller or application subtrees beneath a host base, including nested, repeated and parameterized mounts. Public paths are shared by HTTP routing, OpenAPI, MCP and spec helpers.
- Generate unified OpenAPI definitions and a global MCP server, while preserving mounted controller MCP endpoints and session-bound parameters.
- Generate mounted URLs with
route_pathinside actions andcomposition.url_foroutside requests. Existing class URL helpers retain their original paths.
Performance
A lazy trie matcher avoids copying static path segments and allocates captures only after a successful unescaped match. Local release benchmarks show common dynamic lookups 10–16% faster, glob lookup about 46% faster, zero allocated bytes on trie misses and 32–64 fewer bytes for ordinary dynamic requests. Warmed single-handler and mounted fixtures show no consistent dispatch regression. These results are workload-specific; handler chains add a lookup on each miss and escaped paths retain the original matcher.
Upgrade notes
Existing automatic discovery and template startup remain supported. For unified composition, require reusable controller libraries and declare AC::Server.compose(App::Base, OtherApp::Base) once in config.cr. Reusable libraries should keep executable startup and global configuration separate.
Explicit compositions and mounts validate conflicting public routes, including equivalent parameterized routes and implicit HEAD operations. Mounted controllers keep their own filters; mounting alone does not apply the host controller's filters. The host owns global middleware, sessions, MCP settings and UI assets.
Regenerate MCP description files with --mcp or write_description when adopting composition or changing mounts to retain source comments. Mismatched composed descriptions are regenerated from compiled metadata; legacy descriptions remain supported for ordinary apps.
See the composition API and examples and reproducible benchmark results.