tina-core 0.0.2

Tina platform
Documentation
//! Request扩展
use crate::tina::constant::Constants;
use crate::tina::data::request_ext::RequestTime;
use crate::tina::data::AppResult;
use crate::tina::i18n::ResourceBundle;
use crate::tina::server::application::Application;
use crate::tina::server::session::{Session, SessionInner};
use crate::{app_system_error, tina::grpc::request::Request};
use http::request::Parts;
use std::any::Any;
use std::borrow::Cow;
use std::sync::Arc;

/// 任何类型
pub type AnyType = dyn Any + Send + Sync + 'static;

/// Request扩展
pub trait RequestExt: crate::tina::server::grpc::request_ext::RequestExt2 {
    /// 获取属性
    fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
    where
        Self: Sized;
    /// 设置属性
    fn set_attribute<T: Send + Sync + 'static>(&mut self, value: Arc<T>)
    where
        Self: Sized;
    /// 清除属性
    fn clean_attributes(&mut self);
    /// 获取请求时间
    fn get_request_time(&self) -> AppResult<Arc<RequestTime>>;
    /// 获取应用配置
    fn get_application(&self) -> AppResult<Application>;
    /// 设置应用配置
    fn set_application(&mut self, application: &Application);
    /// 获取Session
    fn get_session(&self) -> Option<Session>;
    /// 设置Session
    fn set_session(&mut self, session: Session);
    /// 获取请求头
    fn get_request_header(&self, name: &str) -> AppResult<Option<Cow<str>>>;
    /// 获取请求头
    fn get_request_headers(&self, name: &str) -> AppResult<Vec<Cow<str>>>;
    /// 获取请求Locale
    fn get_locale(&self) -> String;
}

/// Request扩展2
pub trait RequestExt2: Send + Sync + 'static {
    /// 获取Parts
    fn get_request_part(&self) -> AppResult<&Parts>;
}

impl RequestExt for Request {
    fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
    where
        Self: Sized,
    {
        self.inner.get_attribute()
    }

    fn set_attribute<T: Send + Sync + 'static>(&mut self, value: Arc<T>)
    where
        Self: Sized,
    {
        self.inner.set_attribute(value)
    }

    fn clean_attributes(&mut self) {
        self.inner.clean_attributes()
    }

    fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
        self.inner.get_request_time()
    }

    fn get_application(&self) -> AppResult<Application> {
        self.inner.get_application()
    }

    fn set_application(&mut self, application: &Application) {
        self.inner.set_application(application)
    }

    fn get_session(&self) -> Option<Session> {
        self.inner.get_session()
    }

    fn set_session(&mut self, session: Session) {
        self.inner.set_session(session)
    }

    fn get_request_header(&self, name: &str) -> AppResult<Option<Cow<str>>> {
        self.inner.get_request_header(name)
    }

    fn get_request_headers(&self, name: &str) -> AppResult<Vec<Cow<str>>> {
        self.inner.get_request_headers(name)
    }

    fn get_locale(&self) -> String {
        self.inner.get_locale()
    }
}

impl RequestExt for http::Request<hyper::Body> {
    fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
    where
        Self: Sized,
    {
        let ext = self.extensions();
        let attr: Option<&Arc<T>> = ext.get();
        match attr {
            None => Ok(None),
            Some(v) => Ok(Some(Arc::clone(v))),
        }
    }

    fn set_attribute<T: Send + Sync + 'static>(&mut self, value: Arc<T>)
    where
        Self: Sized,
    {
        let ext = self.extensions_mut();
        ext.insert(value);
    }

    fn clean_attributes(&mut self) {
        let ext = self.extensions_mut();
        ext.clear()
    }

    fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
        let request_time: Option<Arc<RequestTime>> = self.get_attribute()?;
        let request_time = request_time.ok_or_else(|| crate::app_system_error!("no request time found..."))?;
        Ok(request_time)
    }

    fn get_application(&self) -> AppResult<Application> {
        let ext = self.extensions();
        ext.get::<Application>().map(|o| o.to_owned()).ok_or_else(|| crate::app_system_error!("no application found in request"))
    }

    fn set_application(&mut self, application: &Application) {
        let ext = self.extensions_mut();
        ext.insert(application.to_owned());
    }

    fn get_session(&self) -> Option<Session> {
        let ext = self.extensions();
        ext.get::<Session>().cloned()
    }

    fn set_session(&mut self, session: Session) {
        let ext = self.extensions_mut();
        ext.insert(session);
    }

    fn get_request_header(&self, name: &str) -> AppResult<Option<Cow<str>>> {
        let headers = self.get_request_headers(name)?;
        match headers.is_empty() {
            true => Ok(None),
            false => Ok(headers.into_iter().next()),
        }
    }

    fn get_request_headers(&self, name: &str) -> AppResult<Vec<Cow<str>>> {
        let mut values = vec![];
        let all = self.headers().get_all(name);
        for value in all {
            if let Ok(value) = value.to_str() {
                if value.is_empty() || value == "null" {
                    continue;
                }
                values.push(Cow::Borrowed(value));
            }
        }
        Ok(values)
    }

    fn get_locale(&self) -> String {
        match self.headers().get(Constants::REQUEST_HEADER_LOCALE) {
            None => ResourceBundle::get_default_locale(),
            Some(header) => match header.to_str() {
                Ok(val) => val.to_string(),
                Err(_) => ResourceBundle::get_default_locale(),
            },
        }
    }
}

