Skip to main content

homecore_api/
error.rs

1use axum::http::StatusCode;
2use axum::response::{IntoResponse, Response};
3use axum::Json;
4use serde::Serialize;
5use thiserror::Error;
6
7#[derive(Error, Debug)]
8pub enum ApiError {
9    #[error("entity not found: {0}")]
10    NotFound(String),
11    #[error("bad request: {0}")]
12    BadRequest(String),
13    #[error("unauthorized")]
14    Unauthorized,
15    #[error("service not registered: {domain}.{service}")]
16    ServiceNotRegistered { domain: String, service: String },
17    #[error("service unavailable: {0}")]
18    Unavailable(String),
19    #[error("internal error: {0}")]
20    Internal(String),
21}
22
23pub type ApiResult<T> = Result<T, ApiError>;
24
25#[derive(Serialize)]
26struct ErrorPayload {
27    message: String,
28}
29
30impl IntoResponse for ApiError {
31    fn into_response(self) -> Response {
32        let (status, message) = match &self {
33            Self::NotFound(_) => (StatusCode::NOT_FOUND, self.to_string()),
34            Self::BadRequest(_) => (StatusCode::BAD_REQUEST, self.to_string()),
35            Self::Unauthorized => (StatusCode::UNAUTHORIZED, self.to_string()),
36            Self::ServiceNotRegistered { .. } => (StatusCode::BAD_REQUEST, self.to_string()),
37            Self::Unavailable(_) => (StatusCode::SERVICE_UNAVAILABLE, self.to_string()),
38            Self::Internal(_) => (StatusCode::INTERNAL_SERVER_ERROR, self.to_string()),
39        };
40        (status, Json(ErrorPayload { message })).into_response()
41    }
42}