-
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
add method_not_allowed_fallback to router #2903
Conversation
…feat/method_fallback
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.
Hey, thanks for the PR, especially for including good documentation!
Before this can be merged, I think we'd need some unit and/or integration tests though.
In addition to the example in the review comment below, a useful test that I would actually expect to fail with the current implementation strategy after thinking a bit about it would be calling a router like
let app = Router::new()
.route("/", get(index))
.with_state(()) // would be something different in the real world, of course
.method_not_allowed_fallback(mna_fallback);
If you find that I'm right (that this is broken) and don't want to dig into it yourself, I'm happy to write up an explanation on why this would fail.
I thought about your mentioned test, but I think I don't understand the codebase deeply enough to get what you mean, so I would be very thankful if you could share an explanation. |
Right, so since you didn't indicate whether you had actually tried whether I'm right, I just looked again and think I was actually wrong. What I thought would happen was that Please add the test just to be sure, if it succeeds we're good, if not I'm happy to dig deeper and suggest a solution. |
I did test it and it did not work at first. On further investigation, I noticed it works when the call to |
Aha! Then that needs investigation. I specifically had It's pretty late here so I'll get back to this tomorrow. |
… and two weeks have passed 🥲 @yanns since you're very active now, curious whether you have time to look into this. To repeat the important bits from above.. The test added in I anticipated this problem, but apparently for the wrong reason.
Still, something is preventing the |
I'm not sure I understand what the problem is. let app = Router::new()
.route("/", get(|| async { "index" }))
.with_state("state")
.method_not_allowed_fallback(|State(state): State<&'static str>| async move { state }); then the code does not compile:
Is it the issue and the code should compile? |
Ah, maybe there was simply a misunderstanding! Could you try |
This is also working: async fn mna_fallback_with_state() {
let app = Router::new()
.route("/", get(|| async { "index" }))
.with_state(())
.method_not_allowed_fallback(|| async move { "bla" });
let client = TestClient::new(app);
let res = client.post("/").await;
assert_eq!(res.text().await, "bla");
} |
Great. @Lachstec could you resolve the merge conflicts and add the test above (keep the one you wrote too)? |
6cd8386
to
2d156dd
Compare
2ed97f2
to
6cd8386
Compare
f7580f2
to
6a0d9a2
Compare
@jplatte Done! Sorry for taking a while, was fiddling around with rebasing because I was a little bit confused, but it should be fine now. If you require any other changes, let me know :) |
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.
Implementation and tests are good now. I took a closer look at the docs now, can you check whether all these suggestions make sense?
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
@jplatte Thank you for the suggestions, I think they are a well fit, so I adapted them. |
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.
Merging. Thanks for your endurance through many rounds of review!
Co-authored-by: Jonas Platte <jplatte+git@posteo.de>
Adds the possibility to specify a default fallback if a route exists, but the method is not allowed. Fixes #2251.
Motivation
There are usecases where it is required to specify a default handler for when a route exists, but the method that was used to access it is not allowed. An example would be returning a JSON response when the method is not allowed, but have a different handler if no route exists at all. This is currently not possible. The issue #2251 suggests that this functionality is desired by users.
Solution
Add a new public function
method_not_allowed_fallback(self, handler: H) -> Self
toRouter
that calls a new private function,method_not_allowed_fallback(self, handler: H)
, onPathRouter
. This function loops over the registered endpoints and sets the fallback on an endpoint if it is a method router.