use crate::{responder::Responder, response::Response};
use hyper::header::InvalidHeaderValue;
use std::fmt::Debug;
#[derive(thiserror::Error)]
pub enum Error {
#[error("Hyper: {0}")]
Hyper(#[from] hyper::Error),
#[error("Http: {0}")]
Http(#[from] hyper::http::Error),
#[error("Io: {0}")]
Io(#[from] std::io::Error),
#[error("Boxed: {0}")]
Boxed(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Error: {0}")]
Other(String),
#[error("Response StatusCode `{0}`")]
Status(u16),
#[error("Response StatusCode `{0}`,Response Body: {1}")]
Response(u16, serde_json::Value),
#[error("Utf8Error: {0}")]
Utf8Error(#[from] std::str::Utf8Error),
#[error("SerdeJson: {0}")]
SerdeJson(#[from] serde_json::error::Error),
#[error("Deserialize error: {0}")]
Deserialize(#[from] serde::de::value::Error),
#[error("http header error: {0}")]
ToStrError(#[from] hyper::header::ToStrError),
#[cfg(feature = "native_tls")]
#[error("tokio_native_tls error: {0}")]
TokioNativeTls(#[from] tokio_native_tls::native_tls::Error),
#[error("Missing parameter `{0}` (is_query: {1})")]
MissingParameter(String, bool),
#[error("Invalid parameter `{0}` (is_query: {1})")]
InvalidParameter(String, bool),
#[cfg(feature = "msgpack")]
#[error("Could not deserialize the body of a request or response from MessagePack")]
MsgpackDe(#[source] rmp_serde::decode::Error),
#[error("An multer error: {0}")]
Multer(#[from] multer::Error),
#[cfg(feature = "validate")]
#[error("ValidationErrors: {0}")]
ValidationErrors(#[from] validator::ValidationErrors),
#[cfg(feature = "websocket")]
#[error("WebSocket: {0}")]
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
}
impl Error {
#[inline]
pub(crate) fn response_builder(self, builder: Response) -> Response {
match self {
Self::Hyper(e) => builder.status(500).text(e.to_string()),
Self::Http(e) => builder.status(500).text(e.to_string()),
Self::Io(e) => builder.status(500).text(e.to_string()),
#[cfg(feature = "native_tls")]
Self::TokioNativeTls(e) => builder.status(500).text(e.to_string()),
Self::Boxed(e) => builder.status(500).text(e.to_string()),
Self::Other(e) => builder.status(400).text(e.to_string()),
Self::Status(s) => builder.status(s),
Self::Response(s, e) => builder.status(s).text(e.to_string()),
Self::Utf8Error(e) => builder.status(400).text(e.to_string()),
Self::SerdeJson(e) => builder.status(400).text(e.to_string()),
Self::Deserialize(e) => builder.status(400).text(e.to_string()),
Self::ToStrError(e) => builder.status(400).text(e.to_string()),
Self::MissingParameter(e, _) => builder.status(400).text(e.to_string()),
Self::InvalidParameter(e, _) => builder.status(400).text(e.to_string()),
#[cfg(feature = "msgpack")]
Self::MsgpackDe(e) => builder.status(400).text(e.to_string()),
Self::Multer(e) => builder.status(400).text(e.to_string()),
#[cfg(feature = "validate")]
Self::ValidationErrors(e) => builder.status(400).text(e.to_string()),
#[cfg(feature = "websocket")]
Self::WebSocket(e) => builder.status(400).text(e.to_string()),
}
}
}
impl Debug for Error {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
Self::Hyper(d) => std::fmt::Debug::fmt(d, f),
Self::Http(d) => std::fmt::Debug::fmt(d, f),
Self::Io(d) => std::fmt::Debug::fmt(d, f),
Self::Boxed(d) => std::fmt::Debug::fmt(d, f),
Self::Other(d) => std::fmt::Debug::fmt(d, f),
Self::Status(d) => std::fmt::Debug::fmt(d, f),
Self::Response(_, d) => std::fmt::Debug::fmt(d, f),
Self::Utf8Error(d) => std::fmt::Debug::fmt(d, f),
Self::SerdeJson(d) => std::fmt::Debug::fmt(d, f),
Self::Deserialize(d) => std::fmt::Debug::fmt(d, f),
Self::ToStrError(d) => std::fmt::Debug::fmt(d, f),
Self::MissingParameter(d, _) => std::fmt::Debug::fmt(d, f),
Self::InvalidParameter(d, _) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "native_tls")]
Self::TokioNativeTls(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "msgpack")]
Self::MsgpackDe(d) => std::fmt::Debug::fmt(d, f),
Self::Multer(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "validate")]
Self::ValidationErrors(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "websocket")]
Self::WebSocket(d) => std::fmt::Debug::fmt(d, f),
}
}
}
impl From<std::convert::Infallible> for Error {
fn from(e: std::convert::Infallible) -> Self {
Self::Boxed(Box::new(e))
}
}
impl From<InvalidHeaderValue> for Error {
#[inline]
fn from(e: InvalidHeaderValue) -> Self {
Error::Http(hyper::http::Error::from(e))
}
}
impl Responder for Error {
#[inline]
fn response(self, builder: Response) -> Response {
self.response_builder(builder)
}
}