60 lines
1.7 KiB
Rust
60 lines
1.7 KiB
Rust
use axum::{
|
|
body::Body,
|
|
http::{Response, StatusCode},
|
|
response::IntoResponse,
|
|
};
|
|
use thiserror::Error;
|
|
|
|
#[derive(Error, Debug)]
|
|
pub enum HttpError {
|
|
#[error("db shit itself: {0}")]
|
|
DbErr(#[from] sea_orm::DbErr),
|
|
#[error("hashing failed")]
|
|
Hash,
|
|
#[error("resource not found")]
|
|
NotFound,
|
|
#[error("unauthorized")]
|
|
Unauthorized,
|
|
#[error("forbidden")]
|
|
Forbidden,
|
|
#[error("conflict")]
|
|
Conflict,
|
|
#[error("bad request: {0}")]
|
|
BadRequest(String),
|
|
#[error("unprocessable entity: {0}")]
|
|
Unprocessable(String),
|
|
#[error("not acceptable: {0}")]
|
|
NotAcceptable(String),
|
|
#[error("internal error")]
|
|
Internal,
|
|
}
|
|
|
|
impl HttpError {
|
|
fn status(&self) -> StatusCode {
|
|
match self {
|
|
Self::DbErr(_) | Self::Hash | Self::Internal => StatusCode::INTERNAL_SERVER_ERROR,
|
|
Self::NotFound => StatusCode::NOT_FOUND,
|
|
Self::Unauthorized => StatusCode::UNAUTHORIZED,
|
|
Self::Forbidden => StatusCode::FORBIDDEN,
|
|
Self::Conflict => StatusCode::CONFLICT,
|
|
Self::BadRequest(_) => StatusCode::BAD_REQUEST,
|
|
Self::Unprocessable(_) => StatusCode::UNPROCESSABLE_ENTITY,
|
|
Self::NotAcceptable(_) => StatusCode::NOT_ACCEPTABLE,
|
|
}
|
|
}
|
|
}
|
|
|
|
impl IntoResponse for HttpError {
|
|
fn into_response(self) -> Response<Body> {
|
|
let status = self.status();
|
|
// Only surface a message body for client (4xx) errors; keep an empty
|
|
// body for 5xx so internal details aren't leaked.
|
|
let body = if status.is_client_error() {
|
|
self.to_string()
|
|
} else {
|
|
String::new()
|
|
};
|
|
(status, body).into_response()
|
|
}
|
|
}
|