use super::error::ApiError;
use axum::extract::{FromRequest, FromRequestParts, Request};
use axum::http::request::Parts;
use serde::de::DeserializeOwned;
pub struct ApiQuery<T>(pub T);
impl<S, T> FromRequestParts<S> for ApiQuery<T>
where
T: DeserializeOwned + Send,
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
match axum::extract::Query::<T>::from_request_parts(parts, state).await {
Ok(axum::extract::Query(v)) => Ok(ApiQuery(v)),
Err(e) => Err(ApiError::bad_request(format!(
"query string: {}",
e.body_text()
))),
}
}
}
pub struct ApiPath<T>(pub T);
impl<S, T> FromRequestParts<S> for ApiPath<T>
where
T: DeserializeOwned + Send,
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request_parts(parts: &mut Parts, state: &S) -> Result<Self, Self::Rejection> {
match axum::extract::Path::<T>::from_request_parts(parts, state).await {
Ok(axum::extract::Path(v)) => Ok(ApiPath(v)),
Err(e) => Err(ApiError::bad_request(format!("path: {}", e.body_text()))),
}
}
}
pub struct ApiJson<T>(pub T);
impl<S, T> FromRequest<S> for ApiJson<T>
where
T: DeserializeOwned,
S: Send + Sync,
{
type Rejection = ApiError;
async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
match axum::Json::<T>::from_request(req, state).await {
Ok(axum::Json(v)) => Ok(ApiJson(v)),
Err(e) => Err(ApiError::bad_request(format!(
"request body: {}",
e.body_text()
))),
}
}
}