use axum::http::StatusCode; use axum::response::{IntoResponse, Response}; use validator::ValidationErrors; use crate::models::ValidationErrorResponse; #[derive(Debug)] pub enum ValidationRejection { Validator(V), // Validation errors Extractor(E), // Extraction errors, e.g. axum's JsonRejection } impl std::fmt::Display for ValidationRejection { fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { match self { ValidationRejection::Validator(v) => write!(f, "{v}"), ValidationRejection::Extractor(e) => write!(f, "{e}"), } } } impl std::error::Error for ValidationRejection { fn source(&self) -> Option<&(dyn std::error::Error + 'static)> { match self { ValidationRejection::Validator(v) => Some(v), ValidationRejection::Extractor(e) => Some(e), } } } impl IntoResponse for ValidationRejection { fn into_response(self) -> Response { match self { ValidationRejection::Validator(v) => { tracing::error!("Validation error: {v}"); ( StatusCode::UNPROCESSABLE_ENTITY, axum::Json(ValidationErrorResponse::from(v)), ) .into_response() } // logged by ApiError ValidationRejection::Extractor(e) => e.into_response(), } } } pub type ValidRejection = ValidationRejection; impl From for ValidRejection { fn from(v: ValidationErrors) -> Self { Self::Validator(v) } }