1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
use crate::request::Request;
use crate::response::{self, Response, Responder};
use crate::http::Status;

use yansi::Paint;

/// Debug prints the internal value before responding with a 500 error.
///
/// This value exists primarily to allow handler return types that would not
/// otherwise implement [`Responder`]. It is typically used in conjunction with
/// `Result<T, E>` where `E` implements `Debug` but not `Responder`.
///
/// # Example
///
/// Because of the generic `From<E>` implementation for `Debug<E>`, conversions
/// from `Result<T, E>` to `Result<T, Debug<E>>` through `?` occur
/// automatically:
///
/// ```rust
/// # #![feature(proc_macro_hygiene, decl_macro)]
/// use std::io::{self, Read};
///
/// # use rocket::post;
/// use rocket::Data;
/// use rocket::response::Debug;
///
/// #[post("/", format = "plain", data = "<data>")]
/// fn post(data: Data) -> Result<String, Debug<io::Error>> {
///     let mut name = String::with_capacity(32);
///     data.open().take(32).read_to_string(&mut name)?;
///     Ok(name)
/// }
/// ```
///
/// It is also possible to map the error directly to `Debug` via
/// [`Result::map_err()`]:
///
/// ```rust
/// # #![feature(proc_macro_hygiene, decl_macro)]
/// use std::string::FromUtf8Error;
///
/// # use rocket::get;
/// use rocket::response::Debug;
///
/// #[get("/")]
/// fn rand_str() -> Result<String, Debug<FromUtf8Error>> {
///     # /*
///     let bytes: Vec<u8> = random_bytes();
///     # */
///     # let bytes: Vec<u8> = vec![];
///     String::from_utf8(bytes).map_err(Debug)
/// }
/// ```
#[derive(Debug)]
pub struct Debug<E>(pub E);

impl<E> From<E> for Debug<E> {
    #[inline(always)]
    fn from(e: E) -> Self {
        Debug(e)
    }
}

impl<'r, E: std::fmt::Debug> Responder<'r> for Debug<E> {
    fn respond_to(self, _: &Request<'_>) -> response::Result<'r> {
        warn_!("Debug: {:?}", Paint::default(self.0));
        warn_!("Debug always responds with {}.", Status::InternalServerError);
        Response::build().status(Status::InternalServerError).ok()
    }
}