rocket_community/response/debug.rs
1use crate::http::Status;
2use crate::request::Request;
3use crate::response::{self, Responder};
4
5/// Debug prints the internal value before forwarding to the 500 error catcher.
6///
7/// This value exists primarily to allow handler return types that would not
8/// otherwise implement [`Responder`]. It is typically used in conjunction with
9/// `Result<T, E>` where `E` implements `Debug` but not `Responder`.
10///
11/// Note that because of it's common use as an error value, `std::io::Error`
12/// _does_ implement `Responder`. As a result, a `std::io::Result<T>` can be
13/// returned directly without the need for `Debug`:
14///
15/// ```rust
16/// # extern crate rocket_community as rocket;
17/// use std::io;
18///
19/// # use rocket::get;
20/// use rocket::fs::NamedFile;
21///
22/// #[get("/")]
23/// async fn index() -> io::Result<NamedFile> {
24/// NamedFile::open("index.html").await
25/// }
26/// ```
27///
28/// # Example
29///
30/// Because of the generic `From<E>` implementation for `Debug<E>`, conversions
31/// from `Result<T, E>` to `Result<T, Debug<E>>` through `?` occur
32/// automatically:
33///
34/// ```rust
35/// # extern crate rocket_community as rocket;
36/// use std::string::FromUtf8Error;
37///
38/// # use rocket::get;
39/// use rocket::response::Debug;
40///
41/// #[get("/")]
42/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {
43/// # /*
44/// let bytes: Vec<u8> = random_bytes();
45/// # */
46/// # let bytes: Vec<u8> = vec![];
47/// Ok(String::from_utf8(bytes)?)
48/// }
49/// ```
50///
51/// It is also possible to map the error directly to `Debug` via
52/// [`Result::map_err()`]:
53///
54/// ```rust
55/// # extern crate rocket_community as rocket;
56/// use std::string::FromUtf8Error;
57///
58/// # use rocket::get;
59/// use rocket::response::Debug;
60///
61/// #[get("/")]
62/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {
63/// # /*
64/// let bytes: Vec<u8> = random_bytes();
65/// # */
66/// # let bytes: Vec<u8> = vec![];
67/// String::from_utf8(bytes).map_err(Debug)
68/// }
69/// ```
70#[derive(Debug)]
71pub struct Debug<E>(pub E);
72
73impl<E> From<E> for Debug<E> {
74 #[inline(always)]
75 fn from(e: E) -> Self {
76 Debug(e)
77 }
78}
79
80impl<'r, E: std::fmt::Debug> Responder<'r, 'static> for Debug<E> {
81 fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
82 let type_name = std::any::type_name::<E>();
83 info!(type_name, value = ?self.0, "debug response (500)");
84 Err(Status::InternalServerError)
85 }
86}
87
88/// Prints a warning with the error and forwards to the `500` error catcher.
89impl<'r> Responder<'r, 'static> for std::io::Error {
90 fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
91 warn!("i/o error response: {self}");
92 Err(Status::InternalServerError)
93 }
94}