Files
Easytier_lkddi/easytier-contrib/easytier-uptime/src/api/error.rs

81 lines
2.3 KiB
Rust

use axum::http::StatusCode;
use axum::response::{IntoResponse, Response};
use serde_json::json;
use thiserror::Error;
#[derive(Debug, Error)]
pub enum ApiError {
#[error("Database error: {0}")]
Database(#[from] sea_orm::DbErr),
#[error("Validation error: {0}")]
Validation(String),
#[error("Not found: {0}")]
NotFound(String),
#[error("Bad request: {0}")]
BadRequest(String),
#[error("Internal server error: {0}")]
Internal(String),
#[error("Unauthorized: {0}")]
Unauthorized(String),
#[error("Forbidden: {0}")]
Forbidden(String),
}
impl IntoResponse for ApiError {
fn into_response(self) -> Response {
let (status, error_message) = match self {
ApiError::Database(err) => (
StatusCode::INTERNAL_SERVER_ERROR,
format!("Database error: {}", err),
),
ApiError::Validation(msg) => (StatusCode::BAD_REQUEST, msg),
ApiError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
ApiError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
ApiError::Internal(msg) => (StatusCode::INTERNAL_SERVER_ERROR, msg),
ApiError::Unauthorized(msg) => (StatusCode::UNAUTHORIZED, msg),
ApiError::Forbidden(msg) => (StatusCode::FORBIDDEN, msg),
};
let body = json!({
"error": {
"code": status.as_u16(),
"message": error_message
}
});
(status, axum::Json(body)).into_response()
}
}
pub type ApiResult<T> = Result<T, ApiError>;
impl From<validator::ValidationErrors> for ApiError {
fn from(err: validator::ValidationErrors) -> Self {
let errors: Vec<String> = err
.field_errors()
.iter()
.map(|(field, errors)| {
let error_msgs: Vec<String> = errors
.iter()
.map(|error| {
if let Some(msg) = &error.message {
msg.to_string()
} else {
format!("Validation failed for field: {}", field)
}
})
.collect();
error_msgs.join(", ")
})
.collect();
ApiError::Validation(errors.join("; "))
}
}