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}