use crate::app_system_error;
use crate::tina::constant::Constants;
use crate::tina::data::http::request_ext::RequestTime;
use crate::tina::data::http::request_log_param::RequestLogParam;
use crate::tina::data::AppResult;
use crate::tina::i18n::ResourceBundle;
use crate::tina::server::application::Application;
use crate::tina::server::http::request::ReqMetadata;
use crate::tina::server::http::route::RouteBaseConfig;
use crate::tina::server::session::{Session, SessionInner};
use http::Method;
use ntex::web::{HttpRequest, WebRequest};
use std::any::Any;
use std::borrow::Cow;
use std::sync::Arc;
pub type AnyType = dyn Any + 'static;
pub trait RequestExt: crate::tina::server::http::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>(&self, value: Arc<T>)
where
Self: Sized;
fn clean_attributes(&self);
fn get_request_time(&self) -> AppResult<Arc<RequestTime>>;
fn get_route_config(&self) -> AppResult<Arc<RouteBaseConfig>>;
fn set_route_config(&self, config: &Arc<RouteBaseConfig>);
fn get_method(&self) -> Cow<Method>;
fn get_application(&self) -> AppResult<Application>;
fn set_application(&self, application: &Application);
fn get_session(&self) -> Option<Session>;
fn set_session(&self, session: Session);
fn get_remote_ip_address(&self) -> Cow<str>;
fn get_request_path(&self) -> Cow<str>;
fn get_user_agent(&self) -> Cow<str>;
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;
fn get_request_log_param(&self) -> AppResult<Option<Arc<RequestLogParam>>>;
fn set_request_log_param(&self, param: RequestLogParam);
}
pub trait RequestExt2 {}
impl RequestExt for HttpRequest {
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>(&self, value: Arc<T>)
where
Self: Sized,
{
let mut ext = self.extensions_mut();
ext.insert(value);
}
fn clean_attributes(&self) {
let mut ext = self.extensions_mut();
ext.clear()
}
fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
let mut request_time: Option<Arc<RequestTime>> = self.get_attribute()?;
if request_time.is_none() {
let application = self.get_application()?;
self.set_attribute(Arc::new(RequestTime::new(application)));
request_time = self.get_attribute()?;
}
let request_time = request_time.ok_or_else(|| crate::app_system_error!("no request time found..."))?;
Ok(request_time)
}
fn get_route_config(&self) -> AppResult<Arc<RouteBaseConfig>> {
let ext = self.extensions();
let attr: Option<&Arc<RouteBaseConfig>> = ext.get();
match attr {
None => Err(app_system_error!("no route config found in request")),
Some(v) => Ok(v.clone()),
}
}
fn set_route_config(&self, config: &Arc<RouteBaseConfig>) {
let mut ext = self.extensions_mut();
ext.insert(Arc::clone(config))
}
fn get_method(&self) -> Cow<Method> {
Cow::Borrowed(self.method())
}
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(&self, application: &Application) {
let mut ext = self.extensions_mut();
ext.insert(application.to_owned());
}
fn get_session(&self) -> Option<Session> {
let ext = self.extensions();
ext.get::<Session>().map(|o| o.clone())
}
fn set_session(&self, session: Session) {
let mut ext = self.extensions_mut();
ext.insert(session)
}
fn get_remote_ip_address(&self) -> Cow<str> {
let headers = self.headers();
if let Some(ip) = headers.get("x-forwarded-for") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("Proxy-Client-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("WL-Proxy-Client-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("X-Real-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
let ip_with_port = match self.connection_info().remote() {
None => "".to_owned(),
Some(s) => s.to_owned(),
};
return if ip_with_port.contains("[") && ip_with_port.contains("]") {
match ip_with_port.split("]").next() {
None => Cow::Owned(ip_with_port),
Some(s) => match s.len() > 0 {
true => Cow::Owned(s.split_at(1).1.to_string()),
false => Cow::Owned(ip_with_port),
},
}
} else {
match ip_with_port == "0:0:0:0:0:0:0:1" {
true => Cow::Borrowed("127.0.0.1"),
false => match ip_with_port.split(":").next() {
None => Cow::Owned(ip_with_port),
Some(s) => Cow::Owned(s.to_string()),
},
}
};
}
fn get_request_path(&self) -> Cow<str> {
Cow::Borrowed(self.path())
}
fn get_user_agent(&self) -> Cow<str> {
match self.get_request_header("User-Agent") {
Ok(Some(s)) => s,
_ => Cow::Borrowed(""),
}
}
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(),
},
}
}
fn get_request_log_param(&self) -> AppResult<Option<Arc<RequestLogParam>>> {
self.get_attribute()
}
fn set_request_log_param(&self, param: RequestLogParam) {
self.set_attribute(Arc::new(param));
}
}
impl<E> RequestExt for WebRequest<E> {
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>(&self, value: Arc<T>)
where
Self: Sized,
{
let mut ext = self.extensions_mut();
ext.insert(value);
}
fn clean_attributes(&self) {
let mut ext = self.extensions_mut();
ext.clear()
}
fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
let mut request_time: Option<Arc<RequestTime>> = self.get_attribute()?;
if request_time.is_none() {
let application = self.get_application()?;
self.set_attribute(Arc::new(RequestTime::new(application)));
request_time = self.get_attribute()?;
}
let request_time = request_time.ok_or_else(|| crate::app_system_error!("no request time found..."))?;
Ok(request_time)
}
fn get_route_config(&self) -> AppResult<Arc<RouteBaseConfig>> {
let ext = self.extensions();
let attr: Option<&Arc<RouteBaseConfig>> = ext.get();
match attr {
None => Err(app_system_error!("no route config found in request")),
Some(v) => Ok(v.clone()),
}
}
fn set_route_config(&self, config: &Arc<RouteBaseConfig>) {
let mut ext = self.extensions_mut();
ext.insert(Arc::clone(config))
}
fn get_method(&self) -> Cow<Method> {
Cow::Borrowed(self.method())
}
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(&self, application: &Application) {
let mut ext = self.extensions_mut();
ext.insert(application.to_owned());
}
fn get_session(&self) -> Option<Session> {
let ext = self.extensions();
ext.get::<Session>().map(|o| o.clone())
}
fn set_session(&self, session: Session) {
let mut ext = self.extensions_mut();
ext.insert(session)
}
fn get_remote_ip_address(&self) -> Cow<str> {
let headers = self.headers();
if let Some(ip) = headers.get("x-forwarded-for") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("Proxy-Client-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("WL-Proxy-Client-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
if let Some(ip) = headers.get("X-Real-IP") {
return match ip.to_str() {
Ok(s) => Cow::Borrowed(s),
Err(e) => {
tracing::error!("{:?}", e);
Cow::Borrowed("")
}
};
}
let ip_with_port = match self.connection_info().remote() {
None => "".to_owned(),
Some(s) => s.to_owned(),
};
return if ip_with_port.contains("[") && ip_with_port.contains("]") {
match ip_with_port.split("]").next() {
None => Cow::Owned(ip_with_port),
Some(s) => match s.len() > 0 {
true => Cow::Owned(s.split_at(1).1.to_string()),
false => Cow::Owned(ip_with_port),
},
}
} else {
match ip_with_port == "0:0:0:0:0:0:0:1" {
true => Cow::Borrowed("127.0.0.1"),
false => match ip_with_port.split(":").next() {
None => Cow::Owned(ip_with_port),
Some(s) => Cow::Owned(s.to_string()),
},
}
};
}
fn get_request_path(&self) -> Cow<str> {
Cow::Borrowed(self.path())
}
fn get_user_agent(&self) -> Cow<str> {
match self.get_request_header("User-Agent") {
Ok(Some(s)) => s,
_ => Cow::Borrowed(""),
}
}
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(),
},
}
}
fn get_request_log_param(&self) -> AppResult<Option<Arc<RequestLogParam>>> {
self.get_attribute()
}
fn set_request_log_param(&self, param: RequestLogParam) {
self.set_attribute(Arc::new(param));
}
}
impl RequestExt for ReqMetadata {
fn get_attribute<T: Send + Sync + 'static>(&self) -> AppResult<Option<Arc<T>>>
where
Self: Sized,
{
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_attribute()
}
fn set_attribute<T: Send + Sync + 'static>(&self, value: Arc<T>)
where
Self: Sized,
{
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.set_attribute(value)
}
fn clean_attributes(&self) {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.clean_attributes()
}
fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_request_time()
}
fn get_route_config(&self) -> AppResult<Arc<RouteBaseConfig>> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_route_config()
}
fn set_route_config(&self, config: &Arc<RouteBaseConfig>) {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.set_route_config(config)
}
fn get_method(&self) -> Cow<Method> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_method()
}
fn get_application(&self) -> AppResult<Application> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_application()
}
fn set_application(&self, application: &Application) {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.set_application(application)
}
fn get_session(&self) -> Option<Session> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_session()
}
fn set_session(&self, session: Session) {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.set_session(session)
}
fn get_remote_ip_address(&self) -> Cow<str> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_remote_ip_address()
}
fn get_request_path(&self) -> Cow<str> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_request_path()
}
fn get_user_agent(&self) -> Cow<str> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_user_agent()
}
fn get_request_header(&self, name: &str) -> AppResult<Option<Cow<str>>> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_request_header(name)
}
fn get_request_headers(&self, name: &str) -> AppResult<Vec<Cow<str>>> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_request_headers(name)
}
fn get_locale(&self) -> String {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_locale()
}
fn get_request_log_param(&self) -> AppResult<Option<Arc<RequestLogParam>>> {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.get_request_log_param()
}
fn set_request_log_param(&self, param: RequestLogParam) {
let request = self.request.downcast_ref::<HttpRequest>().expect("inner request type error");
request.set_request_log_param(param)
}
}
#[async_trait(?Send)]
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>(&self, _value: Arc<T>)
where
Self: Sized,
{
}
fn clean_attributes(&self) {}
fn get_request_time(&self) -> AppResult<Arc<RequestTime>> {
Err(app_system_error!("unsupported"))
}
fn get_route_config(&self) -> AppResult<Arc<RouteBaseConfig>> {
Err(app_system_error!("unsupported"))
}
fn set_route_config(&self, _config: &Arc<RouteBaseConfig>) {}
fn get_method(&self) -> Cow<Method> {
Cow::Owned(Method::default())
}
fn get_application(&self) -> AppResult<Application> {
Err(app_system_error!("unsupported"))
}
fn set_application(&self, _application: &Application) {}
fn get_session(&self) -> Option<Session> {
None
}
fn set_session(&self, _: Session) {}
fn get_remote_ip_address(&self) -> Cow<str> {
Cow::Borrowed("")
}
fn get_request_path(&self) -> Cow<str> {
Cow::Borrowed("")
}
fn get_user_agent(&self) -> Cow<str> {
Cow::Borrowed("")
}
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()
}
fn get_request_log_param(&self) -> AppResult<Option<Arc<RequestLogParam>>> {
Ok(None)
}
fn set_request_log_param(&self, _param: RequestLogParam) {}
}
impl RequestExt2 for HttpRequest {}
impl<B> RequestExt2 for WebRequest<B> {}
impl RequestExt2 for ReqMetadata {}
impl RequestExt2 for () {}
impl RequestExt2 for SessionInner {}