rocket/response/
debug.rs

1use crate::request::Request;
2use crate::response::{self, Responder};
3use crate::http::Status;
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/// use std::io;
17///
18/// # use rocket::get;
19/// use rocket::fs::NamedFile;
20///
21/// #[get("/")]
22/// async fn index() -> io::Result<NamedFile> {
23///     NamedFile::open("index.html").await
24/// }
25/// ```
26///
27/// # Example
28///
29/// Because of the generic `From<E>` implementation for `Debug<E>`, conversions
30/// from `Result<T, E>` to `Result<T, Debug<E>>` through `?` occur
31/// automatically:
32///
33/// ```rust
34/// use std::string::FromUtf8Error;
35///
36/// # use rocket::get;
37/// use rocket::response::Debug;
38///
39/// #[get("/")]
40/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {
41///     # /*
42///     let bytes: Vec<u8> = random_bytes();
43///     # */
44///     # let bytes: Vec<u8> = vec![];
45///     Ok(String::from_utf8(bytes)?)
46/// }
47/// ```
48///
49/// It is also possible to map the error directly to `Debug` via
50/// [`Result::map_err()`]:
51///
52/// ```rust
53/// use std::string::FromUtf8Error;
54///
55/// # use rocket::get;
56/// use rocket::response::Debug;
57///
58/// #[get("/")]
59/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {
60///     # /*
61///     let bytes: Vec<u8> = random_bytes();
62///     # */
63///     # let bytes: Vec<u8> = vec![];
64///     String::from_utf8(bytes).map_err(Debug)
65/// }
66/// ```
67#[derive(Debug)]
68pub struct Debug<E>(pub E);
69
70impl<E> From<E> for Debug<E> {
71    #[inline(always)]
72    fn from(e: E) -> Self {
73        Debug(e)
74    }
75}
76
77impl<'r, E: std::fmt::Debug> Responder<'r, 'static> for Debug<E> {
78    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
79        let type_name = std::any::type_name::<E>();
80        info!(type_name, value = ?self.0, "debug response (500)");
81        Err(Status::InternalServerError)
82    }
83}
84
85/// Prints a warning with the error and forwards to the `500` error catcher.
86impl<'r> Responder<'r, 'static> for std::io::Error {
87    fn respond_to(self, _: &'r Request<'_>) -> response::Result<'static> {
88        warn!("i/o error response: {self}");
89        Err(Status::InternalServerError)
90    }
91}