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

Fix nesting Router at / leading to double slash in the path #691

Merged
merged 4 commits into from
Jan 6, 2022

Conversation

davidpdrsn
Copy link
Member

If you nested a Router at / the path for the final routes would start with a double slash.

Fixes #690

Aside about how nesting works:

When you nest a service we try and downcast it to a Router. If that succeeds we simply move all the paths from one router onto another, with the path prefix added plus a middleware that strips the prefix before calling the MethodRouter. That simplifies lots of things internally because there is only one router that has all the paths. It also improves performance since matchit can see the entire tree. If the downcast fails we just nest it as an opaque service however, don't really have other options.

This is why nesting a Router at / is fine, and wont collide with all other routes, but nesting something like ServeDir will.

Copy link
Member

@jplatte jplatte left a comment

Choose a reason for hiding this comment

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

So this will be supported while .nest("", /* router */) panics? That seems inconsistent to me.

@davidpdrsn
Copy link
Member Author

We could make nesting at "" work. Its just a simple check currently. Should it work the same as /?

@jplatte
Copy link
Member

jplatte commented Jan 6, 2022

Yeah I think it would make sense for both to behave the same way, whether it works the same as merge or is a panic (in which case the panic message should probably mention merge).

In terms of implementation, wouldn't it be simpler to just delegate nest("" | "/", _) to merge(_)?

@davidpdrsn
Copy link
Member Author

Yeah I think it would make sense for both to behave the same way

Done!

In terms of implementation, wouldn't it be simpler to just delegate nest("" | "/", _) to merge(_)?

I thought so as well but the behavior regarding fallbacks is slightly different between the two. nest always panics if you nest a router with a fallback, because we merge all routes into a single a router and thus can only have one fallback. Supporting nested routers with fallbacks would be nice but required something new in matchit iirc. Whereas merge only panics if both routers have a fallback, because it wouldn't know which one to pick.

@jplatte
Copy link
Member

jplatte commented Jan 6, 2022

Done!

You didn't push though 😅

@davidpdrsn
Copy link
Member Author

whoops!

@davidpdrsn davidpdrsn merged commit d181867 into main Jan 6, 2022
@davidpdrsn davidpdrsn deleted the fix-nest-router-at-root branch January 6, 2022 11:12
davidpdrsn added a commit that referenced this pull request Jan 13, 2022
- **fixed:** Fix using incorrect path prefix when nesting `Router`s at `/` ([#691])
- **fixed:** Make `nest("", service)` work and mean the same as `nest("/", service)` ([#691])
- **fixed:** Replace response code `301` with `308` for trailing slash redirects. Also deprecates
  `Redirect::found` (`302`) in favor of `Redirect::temporary` (`307`) or `Redirect::to` (`303`).
  This is to prevent clients from changing non-`GET` requests to `GET` requests ([#682])

[#691]: #691
[#682]: #682
@davidpdrsn davidpdrsn mentioned this pull request Jan 13, 2022
davidpdrsn added a commit that referenced this pull request Jan 13, 2022
- **fixed:** Fix using incorrect path prefix when nesting `Router`s at `/` ([#691])
- **fixed:** Make `nest("", service)` work and mean the same as `nest("/", service)` ([#691])
- **fixed:** Replace response code `301` with `308` for trailing slash redirects. Also deprecates
  `Redirect::found` (`302`) in favor of `Redirect::temporary` (`307`) or `Redirect::to` (`303`).
  This is to prevent clients from changing non-`GET` requests to `GET` requests ([#682])

[#691]: #691
[#682]: #682
@Atrox
Copy link

Atrox commented Jan 15, 2022

Just as an info:
This change did break my functioning setup of nested routes. I needed to add a / prefix to all of them to work correctly with v0.4.4.

base:

    Router::new()
        .nest("/", pages::routes())

pages::routes before:

    Router::new()
        .route("/", get(index))
        .route("something/:id", get(something))
        .route("other", post(other))

pages::routes now:
(this did not work for me before v0.4.4)

    Router::new()
        .route("/", get(index))
        .route("/something/:id", get(something))
        .route("/other", post(other))

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

Successfully merging this pull request may close these issues.

Odd behavior when nesting root / path
3 participants