fix rust
This commit is contained in:
142
src/error.rs
Normal file
142
src/error.rs
Normal file
@@ -0,0 +1,142 @@
|
||||
use axum::{
|
||||
http::StatusCode,
|
||||
response::{IntoResponse, Response},
|
||||
Json,
|
||||
};
|
||||
use serde_json::json;
|
||||
use thiserror::Error;
|
||||
|
||||
#[derive(Error, Debug)]
|
||||
pub enum AppError {
|
||||
#[error("Database error: {0}")]
|
||||
Database(#[from] sqlx::Error),
|
||||
|
||||
#[error("Migration error: {0}")]
|
||||
Migration(#[from] sqlx::migrate::MigrateError),
|
||||
|
||||
#[error("Validation error: {0}")]
|
||||
Validation(String),
|
||||
|
||||
#[error("Authentication error: {0}")]
|
||||
Authentication(String),
|
||||
|
||||
#[error("Authorization error: {0}")]
|
||||
Authorization(String),
|
||||
|
||||
#[error("Not found: {0}")]
|
||||
NotFound(String),
|
||||
|
||||
#[error("Conflict: {0}")]
|
||||
Conflict(String),
|
||||
|
||||
#[error("External service error: {0}")]
|
||||
ExternalService(String),
|
||||
|
||||
#[error("Configuration error: {0}")]
|
||||
Configuration(String),
|
||||
|
||||
#[error("JSON serialization error: {0}")]
|
||||
Json(#[from] serde_json::Error),
|
||||
|
||||
#[error("HTTP client error: {0}")]
|
||||
HttpClient(#[from] reqwest::Error),
|
||||
|
||||
#[error("JWT error: {0}")]
|
||||
Jwt(#[from] jsonwebtoken::errors::Error),
|
||||
|
||||
#[error("Internal server error: {0}")]
|
||||
Internal(String),
|
||||
}
|
||||
|
||||
impl IntoResponse for AppError {
|
||||
fn into_response(self) -> Response {
|
||||
let (status, error_message, error_code) = match &self {
|
||||
AppError::Database(e) => {
|
||||
tracing::error!("Database error: {}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Database error", "DATABASE_ERROR")
|
||||
}
|
||||
AppError::Migration(e) => {
|
||||
tracing::error!("Migration error: {}", e);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Migration error", "MIGRATION_ERROR")
|
||||
}
|
||||
AppError::Validation(msg) => {
|
||||
(StatusCode::BAD_REQUEST, msg.as_str(), "VALIDATION_ERROR")
|
||||
}
|
||||
AppError::Authentication(msg) => {
|
||||
(StatusCode::UNAUTHORIZED, msg.as_str(), "AUTHENTICATION_ERROR")
|
||||
}
|
||||
AppError::Authorization(msg) => {
|
||||
(StatusCode::FORBIDDEN, msg.as_str(), "AUTHORIZATION_ERROR")
|
||||
}
|
||||
AppError::NotFound(msg) => {
|
||||
(StatusCode::NOT_FOUND, msg.as_str(), "NOT_FOUND")
|
||||
}
|
||||
AppError::Conflict(msg) => {
|
||||
(StatusCode::CONFLICT, msg.as_str(), "CONFLICT")
|
||||
}
|
||||
AppError::ExternalService(msg) => {
|
||||
tracing::error!("External service error: {}", msg);
|
||||
(StatusCode::BAD_GATEWAY, "External service unavailable", "EXTERNAL_SERVICE_ERROR")
|
||||
}
|
||||
AppError::Configuration(msg) => {
|
||||
tracing::error!("Configuration error: {}", msg);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Configuration error", "CONFIGURATION_ERROR")
|
||||
}
|
||||
AppError::Json(e) => {
|
||||
tracing::error!("JSON error: {}", e);
|
||||
(StatusCode::BAD_REQUEST, "Invalid JSON", "JSON_ERROR")
|
||||
}
|
||||
AppError::HttpClient(e) => {
|
||||
tracing::error!("HTTP client error: {}", e);
|
||||
(StatusCode::BAD_GATEWAY, "External service error", "HTTP_CLIENT_ERROR")
|
||||
}
|
||||
AppError::Jwt(e) => {
|
||||
tracing::error!("JWT error: {}", e);
|
||||
(StatusCode::UNAUTHORIZED, "Invalid token", "JWT_ERROR")
|
||||
}
|
||||
AppError::Internal(msg) => {
|
||||
tracing::error!("Internal error: {}", msg);
|
||||
(StatusCode::INTERNAL_SERVER_ERROR, "Internal server error", "INTERNAL_ERROR")
|
||||
}
|
||||
};
|
||||
|
||||
let body = Json(json!({
|
||||
"error": {
|
||||
"code": error_code,
|
||||
"message": error_message,
|
||||
"timestamp": chrono::Utc::now().to_rfc3339()
|
||||
}
|
||||
}));
|
||||
|
||||
(status, body).into_response()
|
||||
}
|
||||
}
|
||||
|
||||
// Convenience methods for common errors
|
||||
impl AppError {
|
||||
pub fn validation<T: Into<String>>(msg: T) -> Self {
|
||||
Self::Validation(msg.into())
|
||||
}
|
||||
|
||||
pub fn authentication<T: Into<String>>(msg: T) -> Self {
|
||||
Self::Authentication(msg.into())
|
||||
}
|
||||
|
||||
pub fn authorization<T: Into<String>>(msg: T) -> Self {
|
||||
Self::Authorization(msg.into())
|
||||
}
|
||||
|
||||
pub fn not_found<T: Into<String>>(msg: T) -> Self {
|
||||
Self::NotFound(msg.into())
|
||||
}
|
||||
|
||||
pub fn conflict<T: Into<String>>(msg: T) -> Self {
|
||||
Self::Conflict(msg.into())
|
||||
}
|
||||
|
||||
pub fn internal<T: Into<String>>(msg: T) -> Self {
|
||||
Self::Internal(msg.into())
|
||||
}
|
||||
}
|
||||
|
||||
pub type AppResult<T> = Result<T, AppError>;
|
Reference in New Issue
Block a user