1use crate::{request::RequestError, status::StatusCode};
2use config::ConfigError;
3use serde::{Deserialize, Serialize, de::DeserializeOwned};
4use snafu::Snafu;
5use std::fmt::{self, Display, Formatter};
6use std::io::Error as IoError;
7
8pub trait Error: std::error::Error + Serialize + DeserializeOwned + Send + Sync + 'static {
20 fn catch_all(status: StatusCode, msg: String) -> Self;
21 fn status(&self) -> StatusCode;
22
23 fn message(&self) -> String {
24 self.to_string()
25 }
26
27 fn from_io_error(source: IoError) -> Self {
28 Self::catch_all(StatusCode::INTERNAL_SERVER_ERROR, source.to_string())
29 }
30
31 fn from_config_error(source: ConfigError) -> Self {
32 Self::catch_all(StatusCode::INTERNAL_SERVER_ERROR, source.to_string())
33 }
34
35 fn from_route_error<E: Display>(source: RouteError<E>) -> Self {
36 Self::catch_all(source.status(), source.to_string())
37 }
38
39 fn from_request_error(source: RequestError) -> Self {
40 Self::catch_all(StatusCode::BAD_REQUEST, source.to_string())
41 }
42
43 fn from_socket_error<E: Display>(source: SocketError<E>) -> Self {
44 Self::catch_all(source.status(), source.to_string())
45 }
46}
47
48#[derive(Clone, Debug, Snafu, Serialize, Deserialize, PartialEq, Eq)]
54#[snafu(display("Error {}: {}", status, message))]
55pub struct ServerError {
56 pub status: StatusCode,
57 pub message: String,
58}
59
60impl Error for ServerError {
61 fn catch_all(status: StatusCode, message: String) -> Self {
62 Self { status, message }
63 }
64
65 fn status(&self) -> StatusCode {
66 self.status
67 }
68
69 fn message(&self) -> String {
70 self.message.clone()
71 }
72}
73
74impl From<IoError> for ServerError {
75 fn from(source: IoError) -> Self {
76 Self::from_io_error(source)
77 }
78}
79
80impl From<ConfigError> for ServerError {
81 fn from(source: ConfigError) -> Self {
82 Self::from_config_error(source)
83 }
84}
85
86impl<E: Display> From<RouteError<E>> for ServerError {
87 fn from(source: RouteError<E>) -> Self {
88 Self::from_route_error(source)
89 }
90}
91
92impl From<RequestError> for ServerError {
93 fn from(source: RequestError) -> Self {
94 Self::from_request_error(source)
95 }
96}
97
98impl<E: Display> From<SocketError<E>> for ServerError {
99 fn from(source: SocketError<E>) -> Self {
100 Self::from_socket_error(source)
101 }
102}
103
104#[derive(Debug)]
110pub enum RouteError<E> {
111 AppSpecific(E),
112 Request(RequestError),
113 UnsupportedContentType,
114 Binary(anyhow::Error),
115 Json(serde_json::Error),
116 Tide { status: StatusCode, message: String },
117 ExportMetrics(String),
118 IncorrectMethod { expected: String },
119}
120
121impl<E: Display> Display for RouteError<E> {
122 fn fmt(&self, f: &mut Formatter<'_>) -> fmt::Result {
123 match self {
124 Self::AppSpecific(err) => write!(f, "{}", err),
125 Self::Request(err) => write!(f, "{}", err),
126 Self::UnsupportedContentType => write!(f, "requested content type is not supported"),
127 Self::Binary(err) => write!(f, "error creating byte stream: {}", err),
128 Self::Json(err) => write!(f, "error creating JSON response: {}", err),
129 Self::Tide { status, message } => write!(f, "{status}: {message}"),
130 Self::ExportMetrics(msg) => write!(f, "error exporting metrics: {msg}"),
131 Self::IncorrectMethod { expected } => {
132 write!(f, "route may only be called as {}", expected)
133 }
134 }
135 }
136}
137
138impl<E> RouteError<E> {
139 pub fn status(&self) -> StatusCode {
140 match self {
141 Self::Request(_) | Self::UnsupportedContentType | Self::IncorrectMethod { .. } => {
142 StatusCode::BAD_REQUEST
143 }
144 _ => StatusCode::INTERNAL_SERVER_ERROR,
145 }
146 }
147
148 pub fn map_app_specific<E2>(self, f: impl Fn(E) -> E2) -> RouteError<E2> {
149 match self {
150 RouteError::AppSpecific(e) => RouteError::AppSpecific(f(e)),
151 RouteError::Request(e) => RouteError::Request(e),
152 RouteError::UnsupportedContentType => RouteError::UnsupportedContentType,
153 RouteError::Binary(err) => RouteError::Binary(err),
154 RouteError::Json(err) => RouteError::Json(err),
155 RouteError::Tide { status, message } => RouteError::Tide { status, message },
156 RouteError::ExportMetrics(msg) => RouteError::ExportMetrics(msg),
157 Self::IncorrectMethod { expected } => RouteError::IncorrectMethod { expected },
158 }
159 }
160}
161
162impl<E> From<RequestError> for RouteError<E> {
163 fn from(err: RequestError) -> Self {
164 Self::Request(err)
165 }
166}
167
168#[derive(Debug)]
174pub enum SocketError<E> {
175 AppSpecific(E),
176 Request(RequestError),
177 Binary(anyhow::Error),
178 Json(serde_json::Error),
179 WebSockets(String),
180 UnsupportedMessageType,
181 Closed,
182 IncorrectMethod { expected: String, actual: String },
183}
184
185impl<E> SocketError<E> {
186 pub fn status(&self) -> StatusCode {
187 match self {
188 Self::Request(_) | Self::UnsupportedMessageType | Self::IncorrectMethod { .. } => {
189 StatusCode::BAD_REQUEST
190 }
191 _ => StatusCode::INTERNAL_SERVER_ERROR,
192 }
193 }
194
195 pub fn map_app_specific<E2>(self, f: &impl Fn(E) -> E2) -> SocketError<E2> {
196 match self {
197 Self::AppSpecific(e) => SocketError::AppSpecific(f(e)),
198 Self::Request(e) => SocketError::Request(e),
199 Self::Binary(e) => SocketError::Binary(e),
200 Self::Json(e) => SocketError::Json(e),
201 Self::WebSockets(e) => SocketError::WebSockets(e),
202 Self::UnsupportedMessageType => SocketError::UnsupportedMessageType,
203 Self::Closed => SocketError::Closed,
204 Self::IncorrectMethod { expected, actual } => {
205 SocketError::IncorrectMethod { expected, actual }
206 }
207 }
208 }
209}
210
211impl<E: Display> Display for SocketError<E> {
212 fn fmt(&self, f: &mut Formatter) -> fmt::Result {
213 match self {
214 Self::AppSpecific(e) => write!(f, "{}", e),
215 Self::Request(e) => write!(f, "{}", e),
216 Self::Binary(e) => write!(f, "error creating byte stream: {}", e),
217 Self::Json(e) => write!(f, "error creating JSON message: {}", e),
218 Self::WebSockets(e) => write!(f, "WebSockets protocol error: {}", e),
219 Self::UnsupportedMessageType => {
220 write!(f, "unsupported content type for WebSockets message")
221 }
222 Self::Closed => write!(f, "connection closed"),
223 Self::IncorrectMethod { expected, actual } => write!(
224 f,
225 "endpoint must be called as {}, but was called as {}",
226 expected, actual
227 ),
228 }
229 }
230}
231
232impl<E> From<RequestError> for SocketError<E> {
233 fn from(err: RequestError) -> Self {
234 Self::Request(err)
235 }
236}
237
238impl<E> From<anyhow::Error> for SocketError<E> {
239 fn from(err: anyhow::Error) -> Self {
240 Self::Binary(err)
241 }
242}
243
244impl<E> From<serde_json::Error> for SocketError<E> {
245 fn from(err: serde_json::Error) -> Self {
246 Self::Json(err)
247 }
248}