69 lines
1.9 KiB
Rust
69 lines
1.9 KiB
Rust
use std::fmt;
|
|
|
|
use axum::{http::StatusCode, response::IntoResponse};
|
|
|
|
use crate::{db, ErrorExt};
|
|
|
|
pub type AppResult<T> = Result<T, AppError>;
|
|
|
|
#[derive(Debug)]
|
|
pub enum AppError {
|
|
Db(db::DbError),
|
|
IO(std::io::Error),
|
|
Other(Box<dyn std::error::Error + 'static + Send + Sync>),
|
|
BadRequest,
|
|
Unauthorized,
|
|
NotFound,
|
|
}
|
|
|
|
impl fmt::Display for AppError {
|
|
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
|
|
match self {
|
|
Self::Db(_) => write!(f, "database error"),
|
|
Self::IO(_) => write!(f, "io error"),
|
|
Self::Other(_) => write!(f, "other error"),
|
|
Self::BadRequest => write!(f, "bad request"),
|
|
Self::Unauthorized => write!(f, "unauthorized"),
|
|
Self::NotFound => write!(f, "not found"),
|
|
}
|
|
}
|
|
}
|
|
|
|
impl std::error::Error for AppError {
|
|
fn source(&self) -> Option<&(dyn std::error::Error + 'static)> {
|
|
match self {
|
|
Self::Db(err) => Some(err),
|
|
Self::IO(err) => Some(err),
|
|
Self::Other(err) => Some(err.as_ref()),
|
|
Self::NotFound | Self::Unauthorized | Self::BadRequest => None,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl From<db::DbError> for AppError {
|
|
fn from(value: db::DbError) -> Self {
|
|
Self::Db(value)
|
|
}
|
|
}
|
|
|
|
impl From<std::io::Error> for AppError {
|
|
fn from(value: std::io::Error) -> Self {
|
|
Self::IO(value)
|
|
}
|
|
}
|
|
|
|
impl IntoResponse for AppError {
|
|
fn into_response(self) -> axum::response::Response {
|
|
match self {
|
|
Self::NotFound => StatusCode::NOT_FOUND.into_response(),
|
|
Self::Unauthorized => StatusCode::UNAUTHORIZED.into_response(),
|
|
Self::BadRequest => StatusCode::BAD_REQUEST.into_response(),
|
|
_ => {
|
|
tracing::error!("{}", self.stack());
|
|
|
|
StatusCode::INTERNAL_SERVER_ERROR.into_response()
|
|
}
|
|
}
|
|
}
|
|
}
|