tina-core 0.0.2

Tina platform
Documentation
//! 接口委托
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::route::RouteBaseConfig;
use crate::tina::server::http::route_ext::{ApiResponder, FromApiRequest};
use crate::tina::server::session::Session;
use axum::extract::{FromRequest, FromRequestParts};
use axum::handler::Handler;
use axum::response::{IntoResponse, Response};
use futures::Future;
use http::Request;
use std::pin::Pin;
use std::sync::Arc;
use std::{fmt::Debug, marker::PhantomData};

use super::request_ext::RequestExt;
use super::route_ext::ApiHandler;

/// 接口委托
pub struct RouteHandlerDelegate<F, Args, S, B, M, Err>
where
    F: ApiHandler<Args, S, B, M> + Send + Clone + 'static,
    Args: FromApiRequest<S, B, M> + FromRequest<S, B, M> + Send + 'static,
    F::Output1: ApiResponder<AppError> + IntoResponse + Send + Sync + 'static,
    Err: Into<AppError> + IntoResponse + Send + 'static,
    S: Send + Sync + 'static,
    B: Send + Sync + 'static,
    M: Send + 'static,
{
    handler: F,
    _phantom_data: PhantomData<(Args, S, B, M, Err)>,
}

impl<F, S, B, M, Args, Err> RouteHandlerDelegate<F, Args, S, B, M, Err>
where
    F: ApiHandler<Args, S, B, M> + Send + Clone + 'static,
    Args: FromApiRequest<S, B, M> + FromRequest<S, B, M> + Send + 'static,
    F::Output1: ApiResponder<AppError> + IntoResponse + Send + Sync + 'static,
    Err: Into<AppError> + IntoResponse + Send + 'static,
    S: Send + Sync + 'static,
    B: Send + Sync + 'static,
    M: Send + 'static,
{
    /// 构建
    pub fn new(handler: F) -> Self {
        Self {
            handler,
            _phantom_data: Default::default(),
        }
    }
    async fn delegate_func(
        handler: F,
        (route_config, remote_ip_address, session, args): (Arc<RouteBaseConfig>, &str, Session, Args),
        state: S,
    ) -> AppResult<F::Output1> {
        let param_value = args.to_param_value()?;
        let r1 = before_delegate(route_config, remote_ip_address, &session, &param_value).await?;
        let r: F::Output1 = ApiHandler::call(handler, args, state).await;
        after_delegate(&session, &param_value, &r, r1).await?;
        Ok(r)
    }
}

impl<F, S, B, M, Args, Err> Clone for RouteHandlerDelegate<F, Args, S, B, M, Err>
where
    F: ApiHandler<Args, S, B, M> + Send + Clone + 'static,
    Args: FromApiRequest<S, B, M> + FromRequest<S, B, M> + Send + 'static,
    F::Output1: ApiResponder<AppError> + IntoResponse + Send + Sync + 'static,
    Err: Into<AppError> + IntoResponse + Send + 'static,
    S: Send + Sync + 'static,
    B: Send + Sync + 'static,
    M: Send + 'static,
{
    fn clone(&self) -> Self {
        Self {
            handler: self.handler.clone(),
            _phantom_data: Default::default(),
        }
    }
}

impl<F, S, B, M, Args, Err> Handler<Args, S, B> for RouteHandlerDelegate<F, Args, S, B, M, Err>
where
    F: ApiHandler<Args, S, B, M> + Send + Clone + 'static,
    Args: FromApiRequest<S, B, M> + FromRequest<S, B, M> + Send + 'static,
    F::Output1: ApiResponder<AppError> + IntoResponse + Send + Sync + 'static,
    Err: Into<AppError> + IntoResponse + Send + 'static,
    S: Send + Sync + 'static,
    B: Debug + Send + Sync + 'static,
    M: Send + 'static,
{
    type Future = Pin<Box<dyn Future<Output = Response> + Send>>;

    fn call(self, req: http::Request<B>, state: S) -> Self::Future {
        let old_handler = self.handler;
        Box::pin(async move {
            let route_config = match req.get_route_config() {
                Ok(v) => v,
                Err(err) => return err.into_response(),
            };
            let remote_ip_address = req.get_remote_ip_address().into_owned();
            let (mut parts, body) = req.into_parts();
            let session = match Session::from_request_parts(&mut parts, &state).await {
                Ok(v) => v,
                Err(err) => return err.into_response(),
            };
            let req2 = Request::from_parts(parts, body);
            let args = match Args::from_request(req2, &state).await {
                Ok(v) => v,
                Err(err) => return err.into_response(),
            };
            match Self::delegate_func(old_handler, (route_config, &remote_ip_address, session, args), state).await {
                Ok(v) => v.into_response(),
                Err(err) => err.into_response(),
            }
        })
    }
}