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 [HandlerError](crate::derive::HandlerError) and implement the [HandlerError] trait.
8///
9/// ```rust
10/// # use actix_web::{App, HttpResponse, HttpServer, get};
11/// # use explicit_error_http::{Bug, Error, HandlerError, derive::HandlerError};
12/// # use log::{debug, error};
13/// # use problem_details::ProblemDetails;
14/// # use serde::Serialize;
15/// #[derive(HandlerError)]
16/// struct MyHandlerError(Error);
17///
18/// impl HandlerError for MyHandlerError {
19///     // Used by the derive for conversion
20///     fn from_http_error(value: Error) -> Self {
21///         MyHandlerError(value)
22///     }
23///
24///     // Set-up monitoring and your custom HTTP response body for bugs
25///     fn public_bug_response(bug: &Bug) -> impl Serialize {
26///         #[cfg(debug_assertions)]
27///         error!("{bug}");
28///
29///         #[cfg(not(debug_assertions))]
30///         error!("{}", serde_json::json!(bug));
31///
32///         ProblemDetails::new()
33///             .with_type(http::Uri::from_static("/errors/internal-server-error"))
34///             .with_title("Internal server error")
35///     }
36///
37///     fn http_error(&self) -> &Error {
38///         &self.0
39///     }
40///
41///     // Monitor domain variant of your errors
42///     fn on_domain_response(error: &explicit_error_http::DomainError) {
43///         if error.output.http_status_code.as_u16() < 500 {
44///             debug!("{error}");
45///         } else {
46///             error!("{error}");
47///         }
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 {
57    /// Accessor required by [HandlerError](crate::derive::HandlerError)
58    fn http_error(&self) -> &Error;
59
60    /// Set-up monitoring and your custom HTTP response body for bugs
61    /// # Examples
62    /// ```rust
63    /// # use explicit_error_http::Bug;
64    /// # use log::{debug, error};
65    /// # use problem_details::ProblemDetails;
66    /// # use serde::Serialize;
67    /// fn public_bug_response(bug: &Bug) -> impl Serialize {
68    ///     #[cfg(debug_assertions)]
69    ///     error!("{bug}");
70    ///
71    ///     #[cfg(not(debug_assertions))]
72    ///     error!("{}", serde_json::json!(bug));
73    ///
74    ///     ProblemDetails::new()
75    ///         .with_type(http::Uri::from_static("/errors/internal-server-error"))
76    ///         .with_title("Internal server error")
77    /// }
78    /// ```
79    fn public_bug_response(bug: &Bug) -> impl Serialize;
80
81    /// Monitor domain variant of your errors
82    /// # Examples
83    /// ```rust
84    /// # use log::{debug, error};
85    /// fn on_domain_response(error: &explicit_error_http::DomainError) {
86    ///     if error.output.http_status_code.as_u16() < 500 {
87    ///         debug!("{error}");
88    ///     } else {
89    ///         error!("{error}");
90    ///     }
91    /// }
92    /// ```
93    fn on_domain_response(error: &DomainError);
94
95    /// Used by the derive for conversion
96    fn from_http_error(value: Error) -> Self;
97}