RFC: #[nest] attribute for first-class nested routing
#4111
Madoshakalaka
started this conversation in
Ideas
Replies: 0 comments
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Uh oh!
There was an error while loading. Please reload this page.
-
Summary
Add
#[nest("/prefix")]to theRoutablederive macro. A route enum candelegate a URL subtree to a nested
Routabletype that defines routes relativeto the mount point. No inner
Switchneeded./settings/friendsresolves toMainRoute::Settings(SettingsRoute::Friends).Motivation
This is what nested routing looks like today:
Three outer variants just to delegate. Every inner route repeats
/settings.Two
Switchcomponents match independently./settings/needs a redirect hackbecause matchit's catch-all requires >= 1 char.
#[nest]eliminates all of this: inner routes are relative, outer enum has onevariant, one
Switchresolves the full tree.Design
Usage
The variant must be a tuple variant with one
Routablefield.#[nest]and#[at]are mutually exclusive.#[not_found]is not allowed on#[nest].Multi-level nesting composes naturally:
/admin/users/42resolves toAppRoute::Admin(AdminRoute::Users(UserRoute::Detail { id: 42 })).Static routes coexist with nests under the same prefix (matchit gives static
routes priority over catch-alls).
matchit registration
For
#[nest("/settings")], the macro registers two patterns:/settings(exact) - sub-path ="/"/settings/{*__nested_N}(catch-all) - sub-path ="/{captured}"Verified: matchit 0.9 supports exact + catch-all + sibling static routes under
the same prefix.
/settings/matches neither pattern (catch-all needs >= 1char), consistent with PR #4110 trailing slash semantics.
Generated
recognize()Nest variants are resolved entirely in
recognize().from_path()isunchanged and only handles
#[at]variants.Generated
to_path()The
"/"special case avoids generating"/settings/"for the inner root.not_foundinteractionIf the inner type has
#[not_found], unrecognized sub-paths produceSome(MainRoute::Settings(SettingsRoute::NotFound)). The switch functiondecides what to do (sub-404, redirect to outer 404, etc.). If the inner type
has no
#[not_found], the outernot_found_route()is used instead.What does not change
The
Routabletrait,Switch,use_route,Navigator, and basename logic.Drawbacks
use_route::<SettingsRoute>()does not work. The hook reads the fullpathname; the inner router uses relative paths. Route must be passed via
props or context.
routes()includes internal catch-all patterns. Users callingroutes()for sitemap generation would see"/settings/{*__nested_0}".Future possibilities
#[nest("/users/{id}")]with mixed fieldsuse_nested_routehook: access sub-route without prop drilling#[at]per variant: match/aboutand/about/on one variantBeta Was this translation helpful? Give feedback.
All reactions