axum-with-seaorm/src/common/err.rs

102 lines
2.5 KiB
Rust

use crate::common::response::AppResponse;
#[derive(Debug)]
pub enum AppErrorType {
System,
Config,
Database,
Notfound,
Validate,
Template,
Authorization,
Forbidden,
}
type Cause = Box<dyn std::error::Error>;
#[derive(Debug)]
pub enum AppErrorItem {
Message(String),
Cause(Cause),
}
#[derive(Debug)]
pub struct AppError {
pub types: AppErrorType,
pub error: AppErrorItem,
}
impl AppError {
pub fn new(types: AppErrorType, error: AppErrorItem) -> Self {
Self { types, error }
}
pub fn from_err(cause: Cause, types: AppErrorType) -> Self {
Self::new(types, AppErrorItem::Cause(cause))
}
pub fn from_msg(msg: &str, types: AppErrorType) -> Self {
Self::new(types, AppErrorItem::Message(msg.to_string()))
}
pub fn notfound() -> Self {
Self::from_msg("不存在的记录", AppErrorType::Notfound)
}
}
impl std::fmt::Display for AppError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
let msg = match &self.error {
AppErrorItem::Cause(err) => err.to_string(),
AppErrorItem::Message(msg) => msg.to_string(),
};
write!(f, "{}", msg)
}
}
impl std::error::Error for AppError {}
impl From<config::ConfigError> for AppError {
fn from(err: config::ConfigError) -> Self {
Self::from_err(Box::new(err), AppErrorType::Config)
}
}
impl From<askama::Error> for AppError {
fn from(err: askama::Error) -> Self {
Self::from_err(Box::new(err), AppErrorType::Template)
}
}
impl From<sea_orm::DbErr> for AppError {
fn from(err: sea_orm::DbErr) -> Self {
Self::from_err(Box::new(err), AppErrorType::Database)
}
}
impl From<jsonwebtoken::errors::Error> for AppError {
fn from(err: jsonwebtoken::errors::Error) -> Self {
Self::from_err(Box::new(err), AppErrorType::Authorization)
}
}
impl From<validator::ValidationErrors> for AppError {
fn from(err: validator::ValidationErrors) -> Self {
Self::from_err(Box::new(err), AppErrorType::Validate)
}
}
impl axum::response::IntoResponse for AppError {
fn into_response(self) -> axum::response::Response {
AppResponse::<()>::from_error(self).into_response()
}
}
/// 记录错误
pub fn log_error(handler_name: &str) -> Box<dyn Fn(AppError) -> AppError> {
let handler_name = handler_name.to_string();
Box::new(move |err| {
tracing::error!("{}: {:?}", handler_name, err);
err
})
}