explicit_error_http/
handler.rs

1use crate::{DomainError, Error};
2use explicit_error::Bug;
3use serde::Serialize;
4
5/// The type [Error] cannot directly be used as handlers or middlewares returned [Err] variant. A dedicated type is required.
6/// The easiest implementation is to declare a [Newtype](https://doc.rust-lang.org/rust-by-example/generics/new_types.html),
7/// derive it with the [HandlerErrorHelpers](crate::derive::HandlerErrorHelpers) and implement the [HandlerError] trait.
8/// ```rust
9/// # use actix_web::{App, HttpResponse, HttpServer, get};
10/// # use explicit_error_http::{Bug, Error, HandlerError, derive::HandlerErrorHelpers};
11/// # use log::{debug, error};
12/// # use problem_details::ProblemDetails;
13/// # use serde::Serialize;
14/// #[derive(HandlerErrorHelpers)]
15/// struct MyHandlerError(Error);
16///
17/// impl HandlerError for MyHandlerError {
18///     // Used by the derive for conversion
19///     fn from_error(value: Error) -> Self {
20///         MyHandlerError(value)
21///     }
22///
23///     // Set-up monitoring and your custom HTTP response body for bugs
24///     fn public_bug_response(bug: &Bug) -> impl Serialize {
25///         #[cfg(debug_assertions)]
26///         error!("{bug}");
27///
28///         #[cfg(not(debug_assertions))]
29///         error!("{}", serde_json::json!(bug));
30///
31///         ProblemDetails::new()
32///             .with_type(http::Uri::from_static("/errors/internal-server-error"))
33///             .with_title("Internal server error")
34///     }
35///
36///     fn error(&self) -> &Error {
37///         &self.0
38///     }
39///
40///     // Monitor domain variant of your errors and eventually override their body
41///     fn domain_response(error: &explicit_error_http::DomainError) -> impl Serialize {
42///         if error.output.http_status_code.as_u16() < 500 {
43///             debug!("{error}");
44///         } else {
45///             error!("{error}");
46///         }
47///         error
48///     }
49/// }
50///
51/// #[get("/my-handler")]
52/// async fn my_handler() -> Result<HttpResponse, MyHandlerError> {
53///     Ok(HttpResponse::Ok().finish())
54/// }
55/// ```
56pub trait HandlerError
57where
58    Self: std::fmt::Debug + std::fmt::Display,
59{
60    /// Accessor required by [HandlerErrorHelpers](crate::derive::HandlerErrorHelpers)
61    fn error(&self) -> &Error;
62
63    /// Set-up monitoring and your custom HTTP response body for bugs
64    /// # Examples
65    /// ```rust
66    /// # use explicit_error_http::Bug;
67    /// # use log::{debug, error};
68    /// # use problem_details::ProblemDetails;
69    /// # use serde::Serialize;
70    /// fn public_bug_response(bug: &Bug) -> impl Serialize {
71    ///     #[cfg(debug_assertions)]
72    ///     error!("{bug}");
73    ///
74    ///     #[cfg(not(debug_assertions))]
75    ///     error!("{}", serde_json::json!(bug));
76    ///
77    ///     ProblemDetails::new()
78    ///         .with_type(http::Uri::from_static("/errors/internal-server-error"))
79    ///         .with_title("Internal server error")
80    /// }
81    /// ```
82    fn public_bug_response(bug: &Bug) -> impl Serialize;
83
84    /// Monitor domain variant of your errors and eventually override their body
85    /// # Examples
86    /// ```rust
87    /// # use log::{debug, error};
88    /// # use serde::Serialize;
89    /// fn domain_response(error: &explicit_error_http::DomainError) -> impl Serialize {
90    ///     if error.output.http_status_code.as_u16() < 500 {
91    ///         debug!("{error}");
92    ///     } else {
93    ///         error!("{error}");
94    ///     }
95    ///     error
96    /// }
97    /// ```
98    fn domain_response(error: &DomainError) -> impl Serialize;
99
100    /// Used by the derive for conversion
101    fn from_error(value: Error) -> Self;
102}