diff --git a/actix-web/CHANGES.md b/actix-web/CHANGES.md index 0144cb912..ee4987b87 100644 --- a/actix-web/CHANGES.md +++ b/actix-web/CHANGES.md @@ -18,6 +18,7 @@ - Add `Route::wrap()` to allow individual routes to use middleware. [#2725] - Add `ServiceConfig::default_service()`. [#2338] [#2743] - Implement `ResponseError` for `std::convert::Infallible` +- Add `Condition::from_option()` to allow creating a conditional middleware from an `Option`. [#2623] ### Changed - Minimum supported Rust version (MSRV) is now 1.56 due to transitive `hashbrown` dependency. diff --git a/actix-web/src/middleware/condition.rs b/actix-web/src/middleware/condition.rs index 65f25a67c..e46ce08ff 100644 --- a/actix-web/src/middleware/condition.rs +++ b/actix-web/src/middleware/condition.rs @@ -26,18 +26,31 @@ use crate::{ /// let app = App::new() /// .wrap(Condition::new(enable_normalize, NormalizePath::default())); /// ``` +/// Or you can use an `Option` to create a new instance: +/// ``` +/// use actix_web::middleware::{Condition, NormalizePath}; +/// use actix_web::App; +/// +/// let app = App::new() +/// .wrap(Condition::from_option(Some(NormalizePath::default()))); +/// ``` pub struct Condition { - transformer: T, - enable: bool, + transformer: Option, } impl Condition { pub fn new(enable: bool, transformer: T) -> Self { Self { - transformer, - enable, + transformer: match enable { + true => Some(transformer), + false => None, + }, } } + + pub fn from_option(transformer: Option) -> Self { + Self { transformer } + } } impl Transform for Condition @@ -55,8 +68,8 @@ where type Future = LocalBoxFuture<'static, Result>; fn new_transform(&self, service: S) -> Self::Future { - if self.enable { - let fut = self.transformer.new_transform(service); + if let Some(transformer) = &self.transformer { + let fut = transformer.new_transform(service); async move { let wrapped_svc = fut.await?; Ok(ConditionMiddleware::Enable(wrapped_svc)) @@ -131,6 +144,7 @@ where #[cfg(test)] mod tests { use actix_service::IntoService as _; + use futures_util::future::ok; use super::*; use crate::{ @@ -167,6 +181,18 @@ mod tests { let _ = Condition::new(true, middleware::ErrorHandlers::::new()); } + fn create_optional_mw(enabled: bool) -> Option> + where + B: 'static, + { + match enabled { + true => Some( + ErrorHandlers::new().handler(StatusCode::INTERNAL_SERVER_ERROR, render_500), + ), + false => None, + } + } + #[actix_rt::test] async fn test_handler_enabled() { let srv = |req: ServiceRequest| async move { @@ -204,4 +230,33 @@ mod tests { test::call_service(&mw, TestRequest::default().to_srv_request()).await; assert_eq!(resp.headers().get(CONTENT_TYPE), None); } + + #[actix_rt::test] + async fn test_handler_some() { + let srv = |req: ServiceRequest| { + ok(req.into_response(HttpResponse::InternalServerError().finish())) + }; + + let mw = Condition::from_option(create_optional_mw(true)) + .new_transform(srv.into_service()) + .await + .unwrap(); + let resp = test::call_service(&mw, TestRequest::default().to_srv_request()).await; + assert_eq!(resp.headers().get(CONTENT_TYPE).unwrap(), "0001"); + } + + #[actix_rt::test] + async fn test_handler_none() { + let srv = |req: ServiceRequest| { + ok(req.into_response(HttpResponse::InternalServerError().finish())) + }; + + let mw = Condition::from_option(create_optional_mw(false)) + .new_transform(srv.into_service()) + .await + .unwrap(); + + let resp = test::call_service(&mw, TestRequest::default().to_srv_request()).await; + assert_eq!(resp.headers().get(CONTENT_TYPE), None); + } }