-
Notifications
You must be signed in to change notification settings - Fork 618
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
Error response refactoring step 2 #1929
Conversation
For a bit further context, the tests for the generic error to response behavior are here. Basically, the error handling behavior is:
|
I've pushed an additional commit to resolve an issue in logging chained errors that was uncovered by this branch. Returning the following from a controller None.chain_error(|| internal("inner error")).chain_error(|| internal("middle error")).chain_error(|| internal("outer error")) results in logging only the outer error on
With the changes in this PR to go through
With the final commit here, we now see the expected log output:
I've added it to this PR since it doesn't really fix anything as a standalone fix on master. |
☔ The latest upstream changes (presumably #1891) made this pull request unmergeable. Please resolve the merge conflicts. |
This serves as a guard rail to help avoid using the wrong error response method. Two files still reference the generic prelude, becuase those files contain mixed endpoints and there is no reason to do a larger refactor at this time.
The `impl<E: AppError> fmt::Display for ChainedError<E>` is sufficient.
2df534f
to
a5a451e
Compare
I've rebased to resolve merge conflicts. I also have a series of commits building on this branch. I'll open a separate PR for that once this lands and I have a chance to add more documentation. |
@jtgeibel Apologies for the delay in reviewing this – I'll get to this in the weekend. |
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 doing this refactoring! The idiosyncratic error reporting, and the wrong status codes in particular, have always irked me, and I'm glad to see these changes.
The endpoints you changed the status codes for look like they are not used by Cargo to me, but I don't know all the things that Cargo can do and have not double-checked in the Cargo code base. It would be great if we could add integration tests for the interaction with Cargo, so we can be more confident about changes that might cause regressions.
Would it be possible to add a test that error chains are logged correctly? Preferably in a fuzzy way, e.g. only making sure that the error message of each error in the change appears exactly once in the log.
My understanding is that with the exception of download, all interactions with crates.io are via the
That would be awesome!
I've pushed some commits that add tests for the I don't think its worth adding anything more complicated at the moment (such as integrating with the logging middleware to capture the actual log output). Right now most uses of |
00deb91
to
2f1e697
Compare
Looks good to me. @bors r+ |
📌 Commit 2f1e697 has been approved by |
Error response refactoring step 2 This is a continuation of #1920. This series captures several changes: * The controller prelude is split to provide helpers for either cargo or frontend endpoints. Eventually this will be unnecessary, but I see it as a temporary guard rail to encourage the correct usage. * Several user and session frontend endpoints are updated to return a response with the correct HTTP status. Tests were updated as necessary. * A `util::errors::http` module is added for concrete error types associated with HTTP status codes. There are more types to be moved here, but for review purposes that can be done in another PR. * Once `cargo_err` was refactored to use `http::Ok`, all of the description and fallback logic in the `AppError` trait and `ConcreteAppError` type was no longer necessary. Here is what I have in mind for the next steps in this refactor: * Add a `not_found` helper that allows a 404 status with an error message for the client. (TBD if this can be merged with the existing `NotFound` type or if that functionality should remain independent.) * Finish moving types to `http` as applicable. * Review remaing existing usage of helpers within controllers. After that groundwork, my final step is to investigate the ability to sanitize error response for cargo at the router level so that `cargo_err` can be removed. It isn't really practical currently to use the correct helper type from within models, since model functionality can be used from either type of endpoint (or both). The router seems like a strange place for that behavior, but it's where the [error to response conversion](https://github.com/rust-lang/crates.io/blob/4a1542cb17ae50c2bfd0f7e85876d82617e30415/src/router.rs#L139) already happens, and the middleware layer only sees a generic `dyn Error`, not our `AppError`. With a central place to sanitize errors for old cargo versions, we could even enable it only for old (and empty) user agents. r? @smarnach
☀️ Test successful - checks-travis |
Add a concrete `util::Error` type (step 3 of refactoring) This PR may be easier to review commit by commit. Overall this series continues the previous refactoring work in #1920 and #1929. In particular, a concrete `util::Error` error type is introduced. The code is updated to follow a style where: * The new concrete type `util::Error` is great for code that is not part of the request/response lifecycle. Binaries have been converted to `fn main() -> Result<(), Error>` where applicable. This avoids pulling in the unnecessary infrastructure to convert errors into a user facing JSON responses (relative to `AppError`). * There are now 13 results across 6 files for `, Error>`. Usage occurs in `src/bin/`, `src/boot/`, and `src/uploaders.rs`. * `diesel::QueryResult` - There is a lot of code that only deals with query errors. If only one type of error is possible in a function, using that specific error is preferable to the more general `util::Error`. This is especially common in model code. * There are now 49 results across 16 files for `QueryResult<`. Most usage is in `src/models/`, with some usage in `src/publish_rate_limit.rs`, `src/tasks/`, and `src/tests/`. * `util::errors::AppResult` - Some failures should be converted into user facing JSON responses. This error type is more dynamic and is box allocated. Low-level errors are typically not converted to user facing errors and most usage is within the models, controllers, and middleware layers (85 of 102 results below). * There are now 102 results across 36 files for `AppResult<`. Most usage is in `src/controllers/` and `src/models/`, with additional usage in `src/middleware/`, `src/{email,github,publish_rate_limit,router,uploaders}.rs`, and `src/{tests,util}/`. Finally, a `middleware::Result` type is introduced for use in middleware and router code. The behavior of `dyn AppError` and `chain_error` is a remaining area for improvement. There may be cases where we want to wrap an `internal` error in a user facing error (like `cargo_err` or `server_err`) and still have the internal error make it up to the logging middleware. However, I don't see an easy way to propagate this up the middleware stack (without encoding it in an internal response header that we later remove, :sweat:). r? @smarnach
This is a continuation of #1920. This series captures several changes:
util::errors::http
module is added for concrete error types associated with HTTP status codes. There are more types to be moved here, but for review purposes that can be done in another PR.cargo_err
was refactored to usehttp::Ok
, all of the description and fallback logic in theAppError
trait andConcreteAppError
type was no longer necessary.Here is what I have in mind for the next steps in this refactor:
not_found
helper that allows a 404 status with an error message for the client. (TBD if this can be merged with the existingNotFound
type or if that functionality should remain independent.)http
as applicable.After that groundwork, my final step is to investigate the ability to sanitize error response for cargo at the router level so that
cargo_err
can be removed. It isn't really practical currently to use the correct helper type from within models, since model functionality can be used from either type of endpoint (or both).The router seems like a strange place for that behavior, but it's where the error to response conversion already happens, and the middleware layer only sees a generic
dyn Error
, not ourAppError
.With a central place to sanitize errors for old cargo versions, we could even enable it only for old (and empty) user agents.
r? @smarnach