diff --git a/src/middleware/condition.rs b/src/middleware/condition.rs new file mode 100644 index 000000000..d130818f4 --- /dev/null +++ b/src/middleware/condition.rs @@ -0,0 +1,93 @@ +use actix_service::{Service, Transform}; +use futures::future::{ok, Either, FutureResult, Map}; +use futures::{Future, Poll}; + +/// `Middleware` for conditianally enables another middleware +/// The controled middleware must not change the `Service` interfaces. +/// This means you cannot control such middlewares like `Logger` or `Compress`. +/// +/// ## Usage +/// +/// ``` +/// use actix_web::middleware::{Condition, NormalizePath}; +/// use actix_web::App; +/// +/// fn main() { +/// std::env::set_var("RUST_LOG", "actix_web=info"); +/// env_logger::init(); +/// +/// let app = App::new() +/// .wrap(Condition::new(true, NormalizePath)); +/// } +/// ``` +/// +pub struct Condition { + trans: T, + enable: bool, +} + +impl Condition { + pub fn new(enable: bool, trans: T) -> Self { + Self { trans, enable } + } +} + +impl Transform for Condition +where + S: Service, + T: Transform, +{ + type Request = S::Request; + type Response = S::Response; + type Error = S::Error; + type InitError = T::InitError; + type Transform = ConditionMiddleware; + type Future = Either< + Map Self::Transform>, + FutureResult, + >; + + fn new_transform(&self, service: S) -> Self::Future { + if self.enable { + let f = self + .trans + .new_transform(service) + .map(ConditionMiddleware::Enable as fn(T::Transform) -> Self::Transform); + Either::A(f) + } else { + Either::B(ok(ConditionMiddleware::Disable(service))) + } + } +} + +pub enum ConditionMiddleware { + Enable(E), + Disable(D), +} + +impl Service for ConditionMiddleware +where + E: Service, + D: Service, +{ + type Request = E::Request; + type Response = E::Response; + type Error = E::Error; + type Future = Either; + + fn poll_ready(&mut self) -> Poll<(), Self::Error> { + use ConditionMiddleware::*; + match self { + Enable(service) => service.poll_ready(), + Disable(service) => service.poll_ready(), + } + } + + fn call(&mut self, req: E::Request) -> Self::Future { + use ConditionMiddleware::*; + match self { + Enable(service) => Either::A(service.call(req)), + Disable(service) => Either::B(service.call(req)), + } + } +} diff --git a/src/middleware/mod.rs b/src/middleware/mod.rs index 814993f0c..311d0ee99 100644 --- a/src/middleware/mod.rs +++ b/src/middleware/mod.rs @@ -6,7 +6,9 @@ mod defaultheaders; pub mod errhandlers; mod logger; mod normalize; +mod condition; pub use self::defaultheaders::DefaultHeaders; pub use self::logger::Logger; pub use self::normalize::NormalizePath; +pub use self::condition::Condition;