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, ¶m_value).await?;
let r: F::Output1 = ApiHandler::call(handler, args, state).await;
after_delegate(&session, ¶m_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(),
}
})
}
}