2026-04-11 15:04:14 +02:00
|
|
|
use axum::{
|
|
|
|
|
http::StatusCode,
|
|
|
|
|
response::{IntoResponse, Response},
|
|
|
|
|
Json,
|
|
|
|
|
};
|
|
|
|
|
use serde::Serialize;
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, thiserror::Error)]
|
|
|
|
|
pub enum AppError {
|
|
|
|
|
#[error("bad request: {0}")]
|
|
|
|
|
BadRequest(String),
|
|
|
|
|
#[error("provider unavailable: {0}")]
|
|
|
|
|
ProviderUnavailable(String),
|
|
|
|
|
#[error("internal error: {0}")]
|
|
|
|
|
Internal(String),
|
2026-04-15 18:18:39 +02:00
|
|
|
#[error("external service error: {0}")]
|
|
|
|
|
ExternalService(String),
|
2026-04-11 15:04:14 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
|
|
#[derive(Debug, Serialize)]
|
|
|
|
|
struct ErrorBody {
|
|
|
|
|
error: String,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl IntoResponse for AppError {
|
|
|
|
|
fn into_response(self) -> Response {
|
|
|
|
|
let status = match self {
|
|
|
|
|
AppError::BadRequest(_) => StatusCode::BAD_REQUEST,
|
|
|
|
|
AppError::ProviderUnavailable(_) => StatusCode::SERVICE_UNAVAILABLE,
|
|
|
|
|
AppError::Internal(_) => StatusCode::INTERNAL_SERVER_ERROR,
|
2026-04-15 18:18:39 +02:00
|
|
|
AppError::ExternalService(_) => StatusCode::BAD_GATEWAY,
|
2026-04-11 15:04:14 +02:00
|
|
|
};
|
|
|
|
|
|
|
|
|
|
let body = Json(ErrorBody {
|
|
|
|
|
error: self.to_string(),
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
(status, body).into_response()
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
impl From<sqlx::Error> for AppError {
|
|
|
|
|
fn from(value: sqlx::Error) -> Self {
|
|
|
|
|
AppError::Internal(value.to_string())
|
|
|
|
|
}
|
|
|
|
|
}
|