-
Notifications
You must be signed in to change notification settings - Fork 1k
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Add new traits and types to improve error handling user experience.
Adds the trait `IntoResultResponse` to be use in place of `IntoResponse` in handlers to allow easy use of `?` on standard errors and other implementations like `anyhow` and `eyre`. The type `ErrorResponse` encapsulate any kind of error with an associated `StatusCode` and the type alias `ResultResponse` use it by default in a `Result`. `ErrorResponse` can be converted from any `Into<Box<dyn Error>>` and also implements `IntoResponse`. `IntoResultResponse` is only implemented by `ResultResponse` to force the type system to unambiguously convert any errors from handlers to `ErrorResponse` when using `?`. This commits only add new traits and types doesn't change any existing API.
- Loading branch information
1 parent
2ec68d6
commit 1d2a674
Showing
10 changed files
with
98 additions
and
69 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,39 @@ | ||
use std::error::Error; | ||
|
||
use http::StatusCode; | ||
|
||
use crate::response::{IntoResponse, Response}; | ||
|
||
/// `ErrorResponse` encapsulates an `Error` and a `StatusCode` to be used as a response, typically in a `Result`. | ||
/// | ||
/// If not `StatusCode` is provided, `StatusCode::INTERNAL_SERVER_ERROR` is used. | ||
#[derive(Debug)] | ||
pub struct ErrorResponse { | ||
status: StatusCode, | ||
error: Box<dyn Error>, | ||
} | ||
|
||
impl ErrorResponse { | ||
/// Create a new `ErrorResponse` with the given status code and error. | ||
pub fn new(status: StatusCode, error: impl Into<Box<dyn Error>>) -> Self { | ||
Self { | ||
status, | ||
error: error.into(), | ||
} | ||
} | ||
} | ||
|
||
impl<E: Into<Box<dyn Error>>> From<E> for ErrorResponse | ||
{ | ||
fn from(error: E) -> Self { | ||
Self::new(StatusCode::INTERNAL_SERVER_ERROR, error) | ||
} | ||
} | ||
|
||
impl IntoResponse for ErrorResponse { | ||
fn into_response(self) -> Response { | ||
let error = format!("{:?}", self.error); | ||
tracing::error!(error = %error); | ||
(self.status, error).into_response() | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,5 +1,6 @@ | ||
pub(crate) mod request; | ||
pub(crate) mod request_parts; | ||
pub(crate) mod result; | ||
|
||
#[cfg(test)] | ||
mod tests { | ||
|
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,20 @@ | ||
use std::error::Error; | ||
|
||
use http::StatusCode; | ||
|
||
use crate::{response::{IntoResponse, ResultResponse}, error_response::ErrorResponse}; | ||
|
||
/// A extention trait to Result to easily attach a `StatusCode` to an error by encapsulating the | ||
/// error into a `ErrorResponse`. | ||
pub trait ResultExt<T: IntoResponse> { | ||
/// maps the error type to a `ErrorResponse` with the given status code. | ||
fn err_with_status(self, status: StatusCode) -> ResultResponse<T>; | ||
} | ||
|
||
impl<T: IntoResponse, E: Into<Box<dyn Error>>> ResultExt<T> for std::result::Result<T, E> { | ||
fn err_with_status(self, status:StatusCode) -> ResultResponse<T> { | ||
self.map_err(|error| { | ||
ErrorResponse::new(status, error) | ||
}) | ||
} | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,18 @@ | ||
use crate::error_response::ErrorResponse; | ||
|
||
use super::IntoResponse; | ||
|
||
/// Trait for generating fallible responses in handlers. | ||
/// | ||
/// This trait is bound by `IntoResponse` and therefor can be be interchanged with it | ||
/// when returning a `Result` from a handler. | ||
/// | ||
/// This trait is only implemented for `ResultResponse<T>` aka `Result<T, ErrorResponse>` | ||
/// where both `T` and `ErrorResponse` implement `IntoResponse`. | ||
/// | ||
/// The trait allows to return a `Result` from a handler. | ||
pub trait IntoResultResponse: IntoResponse {} | ||
impl<T: IntoResponse> IntoResultResponse for ResultResponse<T> {} | ||
|
||
/// A type alias for `Result<T, ErrorResponse>`. | ||
pub type ResultResponse<T, E = ErrorResponse> = std::result::Result<T, E>; |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters