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
|
use actix_web::{error::ResponseError, http::StatusCode, HttpResponse};
use deadpool_postgres::PoolError;
use serde::Serialize;
use std::fmt;
use tokio_postgres::error::Error;
#[derive(Debug, Eq, PartialEq)]
pub enum AppErrorType {
DbError,
NotFoundError,
AuthorizationError,
GitError,
}
#[derive(Debug)]
pub struct AppError {
pub message: Option<String>,
pub cause: Option<String>,
pub error_type: AppErrorType,
}
impl AppError {
pub fn message(&self) -> String {
match &*self {
AppError {
message: Some(message),
..
} => message.clone(),
AppError {
message: None,
error_type: AppErrorType::NotFoundError,
..
} => "The requested item was not found".to_string(),
_ => "An unexpected error has occurred".to_string(),
}
}
}
impl From<PoolError> for AppError {
fn from(error: PoolError) -> AppError {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: AppErrorType::DbError,
}
}
}
impl From<Error> for AppError {
fn from(error: Error) -> AppError {
AppError {
message: None,
cause: Some(error.to_string()),
error_type: AppErrorType::DbError,
}
}
}
impl fmt::Display for AppError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> Result<(), fmt::Error> {
write!(f, "{:?}", self)
}
}
#[derive(Serialize)]
pub struct AppErrorResponse {
pub detail: String,
}
impl ResponseError for AppError {
fn status_code(&self) -> StatusCode {
match self.error_type {
AppErrorType::DbError => StatusCode::INTERNAL_SERVER_ERROR,
AppErrorType::NotFoundError => StatusCode::NOT_FOUND,
AppErrorType::AuthorizationError => StatusCode::UNAUTHORIZED,
AppErrorType::GitError => StatusCode::BAD_REQUEST,
}
}
/// Returns a JSON response with "detail" as key
fn error_response(&self) -> HttpResponse {
HttpResponse::build(self.status_code()).json(AppErrorResponse {
detail: self.message(),
})
}
}
|