by-types 0.3.7

Biyard data types
Documentation
use axum::{
    http::{HeaderMap, HeaderValue},
    response::{IntoResponse, Response},
};
use reqwest::header::{self, IntoHeaderName};
use serde::{Deserialize, Deserializer};

#[derive(Debug, Clone, Default, aide::OperationIo)]
pub struct JsonWithHeaders<T> {
    pub body: T,
    pub headers: HeaderMap,
}

impl<T> JsonWithHeaders<T> {
    pub fn new(body: T) -> Self {
        Self {
            body,
            headers: HeaderMap::new(),
        }
    }

    pub fn insert_header<K>(mut self, key: K, value: &str) -> Self
    where
        K: IntoHeaderName,
    {
        self.headers
            .insert(key, HeaderValue::from_str(&value).unwrap());
        self
    }

    pub fn with_cookie(mut self, value: &str) -> Self {
        self.headers
            .insert(header::SET_COOKIE, HeaderValue::from_str(&value).unwrap());
        self
    }

    pub fn with_authorization(mut self, auth_type: &str, value: &str) -> Self {
        self.headers.insert(
            header::AUTHORIZATION,
            HeaderValue::from_str(&format!("{} {}", auth_type, value)).unwrap(),
        );
        self
    }

    pub fn with_bearer_token(self, token: &str) -> Self {
        self.with_authorization("Bearer", token)
    }
}

impl<T> serde::Serialize for JsonWithHeaders<T>
where
    T: serde::Serialize,
{
    fn serialize<S>(&self, serializer: S) -> Result<S::Ok, S::Error>
    where
        S: serde::Serializer,
    {
        self.body.serialize(serializer)
    }
}

impl<'de, T> Deserialize<'de> for JsonWithHeaders<T>
where
    T: Deserialize<'de>,
{
    fn deserialize<D>(deserializer: D) -> Result<Self, D::Error>
    where
        D: Deserializer<'de>,
    {
        let body = T::deserialize(deserializer)?;
        Ok(JsonWithHeaders {
            body,
            headers: HeaderMap::new(),
        })
    }
}

impl<T> schemars::JsonSchema for JsonWithHeaders<T>
where
    T: schemars::JsonSchema,
{
    fn schema_name() -> String {
        T::schema_name()
    }

    fn json_schema(gen: &mut schemars::gen::SchemaGenerator) -> schemars::schema::Schema {
        T::json_schema(gen)
    }
}

impl<T> IntoResponse for JsonWithHeaders<T>
where
    T: serde::Serialize,
{
    fn into_response(self) -> Response {
        (
            axum::http::StatusCode::OK,
            self.headers,
            axum::Json(self.body),
        )
            .into_response()
    }
}