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;
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);
fn get_session(&self) -> Option<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>>>;
fn get_locale(&self) -> String;
}
pub trait RequestExt2: Send + Sync + 'static {
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"))
}
}