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}