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}