llm_cost_ops_api/api/
validation.rs

1// API request validation utilities
2
3use axum::{
4    async_trait,
5    extract::{FromRequest, Request},
6    Json,
7};
8use serde::de::DeserializeOwned;
9use validator::Validate;
10
11use super::error::{ApiError, ApiResult};
12
13/// Validated JSON extractor
14pub struct ValidatedJson<T>(pub T);
15
16#[async_trait]
17impl<T, S> FromRequest<S> for ValidatedJson<T>
18where
19    T: DeserializeOwned + Validate,
20    S: Send + Sync,
21{
22    type Rejection = ApiError;
23
24    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
25        let Json(value) = Json::<T>::from_request(req, state)
26            .await
27            .map_err(|_| ApiError::BadRequest("Invalid JSON".to_string()))?;
28
29        value.validate()?;
30
31        Ok(ValidatedJson(value))
32    }
33}
34
35/// Validate query parameters
36pub fn validate_query_params<T: Validate>(params: &T) -> ApiResult<()> {
37    params.validate().map_err(|e| e.into())
38}