static condition middleware future

This commit is contained in:
ibraheemdev 2021-04-22 12:08:44 -04:00
parent 73b89d6f58
commit 015e1c7b4d
1 changed files with 31 additions and 9 deletions

View File

@ -1,11 +1,13 @@
//! For middleware documentation, see [`Condition`]. //! For middleware documentation, see [`Condition`].
use std::future::Future;
use std::pin::Pin;
use std::task::{Context, Poll}; use std::task::{Context, Poll};
use actix_service::{Service, Transform}; use actix_service::{Service, Transform};
use actix_utils::future::Either; use actix_utils::future::Either;
use futures_core::future::LocalBoxFuture;
use futures_util::future::FutureExt as _; use futures_core::ready;
/// Middleware for conditionally enabling other middleware. /// Middleware for conditionally enabling other middleware.
/// ///
@ -48,22 +50,42 @@ where
type Error = S::Error; type Error = S::Error;
type Transform = ConditionMiddleware<T::Transform, S>; type Transform = ConditionMiddleware<T::Transform, S>;
type InitError = T::InitError; type InitError = T::InitError;
type Future = LocalBoxFuture<'static, Result<Self::Transform, Self::InitError>>; type Future = ConditionFut<<T>::Future, S>;
fn new_transform(&self, service: S) -> Self::Future { fn new_transform(&self, service: S) -> Self::Future {
if self.enable { if self.enable {
let fut = self.transformer.new_transform(service); let fut = self.transformer.new_transform(service);
async move { ConditionFut::Enable(fut)
let wrapped_svc = fut.await?;
Ok(ConditionMiddleware::Enable(wrapped_svc))
}
.boxed_local()
} else { } else {
async move { Ok(ConditionMiddleware::Disable(service)) }.boxed_local() ConditionFut::Disable(Some(service))
} }
} }
} }
#[pin_project::pin_project(project = ConditionFutProj)]
pub enum ConditionFut<F, D> {
Enable(#[pin] F),
Disable(Option<D>),
}
impl<F, E, D, Ie> Future for ConditionFut<F, D>
where
F: Future<Output = Result<E, Ie>>,
{
type Output = Result<ConditionMiddleware<E, D>, Ie>;
fn poll(self: Pin<&mut Self>, cx: &mut Context<'_>) -> Poll<Self::Output> {
let middleware = match self.project() {
ConditionFutProj::Enable(fut) => ConditionMiddleware::Enable(ready!(fut.poll(cx))?),
ConditionFutProj::Disable(service) => {
ConditionMiddleware::Disable(service.take().unwrap())
}
};
Poll::Ready(Ok(middleware))
}
}
pub enum ConditionMiddleware<E, D> { pub enum ConditionMiddleware<E, D> {
Enable(E), Enable(E),
Disable(D), Disable(D),