-
Notifications
You must be signed in to change notification settings - Fork 57
/
Copy patherrors.rs
executable file
·116 lines (106 loc) · 3.33 KB
/
errors.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
use actix_web::{
error::{BlockingError, ResponseError},
http::StatusCode,
HttpResponse, Error,
};
use derive_more::Display;
use diesel::{
r2d2::PoolError,
result::{DatabaseErrorKind, Error as DBError},
};
use uuid::Error as ParseError;
#[derive(Debug, Display, PartialEq)]
#[allow(dead_code)]
pub enum ApiError {
BadRequest(String),
BlockingError(String),
CacheError(String),
CannotDecodeJwtToken(String),
CannotEncodeJwtToken(String),
InternalServerError(String),
NotFound(String),
ParseError(String),
PoolError(String),
#[display(fmt = "")]
ValidationError(Vec<String>),
Unauthorized(String),
}
/// User-friendly error messages
#[derive(Debug, Deserialize, Serialize)]
pub struct ErrorResponse {
errors: Vec<String>,
}
/// Automatically convert ApiErrors to external Response Errors
impl ResponseError for ApiError {
fn error_response(&self) -> HttpResponse {
match self {
ApiError::BadRequest(error) => {
HttpResponse::BadRequest().json(error)
}
ApiError::NotFound(message) => {
HttpResponse::NotFound().json(message)
}
ApiError::ValidationError(errors) => {
HttpResponse::UnprocessableEntity().json(errors.to_vec())
}
ApiError::Unauthorized(error) => {
HttpResponse::Unauthorized().json(error)
}
_ => HttpResponse::new(StatusCode::INTERNAL_SERVER_ERROR),
}
}
}
/// Utility to make transforming a string reference into an ErrorResponse
impl From<&String> for ErrorResponse {
fn from(error: &String) -> Self {
ErrorResponse {
errors: vec![error.into()],
}
}
}
/// Utility to make transforming a vector of strings into an ErrorResponse
impl From<Vec<String>> for ErrorResponse {
fn from(errors: Vec<String>) -> Self {
ErrorResponse { errors }
}
}
/// Convert DBErrors to ApiErrors
impl From<DBError> for ApiError {
fn from(error: DBError) -> ApiError {
// Right now we just care about UniqueViolation from diesel
// But this would be helpful to easily map errors as our app grows
match error {
DBError::DatabaseError(kind, info) => {
if let DatabaseErrorKind::UniqueViolation = kind {
let message = info.details().unwrap_or_else(|| info.message()).to_string();
return ApiError::BadRequest(message);
}
ApiError::InternalServerError("Unknown database error".into())
}
_ => ApiError::InternalServerError("Unknown database error".into()),
}
}
}
/// Convert PoolErrors to ApiErrors
impl From<PoolError> for ApiError {
fn from(error: PoolError) -> ApiError {
ApiError::PoolError(error.to_string())
}
}
/// Convert ParseErrors to ApiErrors
impl From<ParseError> for ApiError {
fn from(error: ParseError) -> ApiError {
ApiError::ParseError(error.to_string())
}
}
// / Convert Thread BlockingErrors to ApiErrors
impl From<BlockingError> for ApiError {
fn from(error: BlockingError) -> ApiError {
ApiError::InternalServerError(error.to_string())
}
}
impl From<Error> for ApiError{
fn from(value: Error) -> Self {
ApiError::InternalServerError(value.to_string())
}
}