impl RequestExt for Parts {
    fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
    where
        Self: Sized,
    {
        let ext = &self.extensions;
        let attr: Option<&Arc<T>> = ext.get();
        match attr {
            None => Ok(None),
            Some(v) => Ok(Some(Arc::clone(v))),
        }
    }

    fn set_attribute<T: Send + Sync + 'static>(&mut self, value: Arc<T>)
    where
        Self: Sized,
    {
        let ext = &mut self.extensions;
        ext.insert(value);
    }

    fn clean_attributes(&mut self) {
        let ext = &mut self.extensions;
        ext.clear()
    }

    fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
        let request_time: Option<Arc<RequestTime>> = self.get_attribute()?;
        let request_time = request_time.ok_or_else(|| crate::app_system_error!("no request time found..."))?;
        Ok(request_time)
    }

    fn get_application(&self) -> AppResult<Application> {
        let ext = &self.extensions;
        ext.get::<Application>().map(|o| o.to_owned()).ok_or_else(|| crate::app_system_error!("no application found in request"))
    }

    fn set_application(&mut self, application: &Application) {
        let ext = &mut self.extensions;
        ext.insert(application.to_owned());
    }

    fn get_session(&self) -> Option<Session> {
        let ext = &self.extensions;
        ext.get::<Session>().cloned()
    }

    fn set_session(&mut self, session: Session) {
        let ext = &mut self.extensions;
        ext.insert(session);
    }

    fn get_request_header(&self, name: &str) -> AppResult<Option<Cow<str>>> {
        let headers = self.get_request_headers(name)?;
        match headers.is_empty() {
            true => Ok(None),
            false => Ok(headers.into_iter().next()),
        }
    }

    fn get_request_headers(&self, name: &str) -> AppResult<Vec<Cow<str>>> {
        let mut values = vec![];
        let all = self.headers.get_all(name);
        for value in all {
            if let Ok(value) = value.to_str() {
                if value.is_empty() || value == "null" {
                    continue;
                }
                values.push(Cow::Borrowed(value));
            }
        }
        Ok(values)
    }

    fn get_locale(&self) -> String {
        match self.headers.get(Constants::REQUEST_HEADER_LOCALE) {
            None => ResourceBundle::get_default_locale(),
            Some(header) => match header.to_str() {
                Ok(val) => val.to_string(),
                Err(_) => ResourceBundle::get_default_locale(),
            },
        }
    }
}

impl RequestExt for () {
    fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
    where
        Self: Sized,
    {
        Ok(None)
    }

    fn set_attribute<T: Send + Sync + 'static>(&mut self, _value: Arc<T>)
    where
        Self: Sized,
    {
    }

    fn clean_attributes(&mut self) {}

    fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
        Err(app_system_error!("unsupported"))
    }

    fn get_application(&self) -> AppResult<Application> {
        Err(app_system_error!("unsupported"))
    }

    fn set_application(&mut self, _application: &Application) {}

    fn get_session(&self) -> Option<Session> {
        None
    }

    fn set_session(&mut self, _: Session) {}

    fn get_request_header(&self, _name: &str) -> AppResult<Option<Cow<str>>> {
        Ok(None)
    }

    fn get_request_headers(&self, _name: &str) -> AppResult<Vec<Cow<str>>> {
        Ok(vec![])
    }

    fn get_locale(&self) -> String {
        ResourceBundle::get_default_locale()
    }
}

impl RequestExt2 for Request {
    fn get_request_part(&self) -> AppResult<&Parts> {
        self.inner.get_request_part()
    }
}

impl RequestExt2 for http::Request<hyper::Body> {
    fn get_request_part(&self) -> AppResult<&Parts> {
        unimplemented!()
    }
}
impl RequestExt2 for Parts {
    fn get_request_part(&self) -> AppResult<&Parts> {
        Ok(self)
    }
}
impl RequestExt2 for () {
    fn get_request_part(&self) -> AppResult<&Parts> {
        unimplemented!()
    }
}
impl RequestExt2 for SessionInner {
    fn get_request_part(&self) -> AppResult<&Parts> {
        Err(app_system_error!("Cannot get request parts from session, please use ReqMetadata"))
    }
}