From cfd5b381f13937bb00be6bc427c8687a5f5b9732 Mon Sep 17 00:00:00 2001 From: Matt Gathu Date: Mon, 19 Oct 2020 08:18:16 +0200 Subject: [PATCH] Implement Logger middleware regex exclude pattern (#1723) Co-authored-by: Rob Ede --- CHANGES.md | 2 ++ Cargo.toml | 2 +- src/middleware/logger.rs | 41 ++++++++++++++++++++++++++++++++++++++-- 3 files changed, 42 insertions(+), 3 deletions(-) diff --git a/CHANGES.md b/CHANGES.md index 5fd3869f9..ea77607c7 100644 --- a/CHANGES.md +++ b/CHANGES.md @@ -1,7 +1,9 @@ # Changes ## Unreleased - 2020-xx-xx +* Implement Logger middleware regex exclude pattern [#1723] +[#1723]: https://github.com/actix/actix-web/pull/1723 ## 3.1.0 - 2020-09-29 ### Changed diff --git a/Cargo.toml b/Cargo.toml index 56158389c..3960b4d36 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -91,7 +91,7 @@ log = "0.4" mime = "0.3" socket2 = "0.3" pin-project = "0.4.17" -regex = "1.3" +regex = "1.4" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" serde_urlencoded = "0.6.1" diff --git a/src/middleware/logger.rs b/src/middleware/logger.rs index 51d4722d7..9a38d345b 100644 --- a/src/middleware/logger.rs +++ b/src/middleware/logger.rs @@ -13,7 +13,7 @@ use actix_service::{Service, Transform}; use bytes::Bytes; use futures_util::future::{ok, Ready}; use log::debug; -use regex::Regex; +use regex::{Regex, RegexSet}; use time::OffsetDateTime; use crate::dev::{BodySize, MessageBody, ResponseBody}; @@ -92,6 +92,7 @@ pub struct Logger(Rc); struct Inner { format: Format, exclude: HashSet, + exclude_regex: RegexSet, } impl Logger { @@ -100,6 +101,7 @@ impl Logger { Logger(Rc::new(Inner { format: Format::new(format), exclude: HashSet::new(), + exclude_regex: RegexSet::empty(), })) } @@ -111,6 +113,16 @@ impl Logger { .insert(path.into()); self } + + /// Ignore and do not log access info for paths that match regex + pub fn exclude_regex>(mut self, path: T) -> Self { + let inner = Rc::get_mut(&mut self.0).unwrap(); + let mut patterns = inner.exclude_regex.patterns().to_vec(); + patterns.push(path.into()); + let regex_set = RegexSet::new(patterns).unwrap(); + inner.exclude_regex = regex_set; + self + } } impl Default for Logger { @@ -123,6 +135,7 @@ impl Default for Logger { Logger(Rc::new(Inner { format: Format::default(), exclude: HashSet::new(), + exclude_regex: RegexSet::empty(), })) } } @@ -168,7 +181,9 @@ where } fn call(&mut self, req: ServiceRequest) -> Self::Future { - if self.inner.exclude.contains(req.path()) { + if self.inner.exclude.contains(req.path()) + || self.inner.exclude_regex.is_match(req.path()) + { LoggerResponse { fut: self.service.call(req), format: None, @@ -538,6 +553,28 @@ mod tests { let _res = srv.call(req).await; } + #[actix_rt::test] + async fn test_logger_exclude_regex() { + let srv = |req: ServiceRequest| { + ok(req.into_response( + HttpResponse::build(StatusCode::OK) + .header("X-Test", "ttt") + .finish(), + )) + }; + let logger = Logger::new("%% %{User-Agent}i %{X-Test}o %{HOME}e %D test") + .exclude_regex("\\w"); + + let mut srv = logger.new_transform(srv.into_service()).await.unwrap(); + + let req = TestRequest::with_header( + header::USER_AGENT, + header::HeaderValue::from_static("ACTIX-WEB"), + ) + .to_srv_request(); + let _res = srv.call(req).await.unwrap(); + } + #[actix_rt::test] async fn test_url_path() { let mut format = Format::new("%T %U");