ayun-server 0.23.0

The RUST Framework for Web Rustceans.
Documentation
use crate::Result;
use axum::{
    body::Body,
    http::{header, response::Builder, HeaderName, HeaderValue, StatusCode},
    response::Response,
};
use std::any::Any;

pub struct ResponseBuilder {
    inner: Builder,
}

impl Default for ResponseBuilder {
    fn default() -> Self {
        Self::new()
    }
}

impl ResponseBuilder {
    fn new() -> Self {
        Self {
            inner: Builder::new().status(StatusCode::OK),
        }
    }

    pub fn builder(self) -> Builder {
        self.inner
    }

    pub fn status<T>(self, status: T) -> Self
    where
        StatusCode: TryFrom<T>,
        <StatusCode as TryFrom<T>>::Error: Into<axum::http::Error>,
    {
        Self {
            inner: self.inner.status(status),
        }
    }

    pub fn header<K, V>(self, key: K, value: V) -> Self
    where
        HeaderName: TryFrom<K>,
        <HeaderName as TryFrom<K>>::Error: Into<axum::http::Error>,
        HeaderValue: TryFrom<V>,
        <HeaderValue as TryFrom<V>>::Error: Into<axum::http::Error>,
    {
        Self {
            inner: self.inner.header(key, value),
        }
    }

    pub fn extension<T>(self, extension: T) -> Self
    where
        T: Clone + Any + Send + Sync + 'static,
    {
        Self {
            inner: self.inner.extension(extension),
        }
    }

    pub fn etag(self, etag: &str) -> Result<Self, crate::Error> {
        Ok(Self {
            inner: self
                .inner
                .header(header::ETAG, HeaderValue::from_str(etag)?),
        })
    }

    #[cfg(feature = "response-cookie")]
    pub fn cookies(
        self,
        cookies: &[axum_extra::extract::cookie::Cookie<'_>],
    ) -> Result<Self, crate::Error> {
        let mut resp = self.inner;

        for cookie in cookies {
            let header_value = cookie.encoded().to_string().parse::<HeaderValue>()?;
            resp = resp.header(header::SET_COOKIE, header_value);
        }

        Ok(Self { inner: resp })
    }

    pub fn text(self, content: &str) -> Result<Response, crate::Error> {
        Ok(self
            .inner
            .header(
                header::CONTENT_TYPE,
                HeaderValue::from_static(mime::TEXT_PLAIN_UTF_8.as_ref()),
            )
            .body(Body::from(content.to_string()))?)
    }

    pub fn empty(self) -> Result<Response, crate::Error> {
        Ok(self.inner.body(Body::empty())?)
    }

    pub fn html(self, content: &str) -> Result<Response, crate::Error> {
        Ok(self
            .inner
            .header(
                header::CONTENT_TYPE,
                HeaderValue::from_static(mime::TEXT_HTML_UTF_8.as_ref()),
            )
            .body(Body::from(content.to_string()))?)
    }

    #[cfg(feature = "response-json")]
    pub fn json<T>(self, item: T) -> Result<Response, crate::Error>
    where
        T: serde::Serialize,
    {
        use bytes::{BufMut, BytesMut};

        let mut buf = BytesMut::with_capacity(128).writer();
        serde_json::to_writer(&mut buf, &item)?;

        let body = Body::from(buf.into_inner().freeze());

        Ok(self
            .inner
            .header(
                header::CONTENT_TYPE,
                HeaderValue::from_static(mime::APPLICATION_JSON.as_ref()),
            )
            .body(body)?)
    }

    #[cfg(feature = "response-view")]
    pub fn view<T>(self, template: &str, data: T) -> Result<Response, crate::Error>
    where
        T: serde::Serialize,
    {
        let engine = ayun_core::app().resolve::<ayun_view::View>()?;
        let html = engine.render(template, &tera::Context::from_serialize(data)?)?;

        self.html(&html)
    }

    pub fn redirect(self, to: &str) -> Result<Response, crate::Error> {
        Ok(self
            .inner
            .status(StatusCode::SEE_OTHER)
            .header(header::LOCATION, to)
            .body(Body::empty())?)
    }
}