-
Notifications
You must be signed in to change notification settings - Fork 1
/
error.rs
90 lines (83 loc) · 2.98 KB
/
error.rs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
use serde::Serialize;
use std::error::Error as StdError;
use thiserror::Error;
use warp::http::StatusCode;
use warp::{Rejection, Reply};
#[derive(Serialize)]
struct ErrorMessage {
code: u16,
msg: String,
}
pub async fn recover(err: Rejection) -> Result<impl Reply, Rejection> {
//api errors should be returned in json
if let Some(ref err) = err.find::<Error>() {
let error = match err {
Error::InvalidDateFormat(_, _)
| Error::PastDate(_)
| Error::InvalidSymbol
| Error::MissingDateBoundaries
| Error::InvalidDateRange
| Error::InvalidBase(_) => {
log::trace!("api reject, {}", err);
ErrorMessage {
code: StatusCode::BAD_REQUEST.as_u16(),
msg: err.to_string(),
}
}
Error::DateNotFound(_) => {
log::trace!("api reject, {}", err);
ErrorMessage {
code: StatusCode::NOT_FOUND.as_u16(),
msg: "Not Found".into(),
}
}
_ => {
log::error!("unhandled error! {}", err);
ErrorMessage {
code: StatusCode::INTERNAL_SERVER_ERROR.as_u16(),
msg: "Internal Server Error".into(),
}
}
};
return Ok(warp::reply::with_status(
warp::reply::json(&error),
StatusCode::from_u16(error.code).unwrap(),
));
};
Err(err)
}
#[derive(Error, Debug)]
pub enum Error {
#[error("no curencies found for date `{0}`")]
DateNotFound(String),
#[error("could not parse `{0}` as NaiveDate")]
DateParseError(String, #[source] chrono::ParseError),
#[error("`{0}` is invalid, there are no currency rates for dates older then 1999-01-04.")]
PastDate(&'static str),
#[error("`{0}` is an invalid port")]
InvalidPort(String, #[source] std::num::ParseIntError),
#[error("start_at must be older than end_at")]
InvalidDateRange,
#[error("`{0}`: `{1}` is in an invalid date format, date must be in the format %Y-%m-%d")]
InvalidDateFormat(&'static str, String),
#[error("`{0}` is an invalid base currency")]
InvalidBase(String),
#[error("empty currency dataset, should have at least 1 element")]
EmpyDataset,
#[error("symbol list contains invalid symbols")]
InvalidSymbol,
#[error("both start_at and end_at parameters must be present")]
MissingDateBoundaries,
#[error("database error, `{0}`")]
DatabaseError(String, #[source] Option<Box<dyn StdError + Sync + Send>>),
#[error("error fetching currencies from ECB, `{0}`")]
FetcherError(String),
#[error("error rendering template, `{0}`")]
TemplateError(#[source] askama::Error),
}
impl warp::reject::Reject for Error {}
impl From<Error> for warp::reject::Rejection {
fn from(error: Error) -> warp::reject::Rejection {
warp::reject::custom(error)
}
}