Files
simple-instant-stream/crates/server/src/http_error.rs
T

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()
}
}