-
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
Automatic trailing slash redirect is broken when nesting with /
#714
Comments
Seems to me like everything is working fine. I tested: use axum::{routing::get, Router};
use std::net::SocketAddr;
#[tokio::main]
async fn main() {
pub fn app_router() -> Router {
Router::new().route("/", get(|| async { "hi" }))
}
let app = Router::new().nest("/app", app_router());
let addr = SocketAddr::from(([127, 0, 0, 1], 3000));
axum::Server::bind(&addr)
.serve(app.into_make_service())
.await
.unwrap();
}
Note that |
I think this is what's confusing. I would have expected the opposite without thinking much about it. I can definitely see the merit of this though (I think routes with a trailing slash are somewhat uncommon in REST APIs as opposed to file servers where you route them to some index file). |
Yeah I can see that. Thinking if there is a way to make it work, or if its worth it 🤔
Yep thats why I went with the current behavior. |
We could make
Still don't feel like trailing slashes are very common though. |
Our API uses a trailing slash, so we need compatibility. I think Django by default advocates for those too. I gotta say though, strictly in terms of what makes sense to me (nvm my issue), |
Well you can just not use Changing it a breaking change so we can't immediately fix it regardless. I'm not familiar with Django but Rails doesn't use trailing slashes and I don't remember encountering other APIs that did. I'm still unsure about that the right thing to do is. Would like to hear about what others think. |
Yeah, I think I'll just manually construct the API (so no prefix) for now. Anyhow, me wade a mistake when we chose to use a trailing slash. Alas, we can't fix it, at least not for now. |
I still think its worth considering what the most useful and consistent behavior for axum should be. Requires thinking through all the different ways routes can be nested to see if something like #714 (comment) leads to inconsistencies elsewhere. |
I have an idea that is maybe good maybe bad, so I'll let you be the judge. :) I wonder whether it makes sense to have trailing slash a framework-wide configuration (either crate config or runtime), and then just default to either. Default will be none (like none). Added benefit: you can then error (or warn?) when routes forget/accidentally add a trailing slash. |
Interesting idea but I would like to avoid global configuration/action at a distance type stuff for axum. I'm a little worried that it's a slippery slope that could make things hard to understand for users in the future. |
Yeah, so maybe not a global but rather an axium configuration on the Server object or something. |
Maybe not global but router/server wide config falls into the same category imo. At least we've been able to avoid stuff like that before (with the exception of It also makes |
I've done some more testing of the current behavior and these are all the combinations:
All these seem correct to me. It seems let inner = Router::new().route("/", get(handler));
Router::new().nest("/app/", inner); That gives a route at |
This is not really a solution though because of 15 and 16. My code actually looks like:
So the second one will break if I add the slash per your examples (double slash). Also 14 is odd, it really is weird that it deduplicates the |
It seems you can do let inner = Router::new()
.route("/", get(|| async {}))
.route(":app_id/", get(|| async {}));
let app = Router::<Body>::new().nest("/app/", inner);
dbg!(&app); but I'd honestly consider accepting I think a better solution would be to make this work let inner = Router::new()
.route("/", get(|| async {}))
.route("/:app_id/", get(|| async {}));
let app = Router::<Body>::new().nest("/app/", inner); Currently it results in And What do you think? |
I think that given that Axum already de-duplicates slashes (6-8), it makes sense to be consistent and fix the anyway broken 15 and 16. |
My 2c: I think it's sensible to require routes to start in I find it a little bit unfortunate that it's not "just" ¹ and consequently |
Sounds good! I'll fix cases 15 and 16 and add a check for routes not starting with |
+1 on forcing routes to start with |
I'll try to find time later today, thanks! |
Yup, it works. Thanks! |
Bug Report
Version
Platform
Description
When using a nested router and in the nest just using
/
the slash redirect (308) works incorrectly.Code:
Expected:
This command should return the correct data.
Instead: it returns a 308 redirect to
localhost:8080/app
(no trailing slash).The text was updated successfully, but these errors were encountered: