use std::error::Error;
use std::fmt::{self, Debug, Display, Formatter};
use hyper::{Response, StatusCode};
use handler::IntoResponse;
use state::{request_id, State};
use http::response::create_response;
pub struct HandlerError {
status_code: StatusCode,
cause: Box<Error>,
}
pub trait IntoHandlerError {
fn into_handler_error(self) -> HandlerError;
}
impl<E> IntoHandlerError for E
where
E: Error + 'static,
{
fn into_handler_error(self) -> HandlerError {
trace!(" converting Error to HandlerError: {}", self);
HandlerError {
status_code: StatusCode::InternalServerError,
cause: Box::new(self),
}
}
}
impl Display for HandlerError {
fn fmt(&self, out: &mut Formatter) -> fmt::Result {
out.write_str("handler failed to process request")
}
}
impl Debug for HandlerError {
fn fmt(&self, out: &mut Formatter) -> fmt::Result {
Display::fmt(self, out)?;
out.write_str(" (")?;
Debug::fmt(&*self.cause, out)?;
out.write_str(")")
}
}
impl Error for HandlerError {
fn description(&self) -> &str {
"handler failed to process request"
}
fn cause(&self) -> Option<&Error> {
Some(&*self.cause)
}
}
impl HandlerError {
pub fn with_status(self, status_code: StatusCode) -> HandlerError {
HandlerError {
status_code,
..self
}
}
}
impl IntoResponse for HandlerError {
fn into_response(self, state: &State) -> Response {
debug!(
"[{}] HandlerError generating {} {} response: {}",
request_id(state),
self.status_code.as_u16(),
self.status_code
.canonical_reason()
.unwrap_or("(unregistered)",),
self.cause().map(|e| e.description()).unwrap_or("(none)"),
);
create_response(state, self.status_code, None)
}
}