-
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 a separate trait for optional extractors #2475
base: main
Are you sure you want to change the base?
Conversation
91fabd2
to
b8f499e
Compare
@davidpdrsn Have you had time to take a look? The main changes are done, and I don't want to do the remaining docs / changelog writing and cleanup if it's not yet clear whether this will be merged. |
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.
One thing that bugs me is that the optional variants use the same rejections so for example if someone uses the optional typed header there still is valid representation in the rejection. for the missing case.
That said the rejections are non exhaustive so they cannot handle explicitly everything so they may omit this one as well. It might just be confusing.
I will read it more thoroughly tomorrow or over the weekend, but it makes sense as a whole.
I want to think on other ways to make the option work but on a first sight this may be the best solution.
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 code looks good to me.
The drawback I see here is having two distinct traits so it might be harder for users to discover how to properly use Option
s. That said in hindsight, it might be better to force users to use Result
instead of Option
if they really mean to just discard any errors.
I am still unsure about whether it is better to use the same rejections for optional and normal extractors if the missing case is already handled in the normal rejection. I think we could use some kind of enum (probably very similar to Option
) for extractors that have optional variants. But each extractor would have to define IntoResponse
for its missing case.
I also wonder if we couldn't get away with just one FromRequestParts
trait where the extracting method would return an enum with three cases like MyResult<T, T::Missing, T::Rejection>
. Then we could maybe create the extractors with correct semantics without the need for multiple traits.
But if that's not possible or having the two traits is a better tradeoff than whatever issues that potential solution has, the implementation as is looks ok. I think we should just go over the implementations of FromRequest
and FromRequstParts
and add a few implementations for the optional conterparts.
#[derive(Debug, Clone, Copy, Default)] | ||
pub struct OptionalQuery<T>(pub Option<T>); | ||
|
||
#[allow(deprecated)] |
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.
OptionalPath
became this:
parts
.extract::<Option<Path<T>>>()
.await
.map(|opt| Self(opt.map(|Path(x)| x)))
I think that a similar thing can be done here.
async fn option_handler(_: Option<UsersShow>) {} | ||
|
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 think this should also be derived and usable.
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.
Why? When would it be None
?
axum/src/extract/matched_path.rs
Outdated
where | ||
S: Send + Sync, | ||
{ | ||
type Rejection = MatchedPathRejection; |
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 think this should be Infallible
as missing is the only failure case.
And just to be sure, it seems to me like the only way MatchedPath
would be missing is if it is accessed inside a fallback handler? If that's so, I think it would be better not to add this impl and have users just use Result
if they want to guard against using it there.
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.
It could also be missing if you don't use Router
at all, for example calling .into_service()
on a handler and using the resulting handler as a standalone service.
Why would it be better to require users to use Result
here in your opinion? I think both the Option
and Result
route are very rarely useful, but if you want to distinguish, or just be defensive against logic bugs affecting other parts of the system, the Option
route seems more convenient.
Damn, I didn't realize I failed to respond to most of the feedback here since asking for it. I definitely think having more specific rejection types would be better. I think it's something I skipped initially because it was just easier that way for the first prototype. I'll try to make some time to back to this soon-ish. |
226a27e
to
d7446e3
Compare
d7446e3
to
6460d88
Compare
Suggestions for the docs would be very much welcome 😅 |
… and deprecate OptionalPath.
… and deprecate OptionalQuery.
6460d88
to
1f2c649
Compare
Motivation
Closes #2298.
Solution
OptionalFromRequest
,OptionalFromRequestParts
OptionalFoo
extractors