Skip to content

Change Router::nest to flatten the routes - #1711

Merged
davidpdrsn merged 13 commits into
mainfrom
flatten-nest
Apr 11, 2023
Merged

Change Router::nest to flatten the routes#1711
davidpdrsn merged 13 commits into
mainfrom
flatten-nest

Conversation

@davidpdrsn

@davidpdrsn davidpdrsn commented Jan 20, 2023

Copy link
Copy Markdown
Member

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.

Comment thread axum/src/routing/route.rs Outdated
Comment thread axum/src/extract/matched_path.rs Outdated
Comment thread axum/src/routing/mod.rs Outdated
debug_assert!(path.starts_with('/'));

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

Copy link
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
Contributor

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
Copy Markdown
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
Copy Markdown
Member Author

@jplatte I finally got fallback inheritance working properly 🎉

Comment thread axum/src/routing/mod.rs
Comment thread axum/src/routing/mod.rs Outdated
}

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

Copy link
Copy Markdown
Contributor

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
}

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

Copy link
Copy Markdown
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
Copy Markdown
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
Copy Markdown

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
Copy Markdown
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

Development

Successfully merging this pull request may close these issues.

Router::nest has poor performance on 0.6 Extracting MatchedPath in middleware will not always give the final matched path

4 participants