use crate::tina::data::app_error::AppError;
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 futures_util::future::LocalBoxFuture;
use futures_util::FutureExt;
use ntex::web::Handler;
use std::marker::PhantomData;
use super::request_ext::RequestExt;
pub struct RouteHandlerDelegate<F, Args>
where
F: Handler<Args, AppError> + Clone + 'static,
Args: FromApiRequest<AppError> + 'static,
Args::Error: Into<AppError>,
F::Output: ApiResponder<AppError>,
{
handler: F,
_phantom_data: PhantomData<Args>,
}
impl<F, Args> RouteHandlerDelegate<F, Args>
where
F: Handler<Args, AppError> + Clone + 'static,
Args: FromApiRequest<AppError> + 'static,
Args::Error: Into<AppError>,
F::Output: ApiResponder<AppError>,
{
pub fn new(handler: F) -> Self {
Self {
handler,
_phantom_data: 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> Clone for RouteHandlerDelegate<F, Args>
where
Args: 'static + FromApiRequest<AppError>,
Args::Error: Into<AppError>,
F: Handler<Args, AppError> + Clone + 'static,
F::Output: ApiResponder<AppError>,
{
fn clone(&self) -> Self {
Self {
handler: self.handler.clone(),
_phantom_data: Default::default(),
}
}
}
impl<F, Args> Handler<(ReqMetadata, Session, Args), AppError> for RouteHandlerDelegate<F, Args>
where
F: Handler<Args, AppError> + Clone + 'static,
Args: FromApiRequest<AppError> + 'static,
Args::Error: Into<AppError>,
F::Output: ApiResponder<AppError>,
{
type Output = AppResult<F::Output>;
type Future<'f> = LocalBoxFuture<'f, AppResult<F::Output>> where F: 'f;
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()
}
}