use crate::{responder::Responder, response::Builder};
use hyper::{header::InvalidHeaderValue, StatusCode};
use std::fmt::{Debug, Formatter};
#[derive(thiserror::Error, Debug)]
pub enum InternalError {
#[error("Http: {0}")]
Http(hyper::http::Error),
#[error("Hyper: {0}")]
Hyper(hyper::Error),
#[error("ToStr: {0}")]
ToStr(hyper::header::ToStrError),
}
#[derive(thiserror::Error)]
pub enum Error {
#[error("Internal: {0}")]
Internal(#[from] InternalError),
#[error("Io: {0}")]
Io(#[from] std::io::Error),
#[error("Boxed: {0}")]
Boxed(Box<dyn std::error::Error + Send + Sync + 'static>),
#[error("Hyper: {0}")]
Hyper(hyper::Error),
#[error("Other: {0}")]
Other(String),
#[error("Response StatusCode `{0}`")]
Status(StatusCode),
#[error("Response StatusCode `{0}`,Response Body: {1}")]
Response(StatusCode, serde_json::Value),
#[error("FromUtf8Error: {0}")]
FromUtf8Error(#[from] std::string::FromUtf8Error),
#[error("SerdeJson: {0}")]
SerdeJson(#[from] serde_json::error::Error),
#[error("SerdeUrlDe: {0}")]
SerdeUrlDe(#[from] serde_urlencoded::de::Error),
#[error("SerdeUrlSer: {0}")]
SerdeUrlSer(#[from] serde_urlencoded::ser::Error),
#[cfg(feature = "websocket")]
#[error("WebSocket: {0}")]
WebSocket(#[from] tokio_tungstenite::tungstenite::Error),
#[cfg(feature = "multipart")]
#[error("An multer error: {0}")]
Multer(#[from] multer::Error),
#[cfg(feature = "msgpack")]
#[error("could not deserialize the body of a request or response from MessagePack")]
MsgpackDeserialization(#[source] rmp_serde::decode::Error),
#[error("Missing parameter `{0}` (is_query: {1})")]
MissingParameter(String, bool),
#[error("Invalid parameter `{0}` (is_query: {1})")]
InvalidParameter(String, bool),
#[cfg(feature = "validate")]
#[cfg_attr(docsrs, doc(cfg(feature = "validate")))]
#[error("ValidationErrors: {0}")]
ValidationErrors(#[from] validator::ValidationErrors),
#[error("AddrParseError: {0}")]
AddrParseError(#[from] std::net::AddrParseError),
}
impl Debug for Error {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
match self {
Self::Internal(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::Hyper(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::FromUtf8Error(d) => std::fmt::Debug::fmt(d, f),
Self::SerdeJson(d) => std::fmt::Debug::fmt(d, f),
Self::SerdeUrlDe(d) => std::fmt::Debug::fmt(d, f),
Self::SerdeUrlSer(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "websocket")]
Self::WebSocket(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "multipart")]
Self::Multer(d) => std::fmt::Debug::fmt(d, f),
#[cfg(feature = "msgpack")]
Self::MsgpackDeserialization(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 = "validate")]
Self::ValidationErrors(d) => std::fmt::Debug::fmt(d, f),
Self::AddrParseError(d) => std::fmt::Debug::fmt(d, f),
}
}
}
impl Error {
#[inline]
pub(crate) fn response_builder(self, builder: Builder) -> Builder {
match self {
Self::Internal(e) => builder.status(500).text(e.to_string()),
Self::Io(e) => builder.status(500).text(e.to_string()),
Self::Boxed(e) => builder.status(500).text(e.to_string()),
Self::Hyper(e) => builder.status(500).text(e.to_string()),
Self::Other(e) => builder.status(500).text(e.to_string()),
Self::Status(s) => builder.status(s),
Self::Response(s, e) => builder.status(s).text(e.to_string()),
Self::FromUtf8Error(e) => builder.status(400).text(e.to_string()),
Self::SerdeJson(e) => builder.status(400).text(e.to_string()),
Self::SerdeUrlDe(e) => builder.status(400).text(e.to_string()),
Self::SerdeUrlSer(e) => builder.status(400).text(e.to_string()),
#[cfg(feature = "websocket")]
Self::WebSocket(e) => builder.status(400).text(e.to_string()),
#[cfg(feature = "multipart")]
Self::Multer(e) => builder.status(400).text(e.to_string()),
#[cfg(feature = "msgpack")]
Self::MsgpackDeserialization(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 = "validate")]
Self::ValidationErrors(e) => builder.status(400).text(e.to_string()),
Self::AddrParseError(e) => builder.status(400).text(e.to_string()),
}
}
}
impl From<hyper::http::Error> for Error {
#[inline]
fn from(e: hyper::http::Error) -> Self {
Error::Internal(InternalError::Http(e))
}
}
impl From<InvalidHeaderValue> for Error {
#[inline]
fn from(e: InvalidHeaderValue) -> Self {
Error::Internal(InternalError::Http(hyper::http::Error::from(e)))
}
}
impl From<hyper::Error> for Error {
#[inline]
fn from(e: hyper::Error) -> Self {
Error::Internal(InternalError::Hyper(e))
}
}
impl From<hyper::header::ToStrError> for Error {
#[inline]
fn from(e: hyper::header::ToStrError) -> Self {
Error::Internal(InternalError::ToStr(e))
}
}
impl From<std::convert::Infallible> for Error {
fn from(e: std::convert::Infallible) -> Self {
Self::Boxed(Box::new(e))
}
}
impl Responder for Error {
#[allow(unused_variables)]
#[inline]
fn response(self, builder: Builder) -> Builder {
self.response_builder(builder)
}
}