-
Notifications
You must be signed in to change notification settings - Fork 83
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
refactor: overhaul errors #395
base: main
Are you sure you want to change the base?
Conversation
Hmph. The CI duly notes that this makes interop with hyper http more difficult (obviously). |
71276ec
to
39ecbd7
Compare
39ecbd7
to
56fda40
Compare
@yoshuawuyts Hey I would like to merge this tomorrow if there is no objection |
56fda40
to
d10f4a8
Compare
Made one additional change to this... all the enums are |
|
||
#[cfg(feature = "hyperium_http")] | ||
#[error("Hyperium HTTP error: {}", .0)] | ||
HyperiumHttp(#[from] http::Error), |
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.
Could we just bundle this into a case for third-party library errors, and support downcasting? That would avoid exposing third-party types in our API, which could introduce breakage if those libraries bump versions.
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.
@joshtriplett What would that look like? Specifically the "bundle this into a case for third-party library errors" part of that
#[error("ETag header was invalid")] | ||
ETagInvalid, | ||
#[error("Age header was invalid: length out of bounds (unsized 64 bit integer)")] | ||
AgeInvalid, |
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.
In general, do we want to have one of these variants for every header, or do we want to have one variant that has a header name and a message?
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.
That's a good question, I don't know, but it would become trickier in some circumstances.
I figured it might be useful in code sometimes to be able to match on the header error (but this is just a feeling).
Some headers have error situations with non-&'static str
information.
Also some don't really have any error variance and I can't forsee where they would, like ETag
or Age
, so I didn't give them a &'static str
, but maybe they should all have that.
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.
Another question would be naming... how do we feel about <header name>Invalid<optional detailed invalid area>
?
#[error("HTTP Date-Time invalid seconds")] | ||
SecondsInvalid, | ||
#[error("HTTP Date-Time invalid minutes")] | ||
MinutesInvalid, | ||
#[error("HTTP Date-Time invalid hours")] | ||
HourInvalid, | ||
#[error("HTTP Date-Time invalid day")] | ||
DayInvalid, | ||
#[error("HTTP Date-Time invalid month")] | ||
MonthInvalid, | ||
#[error("HTTP Date-Time invalid year")] | ||
YearInvalid, | ||
#[error("HTTP Date-Time invalid week-day")] | ||
WeekdayInvalid, |
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.
Is anyone going to use individual variants like this, rather than a more general parse error? When would someone want to treat these programmatically differently, rather than just showing a different error?
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.
Hmm. The existing code just made all these errors and I kinda replicated it... I don't know if it would be useful... if not these could probably be &'static str
s...
Posted a few bits of feedback, but generally this looks great. Thanks for the substantial amount of work here. |
d10f4a8
to
5593ccd
Compare
Overhauls errors to allow for 3 types of errors: - Concrete errors (enum) from http-types itself - A dynamic error type for response handlers - A combined type for handling request+response for a client
5593ccd
to
5f5eb12
Compare
@yoshuawuyts if you are going to write a bunch of typed headers could you please take a look at this first? |
@Fishrock123 thanks so much for the ping! - we were actually running into very similar issues around error handling while looking to integrate I still need to look at this line-by-line, but want to at least respond that I agree that we should land this before any further work on typed headers. |
I haven't read the diff, but just a quick though since future API breakage seems to be a strong concern here. Consider making all the concrete enums nonexhaustive. That will permit expanding them in future without API breakage - everyone will need to explicitly handle unexpected errors and not assume the error space will expand. (See e.g. filesystem errors in the stdlib for the pain of not doing this in advance). |
Yes, it will be a large api change. I think that’s fine since no one really likes the current api anyway. Also, yes I already did mark them all as |
I'm maintaining a hard fork of this repo that I plan to keep up to date, please resubmit this PR at https://github.com/OneOfOne/http-types-rs |
Overhauls errors to allow for 3 types of errors:
Error
was previously)There is some exposition for this in Zulip: https://http-rs.zulipchat.com/#narrow/stream/261414-http-types/topic/New.20error.20types.20.26.20result.20apis/near/254273467
Basically this solves two problems:
The first problem is pretty simple to solve but was quite laborious. It meant changing all those
bail!("some string error")
and what not to be concrete enum variants to some degree of specificity. I have kept some errors grouped together where the string output could mean something to anyone debugging a problem but is unlikely to be something which someone would reasonably want to check during program runtime. This is to reduce the amount of labor doing this but also to cap the enum variants and prevent the number of variants from becoming unmanageable.The second problem is tricky and weird. My solution is
RequestError
. This allows dynamic errors from surf middleware but also allows us to have concrete errors there. Some indirection is required forResponseError
due toStdError
's conflict withanyhow
(The problem is a conflict withFrom<T> for T
, which I will never not be profusely annoyed at).There are some potential issues here / open questions:
HTTP(http_types::Error)
or such, which... isn't really correct.HeaderError
,BodyError
, etc. Would need to make a couple extra types.Error::ArgTryIntoError(Box<dyn std::error::Error + Send + Sync + 'static>)
exist? Would returningResult<Result<T>>
in the necessary places be better? (@yoshuawuyts this is what I was asking on Zulip)Send + Sync + 'static
requirements correct or a problem?Edit: the diff is obviously quite large, so here are the interesting parts:
errors::error_kind.rs
errors::mod.rs
errors::request_error.rs
errors::response_error.rs