axum_extra.rs
1 use axum::extract::path::ErrorKind; 2 use axum::extract::rejection::{PathRejection, QueryRejection}; 3 use axum::extract::FromRequestParts; 4 use axum::http::request::Parts; 5 use axum::http::StatusCode; 6 use axum::{async_trait, Json}; 7 8 use serde::de::DeserializeOwned; 9 use serde::Serialize; 10 11 pub struct Path<T>(pub T); 12 13 #[async_trait] 14 impl<S, T> FromRequestParts<S> for Path<T> 15 where 16 T: DeserializeOwned + Send, 17 S: Send + Sync, 18 { 19 type Rejection = (StatusCode, axum::Json<Error>); 20 21 async fn from_request_parts(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { 22 match axum::extract::Path::<T>::from_request_parts(req, state).await { 23 Ok(value) => Ok(Self(value.0)), 24 Err(rejection) => { 25 let status = StatusCode::BAD_REQUEST; 26 let body = match rejection { 27 PathRejection::FailedToDeserializePathParams(inner) => { 28 let kind = inner.into_kind(); 29 match &kind { 30 ErrorKind::Message(msg) => Json(Error { 31 success: false, 32 error: msg.to_string(), 33 }), 34 _ => Json(Error { 35 success: false, 36 error: kind.to_string(), 37 }), 38 } 39 } 40 _ => Json(Error { 41 success: false, 42 error: format!("{rejection}"), 43 }), 44 }; 45 46 Err((status, body)) 47 } 48 } 49 } 50 } 51 52 #[derive(Default)] 53 pub struct Query<T>(pub T); 54 55 #[async_trait] 56 impl<S, T> FromRequestParts<S> for Query<T> 57 where 58 T: DeserializeOwned + Send, 59 S: Send + Sync, 60 { 61 type Rejection = (StatusCode, axum::Json<Error>); 62 63 async fn from_request_parts(req: &mut Parts, state: &S) -> Result<Self, Self::Rejection> { 64 match axum::extract::Query::<T>::from_request_parts(req, state).await { 65 Ok(value) => Ok(Self(value.0)), 66 Err(rejection) => { 67 let status = StatusCode::BAD_REQUEST; 68 let body = match rejection { 69 QueryRejection::FailedToDeserializeQueryString(inner) => Json(Error { 70 success: false, 71 error: inner.to_string(), 72 }), 73 _ => Json(Error { 74 success: false, 75 error: format!("{rejection}"), 76 }), 77 }; 78 79 Err((status, body)) 80 } 81 } 82 } 83 } 84 85 #[derive(Serialize)] 86 pub struct Error { 87 success: bool, 88 error: String, 89 }