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 = "websocket")]
#[error("WebSocket: {0}")]
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
#[cfg(feature = "openapi")]
#[error("StatusError: {0}")]
StatusError(hypers_openapi::StatusError),
}
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 = "websocket")]
Self::WebSocket(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "openapi")]
Self::StatusError(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, res: &mut Response) {
let (status, text) = match self {
Self::Hyper(e) => (500, e.to_string()),
Self::Http(e) => (500, e.to_string()),
Self::Io(e) => (500, e.to_string()),
#[cfg(feature = "native_tls")]
Self::TokioNativeTls(e) => (500, e.to_string()),
Self::Boxed(e) => (500, e.to_string()),
Self::Other(e) => (400, e),
Self::Status(s) => (s, "".to_owned()),
Self::Response(s, e) => (s, e.to_string()),
Self::Utf8Error(e) => (400, e.to_string()),
Self::SerdeJson(e) => (400, e.to_string()),
Self::Deserialize(e) => (400, e.to_string()),
Self::ToStrError(e) => (400, e.to_string()),
Self::MissingParameter(e, _) => (400, e),
Self::InvalidParameter(e, _) => (400, e),
#[cfg(feature = "msgpack")]
Self::MsgpackDe(e) => (400, e.to_string()),
Self::Multer(e) => (400, e.to_string()),
#[cfg(feature = "websocket")]
Self::WebSocket(e) => (400, e.to_string()),
#[cfg(feature = "openapi")]
Self::StatusError(e) => (e.code.as_u16(), e.detail),
};
res.status(status).body(text);
}
}