tina-core 0.0.2

Tina platform
Documentation
//! 接口委托
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, &param_value).await?;
        let r: F::Output = handler.call(args).await;
        after_delegate(&session, &param_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()
    }
}