Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Change Router::nest to flatten the routes #1711

Merged
merged 13 commits into from
Apr 11, 2023
Merged

Change Router::nest to flatten the routes #1711

merged 13 commits into from
Apr 11, 2023

Conversation

davidpdrsn
Copy link
Member

@davidpdrsn davidpdrsn commented Jan 20, 2023

This changes Router::nest to "flatten" the routes. By flattening I mean just
moving the routes from one router to another by calling
.route(nest_path, nested_endpoint). That means there aren't any Routers
nested inside each other and instead we just have one flattened Router which
performs better.

The main tricky part was fallback inheritance. The main reason we didn't flatten
routes in 0.6 previously was specifically because of fallback inheritance.

The solution I went for here was to make an internal PathRouter type. It has
most routing functions from Router, except fallbacks. A Router then
contains two PathRouters: One for the actual routes and another for
fallbacks. Then when you add a fallback to the root router that adds / and
/* routes to the fallback PathRouter. Nesting is then pretty straight
forward: We just nest the routes from each PathRouter.

Fixes #1624
Fixes #1441

TODO

  • How to handle nested fallbacks
  • Update tests for MatchedPath
  • Changelog

Don't believe there are any docs changes to make.

axum/src/routing/route.rs Outdated Show resolved Hide resolved
axum/src/extract/matched_path.rs Outdated Show resolved Hide resolved
debug_assert!(path.starts_with('/'));

if prefix.ends_with('/') {
format!("{prefix}{}", path.trim_start_matches('/')).into()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Now I'm wondering how multiple successive slashes behave elsewhere 🤔

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Like if you do .nest("////", _)?

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Yeah, that or .nest("///foo/", _).

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

You've nerd sniped me 😜 I'll make a note and do some tests.

@davidpdrsn davidpdrsn marked this pull request as ready for review April 7, 2023 19:43
@davidpdrsn davidpdrsn requested a review from jplatte April 7, 2023 19:44
@davidpdrsn
Copy link
Member Author

@jplatte I finally got fallback inheritance working properly 🎉

axum/src/routing/mod.rs Show resolved Hide resolved
axum/src/routing/mod.rs Outdated Show resolved Hide resolved
@@ -262,6 +282,23 @@ mod tests {
assert_eq!(res.status(), StatusCode::OK);
}

#[tokio::test]
async fn can_extract_nested_matched_path_in_middleware_via_extension_using_nest() {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

🙌🏼

Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
@davidpdrsn davidpdrsn merged commit 2c2cf36 into main Apr 11, 2023
@davidpdrsn davidpdrsn deleted the flatten-nest branch April 11, 2023 14:17
@@ -29,6 +29,7 @@ where
}

fn call(&mut self, _req: Request<B>) -> Self::Future {
println!("NotFound hit");
Copy link
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Should this stay?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

It should not 😅 removed in v0.6.14

davidpdrsn added a commit that referenced this pull request Apr 14, 2023
With the introduction of `PathRouter` in #1711 I forgot that fallbacks
shouldn't be able to extract `MatchedPath`. The extension for it was
interested regardless if the `PathRouter` was used as a fallback or not.

It doesn't make sense to extract `MatchedPath` in a fallback because
there was no matched route. Turns out it also fixes a panic with a
specifical fallback/nest setup.

Fixes #1931
davidpdrsn added a commit that referenced this pull request Apr 14, 2023
With the introduction of `PathRouter` in #1711 I forgot that fallbacks
shouldn't be able to extract `MatchedPath`. The extension for it was
interested regardless if the `PathRouter` was used as a fallback or not.

It doesn't make sense to extract `MatchedPath` in a fallback because
there was no matched route. Turns out it also fixes a panic with a
specifical fallback/nest setup.

Fixes #1931
@MidasLamb
Copy link

Thanks for this! I think this is responsible for fixing an issue we had where the telemetry we had for nested routers didn't get their http.route set properly

@davidpdrsn
Copy link
Member Author

Yep that most likely #1441

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
4 participants