-
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
Use 308 status instead of 301 when redirecting #682
Conversation
For redirects resulting from requests to paths with a trailing slash, use 308 instead of 301 to prevent non-GET requests (POST, PUT, etc) from being changed to GET. For example, (assuming a route for /path is defined)... - Old behavior results in: POST /path/ -> GET /path - New behavior results in: POST /path/ -> POST /path Fixes tokio-rs#681
Should this PR be against [1] e.g., if a server had a different route defined for the |
Converted to draft while I add deprecation attributes to methods that return ambiguous response codes (viz., |
Deprecates found() due to its use of HTTP 302
Use Redirect::permanent instead of re-implementing its functionality
It looks like there's currently no built-in method for |
Replace usages of Redirect:found with Redirect::to and Redirect::temporary as appropriate
I'm not yet marking this as ready for review, since I haven't tested |
if we change 301 -> 308 https://developer.mozilla.org/en-US/docs/Web/HTTP/Status/307
|
@ttys3 I agree. I had already marked
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Thanks for fixing this!
IMO its not a breaking change so doesn't have to merged into axum-next
.
Previously the example would panic if a request was made without the `Cookie` header. Now the user is redirected to the login page as expected.
I verified that the example still works and made some small improvements along the way (though I had to expose some previously-private fields to nicely destructure an existing error when requests without a I'd like confirmation that exposing |
examples/oauth/src/main.rs
Outdated
impl From<TypedHeaderRejection> for AuthRedirect { | ||
fn from(error: TypedHeaderRejection) -> Self { | ||
match error { | ||
TypedHeaderRejection { | ||
name: &header::COOKIE, | ||
reason: TypedHeaderRejectionReason::Missing, | ||
} => AuthRedirect, | ||
_ => panic!("unexpected error getting Cookie header(s)"), | ||
} | ||
} | ||
} |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not hugely fond of this, but I couldn't think of a better way to do it without introducing a wrapping type or using anyhow
in a way I'm not familiar with. Suggestions welcome.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I'm not very familiar with this example but the fields should stay private. Users should not be able to construct this type directly or mutate the fields.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
The fields of TypedHeaderRejection should stay private.
Apologies for all of the extra commits. I'm not squashing to abide by the contributing guidelines. |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
LGMT! Thanks 😃
Appreciated! Makes reviewing changes since my last review much easier. |
You know GitHub can also render force-push diffs though, right? (need to click the text "force-pushed" in the comments view) |
Maybe 🤷 I remember not being able to figure it out |
It is definitely weird, but it works (just requires a few extra clicks because the notification will lead you to a "we couldn't find these commits" page). Example: ruma/ruma#796 (comment) |
- **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
- **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
Motivation
Assuming a route for
/path
is defined,POST
/path/
currently may redirect toGET
/path
when it should redirect toPOST
/path
(depending on the client).This was outlined in #681.
This has potential security implications (e.g., if the
POST
contained sensitive data, that data may be saved by the user's client in their browser history and/or in the server's access logs).It's worth noting that the internal test client, a wrapper for the popular
reqwest
client, is susceptible to this incorrect behavior.Solution
This PR replaces the
301
redirect with a308
and adds corresponding tests to verify the behavior (note that these tests fail without the accompanying code change).axum-next
CHANGELOG.md
should be added