ts-webapi 0.4.11

Library for my web API projects
Documentation
//! Custom JSON extractor for returning standard  errors.

use axum::{
    extract::{FromRequest, OptionalFromRequest, Request, rejection::JsonRejection},
    response::IntoResponse,
};
use http::StatusCode;
use serde::{Serialize, de::DeserializeOwned};

/// Custom JSON extractor for returning standard errors.
pub struct Json<T>(pub T);

impl<T: Serialize> IntoResponse for Json<T> {
    fn into_response(self) -> axum::response::Response {
        let Self(value) = self;
        axum::Json(value).into_response()
    }
}

impl<T, S> FromRequest<S> for Json<T>
where
    T: DeserializeOwned,
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request(req: Request, state: &S) -> Result<Self, Self::Rejection> {
        <axum::Json<_> as FromRequest<S>>::from_request(req, state)
            .await
            .map_err(to_unprocessable_entity)
            .map(|value| Self(value.0))
    }
}

impl<T, S> OptionalFromRequest<S> for Json<T>
where
    T: DeserializeOwned,
    S: Send + Sync,
{
    type Rejection = StatusCode;

    async fn from_request(req: Request, state: &S) -> Result<Option<Self>, Self::Rejection> {
        <axum::Json<_> as OptionalFromRequest<S>>::from_request(req, state)
            .await
            .map_err(to_unprocessable_entity)
            .map(|value| value.map(|value| Self(value.0)))
    }
}

/// Convert a JSON rejection to an unprocessable entity status code.
#[track_caller]
fn to_unprocessable_entity(value: JsonRejection) -> StatusCode {
    log::warn!(
        "request contained an unprocessable body ({}): {}",
        value.status(),
        value.body_text()
    );
    StatusCode::UNPROCESSABLE_ENTITY
}