use crate::tina::data::AppResult;
use crate::tina::server::http::middleware_process::{after_delegate, before_delegate};
use crate::tina::server::http::request::ReqMetadata;
use crate::tina::server::http::route_ext::{ApiResponder, FromApiRequest};
use crate::tina::server::session::Session;
use actix_web::error::Error;
use actix_web::Handler;
use futures_util::future::LocalBoxFuture;
use futures_util::FutureExt;
use std::marker::PhantomData;
use super::request_ext::RequestExt;
pub struct RouteHandlerDelegate<F, Args, Body>
where
F: Handler<Args> + Clone,
Args: FromApiRequest<Error> + 'static,
F::Output: ApiResponder<Body>,
Args::Error: Into<Error>,
<F as Handler<Args>>::Output: ApiResponder<Body>,
Body: 'static,
{
handler: F,
_phantom_data_1: PhantomData<Args>,
_phantom_data_2: PhantomData<Body>,
}
impl<F, Args, Body> RouteHandlerDelegate<F, Args, Body>
where
F: Handler<Args> + Clone,
Args: FromApiRequest<Error> + 'static,
F::Output: ApiResponder<Body>,
Args::Error: Into<Error>,
<F as Handler<Args>>::Output: ApiResponder<Body>,
Body: 'static,
{
pub fn new(handler: F) -> Self {
Self {
handler,
_phantom_data_1: Default::default(),
_phantom_data_2: Default::default(),
}
}
async fn delegate_func(handler: F, (req, session, args): (ReqMetadata, Session, Args)) -> AppResult<F::Output> {
let param_value = args.to_param_value()?;
let route_config = req.get_route_config()?;
let remote_ip_address = req.get_remote_ip_address();
let r1 = before_delegate(route_config, &remote_ip_address, &session, ¶m_value).await?;
let r: F::Output = handler.call(args).await;
after_delegate(&session, ¶m_value, &r, r1).await?;
Ok(r)
}
}
impl<F, Args, Body> Clone for RouteHandlerDelegate<F, Args, Body>
where
F: Handler<Args> + Clone,
Args: FromApiRequest<Error> + 'static,
F::Output: ApiResponder<Body>,
Args::Error: Into<Error>,
<F as Handler<Args>>::Output: ApiResponder<Body>,
Body: 'static,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
_phantom_data_1: Default::default(),
_phantom_data_2: Default::default(),
}
}
}
impl<F, Args, Body> Handler<(ReqMetadata, Session, Args)> for RouteHandlerDelegate<F, Args, Body>
where
F: Handler<Args> + Clone,
Args: FromApiRequest<Error> + 'static,
F::Output: ApiResponder<Body>,
Args::Error: Into<Error>,
<F as Handler<Args>>::Output: ApiResponder<Body>,
Body: 'static,
{
type Output = AppResult<F::Output>;
type Future = LocalBoxFuture<'static, AppResult<F::Output>>;
fn call(&self, param: (ReqMetadata, Session, Args)) -> Self::Future {
let old_handler = self.handler.clone();
async move { Self::delegate_func(old_handler, param).await }.boxed_local()
}
}