mirror of https://github.com/fafhrd91/actix-web
Merge branch 'master' into fix_accept-encoding_header_without_compress_feature
This commit is contained in:
commit
1d7019da87
|
@ -2,6 +2,9 @@
|
||||||
|
|
||||||
## Unreleased - 2020-xx-xx
|
## Unreleased - 2020-xx-xx
|
||||||
|
|
||||||
|
* Implement Logger middleware regex exclude pattern [#1723]
|
||||||
|
[#1723]: https://github.com/actix/actix-web/pull/1723
|
||||||
|
|
||||||
### Fixed
|
### Fixed
|
||||||
|
|
||||||
* awc now uses `Accept-Encoding: identity` instead of `Accept-Encoding: br` when no compression feature is enabled
|
* awc now uses `Accept-Encoding: identity` instead of `Accept-Encoding: br` when no compression feature is enabled
|
||||||
|
|
|
@ -91,7 +91,7 @@ log = "0.4"
|
||||||
mime = "0.3"
|
mime = "0.3"
|
||||||
socket2 = "0.3"
|
socket2 = "0.3"
|
||||||
pin-project = "0.4.17"
|
pin-project = "0.4.17"
|
||||||
regex = "1.3"
|
regex = "1.4"
|
||||||
serde = { version = "1.0", features = ["derive"] }
|
serde = { version = "1.0", features = ["derive"] }
|
||||||
serde_json = "1.0"
|
serde_json = "1.0"
|
||||||
serde_urlencoded = "0.6.1"
|
serde_urlencoded = "0.6.1"
|
||||||
|
|
|
@ -4,7 +4,9 @@ use std::ptr::copy_nonoverlapping;
|
||||||
use std::slice;
|
use std::slice;
|
||||||
|
|
||||||
// Holds a slice guaranteed to be shorter than 8 bytes
|
// Holds a slice guaranteed to be shorter than 8 bytes
|
||||||
struct ShortSlice<'a>(&'a mut [u8]);
|
struct ShortSlice<'a> {
|
||||||
|
inner: &'a mut [u8],
|
||||||
|
}
|
||||||
|
|
||||||
impl<'a> ShortSlice<'a> {
|
impl<'a> ShortSlice<'a> {
|
||||||
/// # Safety
|
/// # Safety
|
||||||
|
@ -12,10 +14,11 @@ impl<'a> ShortSlice<'a> {
|
||||||
unsafe fn new(slice: &'a mut [u8]) -> Self {
|
unsafe fn new(slice: &'a mut [u8]) -> Self {
|
||||||
// Sanity check for debug builds
|
// Sanity check for debug builds
|
||||||
debug_assert!(slice.len() < 8);
|
debug_assert!(slice.len() < 8);
|
||||||
ShortSlice(slice)
|
ShortSlice { inner: slice }
|
||||||
}
|
}
|
||||||
|
|
||||||
fn len(&self) -> usize {
|
fn len(&self) -> usize {
|
||||||
self.0.len()
|
self.inner.len()
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -56,7 +59,7 @@ pub(crate) fn apply_mask(buf: &mut [u8], mask_u32: u32) {
|
||||||
fn xor_short(buf: ShortSlice<'_>, mask: u64) {
|
fn xor_short(buf: ShortSlice<'_>, mask: u64) {
|
||||||
// SAFETY: we know that a `ShortSlice` fits in a u64
|
// SAFETY: we know that a `ShortSlice` fits in a u64
|
||||||
unsafe {
|
unsafe {
|
||||||
let (ptr, len) = (buf.0.as_mut_ptr(), buf.0.len());
|
let (ptr, len) = (buf.inner.as_mut_ptr(), buf.len());
|
||||||
let mut b: u64 = 0;
|
let mut b: u64 = 0;
|
||||||
#[allow(trivial_casts)]
|
#[allow(trivial_casts)]
|
||||||
copy_nonoverlapping(ptr, &mut b as *mut _ as *mut u8, len);
|
copy_nonoverlapping(ptr, &mut b as *mut _ as *mut u8, len);
|
||||||
|
@ -96,7 +99,13 @@ fn align_buf(buf: &mut [u8]) -> (ShortSlice<'_>, &mut [u64], ShortSlice<'_>) {
|
||||||
|
|
||||||
// SAFETY: we know the middle section is correctly aligned, and the outer
|
// SAFETY: we know the middle section is correctly aligned, and the outer
|
||||||
// sections are smaller than 8 bytes
|
// sections are smaller than 8 bytes
|
||||||
unsafe { (ShortSlice::new(head), cast_slice(mid), ShortSlice(tail)) }
|
unsafe {
|
||||||
|
(
|
||||||
|
ShortSlice::new(head),
|
||||||
|
cast_slice(mid),
|
||||||
|
ShortSlice::new(tail),
|
||||||
|
)
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
// We didn't cross even one aligned boundary!
|
// We didn't cross even one aligned boundary!
|
||||||
|
|
||||||
|
|
|
@ -13,7 +13,7 @@ use actix_service::{Service, Transform};
|
||||||
use bytes::Bytes;
|
use bytes::Bytes;
|
||||||
use futures_util::future::{ok, Ready};
|
use futures_util::future::{ok, Ready};
|
||||||
use log::debug;
|
use log::debug;
|
||||||
use regex::Regex;
|
use regex::{Regex, RegexSet};
|
||||||
use time::OffsetDateTime;
|
use time::OffsetDateTime;
|
||||||
|
|
||||||
use crate::dev::{BodySize, MessageBody, ResponseBody};
|
use crate::dev::{BodySize, MessageBody, ResponseBody};
|
||||||
|
@ -92,6 +92,7 @@ pub struct Logger(Rc<Inner>);
|
||||||
struct Inner {
|
struct Inner {
|
||||||
format: Format,
|
format: Format,
|
||||||
exclude: HashSet<String>,
|
exclude: HashSet<String>,
|
||||||
|
exclude_regex: RegexSet,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl Logger {
|
impl Logger {
|
||||||
|
@ -100,6 +101,7 @@ impl Logger {
|
||||||
Logger(Rc::new(Inner {
|
Logger(Rc::new(Inner {
|
||||||
format: Format::new(format),
|
format: Format::new(format),
|
||||||
exclude: HashSet::new(),
|
exclude: HashSet::new(),
|
||||||
|
exclude_regex: RegexSet::empty(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -111,6 +113,16 @@ impl Logger {
|
||||||
.insert(path.into());
|
.insert(path.into());
|
||||||
self
|
self
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Ignore and do not log access info for paths that match regex
|
||||||
|
pub fn exclude_regex<T: Into<String>>(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 {
|
impl Default for Logger {
|
||||||
|
@ -123,6 +135,7 @@ impl Default for Logger {
|
||||||
Logger(Rc::new(Inner {
|
Logger(Rc::new(Inner {
|
||||||
format: Format::default(),
|
format: Format::default(),
|
||||||
exclude: HashSet::new(),
|
exclude: HashSet::new(),
|
||||||
|
exclude_regex: RegexSet::empty(),
|
||||||
}))
|
}))
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -168,7 +181,9 @@ where
|
||||||
}
|
}
|
||||||
|
|
||||||
fn call(&mut self, req: ServiceRequest) -> Self::Future {
|
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 {
|
LoggerResponse {
|
||||||
fut: self.service.call(req),
|
fut: self.service.call(req),
|
||||||
format: None,
|
format: None,
|
||||||
|
@ -538,6 +553,28 @@ mod tests {
|
||||||
let _res = srv.call(req).await;
|
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]
|
#[actix_rt::test]
|
||||||
async fn test_url_path() {
|
async fn test_url_path() {
|
||||||
let mut format = Format::new("%T %U");
|
let mut format = Format::new("%T %U");
|
||||||
|
|
Loading…
Reference in New Issue