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}