-
Notifications
You must be signed in to change notification settings - Fork 1.1k
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
Consider changing the behavior of / route when nesting #2659
Comments
cc @yanns @mladedav @ibraheemdev do any of you have ideas / opinions on this? |
I've also sometimes guessed wrong how the nesting with root handlers works. One option would be to simply concatenate, but there should be rules to disallow things like this: Router::new().nest("/foo", Router::new().route("bar", todo)); // matches `/foobar` ?? What I imagine could work is that axum would require:
For example: Router::new().nest("", Router::new().route("/foo", todo)); // error - nest must start with a slash
Router::new().nest("/", Router::new().route("/foo", todo)); // error - nest must not ends with a slash
Router::new().nest("/foo", Router::new().route("", todo)); // matches `/foo`
Router::new().nest("/foo", Router::new().route("/", todo)); //matches `/foo/`
Router::new().nest("/foo", Router::new().route("/bar", todo)); //matches `/foo/bar`
Router::new().nest("/foo", Router::new().route("/bar/", todo)); //matches `/foo/bar/`
Router::new().nest("/foo/", Router::new().route("/bar", todo)); // error - nest ends with a slash
Router::new().nest("/foo", Router::new().route("bar", todo)); // error - route doesn't start with a slash Currently, axum only requires all paths to start with a slash as far as I know. This would allow setting routes with or without trailing slashes and would even prevent users from building the same router multiple ways ( The thing I dislike about this the most is that
would behave differently based on whether it would be nested or not. On top level the two routes are equivalent (so we should maybe even reject starting the server due to conflicting routes) but in a nested router they are different. This is because RFC 3386 mentions that One way out of this would be to either let the user provide the Another would be to make the empty route even more special in a way that it returns different type, e.g. |
I have never used |
This was discussed back in 2022 #714 #1118 but I cannot find where the decisions were made You can use NormalizePath use axum::{
extract::Request, routing::get, routing::get_service,
Router, ServiceExt,
};
use tokio::net::TcpListener;
use tower_http::{
normalize_path::NormalizePathLayer,
services::{ServeDir, ServeFile},
};
use tower_layer::Layer;
#[tokio::main]
async fn main() {
fn app_router() -> Router {
Router::new()
.route("/", get(|| async { "hi" }))
}
let serve_dir =
get_service(ServeDir::new("static").not_found_service(ServeFile::new("static/index.html")));
let app = Router::new()
.nest("/api", app_router())
.nest_service("/", serve_dir);
let app = NormalizePathLayer::trim_trailing_slash().layer(app);
let app = ServiceExt::<Request>::into_make_service(app);
let listener = TcpListener::bind("127.0.0.1:3000").await.unwrap();
axum::serve(listener, app)
.await
.unwrap();
} |
there is also some strange behaviours around I have made a gist with the details https://gist.github.com/timhughes/745a07746f96c64586682d78829b840b |
Currently, given a router
and an outer router
Router::new().nest("/foo", inner)
=> only the route/foo
existsRouter::new().nest("/foo/", inner)
=> only the route/foo/
existsIt seems like people (me included) generally prefer the first form, but oftentimes expect different behavior (see #2267). We should (re)consider what behavior(s) are reasonable for the upcoming release. Also worth checking: What happens with
nest_service
?The text was updated successfully, but these errors were encountered: