56 lines
1.6 KiB
Rust
56 lines
1.6 KiB
Rust
use axum::{
|
|
Json,
|
|
http::StatusCode,
|
|
response::{IntoResponse, Response},
|
|
};
|
|
use tracing::error;
|
|
|
|
use crate::models::ErrorResponse;
|
|
|
|
#[derive(Debug)]
|
|
pub enum AppError {
|
|
Unauthorized,
|
|
NotFound(String),
|
|
BadRequest(String),
|
|
TooManyRequests(String),
|
|
/// (public_message, internal_details) — details are logged but not returned.
|
|
Internal(String, Option<String>),
|
|
}
|
|
|
|
impl IntoResponse for AppError {
|
|
fn into_response(self) -> Response {
|
|
let (status, error_message) = match self {
|
|
AppError::Unauthorized => (StatusCode::UNAUTHORIZED, "Unauthorized".to_string()),
|
|
AppError::NotFound(msg) => (StatusCode::NOT_FOUND, msg),
|
|
AppError::BadRequest(msg) => (StatusCode::BAD_REQUEST, msg),
|
|
AppError::TooManyRequests(msg) => (StatusCode::TOO_MANY_REQUESTS, msg),
|
|
AppError::Internal(msg, details) => {
|
|
if let Some(d) = details {
|
|
error!("Internal error: {} — {}", msg, d);
|
|
} else {
|
|
error!("Internal error: {}", msg);
|
|
}
|
|
(
|
|
StatusCode::INTERNAL_SERVER_ERROR,
|
|
"Internal error".to_string(),
|
|
)
|
|
}
|
|
};
|
|
|
|
let body = Json(ErrorResponse {
|
|
error: error_message,
|
|
});
|
|
|
|
(status, body).into_response()
|
|
}
|
|
}
|
|
|
|
impl<E> From<E> for AppError
|
|
where
|
|
E: std::error::Error + Send + Sync + 'static,
|
|
{
|
|
fn from(err: E) -> Self {
|
|
AppError::Internal("Internal Server Error".to_string(), Some(err.to_string()))
|
|
}
|
|
}
|