fastskill_core/http/
errors.rs1use axum::{
4 http::StatusCode,
5 response::{IntoResponse, Response},
6 Json,
7};
8use serde_json::json;
9use std::collections::HashMap;
10
11#[derive(Debug, Clone)]
13pub enum HttpError {
14 Unauthorized(String),
16 Forbidden(String),
17
18 BadRequest(String),
20 ValidationError(HashMap<String, Vec<String>>),
21
22 NotFound(String),
24
25 Conflict(String),
27
28 InternalServerError(String),
30
31 ServiceError(String),
33
34 ServiceUnavailable(String),
36}
37
38impl HttpError {
39 pub fn status_code(&self) -> StatusCode {
41 match self {
42 HttpError::Unauthorized(_) => StatusCode::UNAUTHORIZED,
43 HttpError::Forbidden(_) => StatusCode::FORBIDDEN,
44 HttpError::BadRequest(_) | HttpError::ValidationError(_) => StatusCode::BAD_REQUEST,
45 HttpError::NotFound(_) => StatusCode::NOT_FOUND,
46 HttpError::Conflict(_) => StatusCode::CONFLICT,
47 HttpError::InternalServerError(_) | HttpError::ServiceError(_) => {
48 StatusCode::INTERNAL_SERVER_ERROR
49 }
50 HttpError::ServiceUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
51 }
52 }
53
54 pub fn error_code(&self) -> &'static str {
56 match self {
57 HttpError::Unauthorized(_) => "UNAUTHORIZED",
58 HttpError::Forbidden(_) => "FORBIDDEN",
59 HttpError::BadRequest(_) => "BAD_REQUEST",
60 HttpError::ValidationError(_) => "VALIDATION_ERROR",
61 HttpError::NotFound(_) => "NOT_FOUND",
62 HttpError::Conflict(_) => "CONFLICT",
63 HttpError::InternalServerError(_) => "INTERNAL_SERVER_ERROR",
64 HttpError::ServiceError(_) => "SERVICE_ERROR",
65 HttpError::ServiceUnavailable(_) => "SERVICE_UNAVAILABLE",
66 }
67 }
68}
69
70impl std::fmt::Display for HttpError {
71 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
72 match self {
73 HttpError::Unauthorized(msg) => write!(f, "Unauthorized: {}", msg),
74 HttpError::Forbidden(msg) => write!(f, "Forbidden: {}", msg),
75 HttpError::BadRequest(msg) => write!(f, "Bad Request: {}", msg),
76 HttpError::ValidationError(errors) => {
77 write!(f, "Validation Error: {:?}", errors)
78 }
79 HttpError::NotFound(msg) => write!(f, "Not Found: {}", msg),
80 HttpError::Conflict(msg) => write!(f, "Conflict: {}", msg),
81 HttpError::InternalServerError(msg) => write!(f, "Internal Server Error: {}", msg),
82 HttpError::ServiceError(msg) => write!(f, "Service Error: {}", msg),
83 HttpError::ServiceUnavailable(msg) => write!(f, "Service Unavailable: {}", msg),
84 }
85 }
86}
87
88impl std::error::Error for HttpError {}
89
90impl IntoResponse for HttpError {
91 fn into_response(self) -> Response {
92 let status = self.status_code();
93 let error_code = self.error_code();
94
95 let (message, details) = match self {
96 HttpError::ValidationError(errors) => {
97 ("Validation failed".to_string(), Some(json!(errors)))
98 }
99 HttpError::Unauthorized(msg)
100 | HttpError::Forbidden(msg)
101 | HttpError::BadRequest(msg)
102 | HttpError::NotFound(msg)
103 | HttpError::Conflict(msg)
104 | HttpError::InternalServerError(msg)
105 | HttpError::ServiceError(msg)
106 | HttpError::ServiceUnavailable(msg) => (msg, None),
107 };
108
109 let body = Json(json!({
110 "success": false,
111 "error": {
112 "code": error_code,
113 "message": message,
114 "details": details
115 }
116 }));
117
118 (status, body).into_response()
119 }
120}
121
122impl From<crate::core::service::ServiceError> for HttpError {
124 fn from(err: crate::core::service::ServiceError) -> Self {
125 match err {
126 crate::core::service::ServiceError::SkillNotFound(msg) => HttpError::NotFound(msg),
127 crate::core::service::ServiceError::Validation(msg) => HttpError::BadRequest(msg),
128 crate::core::service::ServiceError::Config(msg) => HttpError::InternalServerError(msg),
129 crate::core::service::ServiceError::Io(err) => {
130 HttpError::InternalServerError(err.to_string())
131 }
132 crate::core::service::ServiceError::Custom(msg) => HttpError::ServiceError(msg),
133 crate::core::service::ServiceError::Storage(msg) => HttpError::InternalServerError(msg),
134 crate::core::service::ServiceError::Execution(_) => {
135 HttpError::InternalServerError("Execution error".to_string())
136 }
137 crate::core::service::ServiceError::Event(msg) => HttpError::InternalServerError(msg),
138 crate::core::service::ServiceError::InvalidOperation(msg) => HttpError::BadRequest(msg),
139 }
140 }
141}
142
143pub type HttpResult<T> = Result<T, HttpError>;