Skip to content

Commit 2cfe6df

Browse files
committed
exclude methods in agent
1 parent c23bc54 commit 2cfe6df

File tree

6 files changed

+62
-2
lines changed

6 files changed

+62
-2
lines changed

src/api/rule.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -282,6 +282,7 @@ impl Rule {
282282
pub fn into_route(self, config: &RouterConfig) -> Route<Rule> {
283283
Route::new(
284284
self.source.methods.clone(),
285+
self.source.exclude_methods,
285286
self.source.scheme.clone(),
286287
self.host(config.ignore_host_case),
287288
self.path_and_query(config.ignore_path_and_query_case),

src/build.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -119,6 +119,8 @@ struct Source {
119119
headers: Option<Vec<SourceHeader>>,
120120
#[serde(skip_serializing_if = "Option::is_none")]
121121
methods: Option<Vec<String>>,
122+
#[serde(skip_serializing_if = "Option::is_none")]
123+
exclude_methods: Option<bool>,
122124
#[serde(skip_serializing_if = "Vec::is_empty", default, with = "serde_yaml::with::singleton_map_recursive")]
123125
ips: Vec<IpConstraint>,
124126
#[serde(skip_serializing_if = "Option::is_none")]
@@ -130,6 +132,8 @@ struct Source {
130132
#[serde(skip_serializing_if = "Option::is_none")]
131133
response_status_codes: Option<Vec<u16>>,
132134
#[serde(skip_serializing_if = "Option::is_none")]
135+
exclude_response_status_codes: Option<bool>,
136+
#[serde(skip_serializing_if = "Option::is_none")]
133137
sampling: Option<u32>,
134138
}
135139

src/router/request_matcher/method.rs

Lines changed: 50 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@ use std::collections::HashMap;
77
#[derive(Debug, Clone)]
88
pub struct MethodMatcher<T: RouteData> {
99
methods: HashMap<String, Box<dyn RequestMatcher<T>>>,
10+
exclude_methods: HashMap<Vec<String>, Box<dyn RequestMatcher<T>>>,
1011
any_method: Box<dyn RequestMatcher<T>>,
1112
count: usize,
1213
}
@@ -21,6 +22,14 @@ impl<T: RouteData> RequestMatcher<T> for MethodMatcher<T> {
2122
if methods.is_empty() {
2223
self.any_method.insert(route);
2324
} else {
25+
if route.exclude_methods().is_some() {
26+
self.exclude_methods
27+
.entry(methods.clone())
28+
.or_insert_with(|| MethodMatcher::create_sub_matcher())
29+
.insert(route.clone());
30+
31+
return;
32+
}
2433
for method in methods {
2534
if !self.methods.contains_key(method) {
2635
self.methods.insert(method.to_string(), MethodMatcher::create_sub_matcher());
@@ -48,6 +57,12 @@ impl<T: RouteData> RequestMatcher<T> for MethodMatcher<T> {
4857
matcher.len() > 0
4958
});
5059

60+
self.exclude_methods.retain(|_, matcher| {
61+
removed = removed || matcher.remove(id);
62+
63+
matcher.len() > 0
64+
});
65+
5166
if removed {
5267
self.count -= 1;
5368
}
@@ -62,13 +77,47 @@ impl<T: RouteData> RequestMatcher<T> for MethodMatcher<T> {
6277
routes.extend(matcher.match_request(request));
6378
}
6479

80+
for (methods, matcher) in &self.exclude_methods {
81+
if !methods.contains(&request.method().into()) {
82+
routes.extend(matcher.match_request(request));
83+
}
84+
}
85+
6586
routes
6687
}
6788

6889
fn trace(&self, request: &Request) -> Vec<Trace<T>> {
6990
let mut traces = self.any_method.trace(request);
7091
let request_method = request.method();
7192

93+
for (methods, matcher) in &self.exclude_methods {
94+
if !methods.contains(&request_method.into()) {
95+
let method_traces = matcher.trace(request);
96+
97+
traces.push(Trace::new(
98+
true,
99+
true,
100+
matcher.len() as u64,
101+
method_traces,
102+
TraceInfo::ExcludeMethods {
103+
request: request_method.to_string(),
104+
against: Some(methods.clone()),
105+
},
106+
));
107+
} else {
108+
traces.push(Trace::new(
109+
false,
110+
false,
111+
matcher.len() as u64,
112+
Vec::new(),
113+
TraceInfo::ExcludeMethods {
114+
request: request_method.to_string(),
115+
against: Some(methods.clone()),
116+
},
117+
));
118+
}
119+
}
120+
72121
for (method, matcher) in &self.methods {
73122
if method == request_method {
74123
let method_traces = matcher.trace(request);
@@ -140,6 +189,7 @@ impl<T: RouteData> Default for MethodMatcher<T> {
140189
fn default() -> Self {
141190
MethodMatcher {
142191
methods: HashMap::new(),
192+
exclude_methods: HashMap::new(),
143193
any_method: MethodMatcher::create_sub_matcher(),
144194
count: 0,
145195
}

src/router/route.rs

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@ impl<T: RouteData> Route<T> {
3333
#[allow(clippy::too_many_arguments)]
3434
pub fn new(
3535
methods: Option<Vec<String>>,
36+
exclude_methods: Option<bool>,
3637
scheme: Option<String>,
3738
host: Option<StaticOrDynamic>,
3839
path_and_query: StaticOrDynamic,
@@ -50,6 +51,7 @@ impl<T: RouteData> Route<T> {
5051
scheme,
5152
host,
5253
methods,
54+
exclude_methods,
5355
path_and_query,
5456
headers,
5557
ips,
@@ -81,6 +83,8 @@ impl<T: RouteData> Route<T> {
8183
self.methods.as_ref()
8284
}
8385

86+
pub fn exclude_methods(&self) -> Option<bool> { self.exclude_methods }
87+
8488
pub fn priority(&self) -> i64 {
8589
self.priority
8690
}

src/router/trace.rs

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ pub enum TraceInfo<T: RouteData> {
2929
Ip { request: String, against: String },
3030
DateTimeGroup { conditions: Vec<TraceInfoDateTimeCondition> },
3131
Method { request: String, against: Option<String> },
32+
ExcludeMethods { request: String, against: Option<Vec<String>> },
3233
HeaderGroup { conditions: Vec<TraceInfoHeaderCondition> },
3334
PathAndQueryStatic { request: String },
3435
PathAndQueryRegex,

tests/redirectionio_router_test.rs

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9231,7 +9231,7 @@ fn setup_rule_methods_trigger() -> Router<Rule> {
92319231
let config: RouterConfig = serde_json::from_str(r#"{"always_match_any_host":false,"ignore_header_case":false,"ignore_host_case":false,"ignore_marketing_query_params":true,"ignore_path_and_query_case":false,"marketing_query_params":["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],"pass_marketing_query_params_to_target":true}"#).expect("cannot deserialize");
92329232
let mut router = Router::<Rule>::from_config(config);
92339233

9234-
let route_1: Rule = serde_json::from_str(r#"{"id":"rule-exclude-methods","rank":0,"source":{"methods":["GET","POST"],"path":"/exclude-methods"},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");
9234+
let route_1: Rule = serde_json::from_str(r#"{"id":"rule-exclude-methods","rank":0,"source":{"exclude_methods":true,"methods":["GET","POST"],"path":"/exclude-methods"},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");
92359235
router.insert(route_1.into_route(&router.config));
92369236

92379237
let route_2: Rule = serde_json::from_str(r#"{"id":"rule-include-methods","rank":0,"source":{"methods":["GET","POST"],"path":"/include-methods"},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");
@@ -9778,7 +9778,7 @@ fn setup_rule_response_status_codes_trigger() -> Router<Rule> {
97789778
let config: RouterConfig = serde_json::from_str(r#"{"always_match_any_host":false,"ignore_header_case":false,"ignore_host_case":false,"ignore_marketing_query_params":true,"ignore_path_and_query_case":false,"marketing_query_params":["utm_source","utm_medium","utm_campaign","utm_term","utm_content"],"pass_marketing_query_params_to_target":true}"#).expect("cannot deserialize");
97799779
let mut router = Router::<Rule>::from_config(config);
97809780

9781-
let route_1: Rule = serde_json::from_str(r#"{"id":"rule-exclude-status-codes","rank":0,"source":{"path":"/exclude-status-codes","response_status_codes":[200,201]},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");
9781+
let route_1: Rule = serde_json::from_str(r#"{"id":"rule-exclude-status-codes","rank":0,"source":{"exclude_response_status_codes":true,"path":"/exclude-status-codes","response_status_codes":[200,201]},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");
97829782
router.insert(route_1.into_route(&router.config));
97839783

97849784
let route_2: Rule = serde_json::from_str(r#"{"id":"rule-include-status-codes","rank":0,"source":{"path":"/include-status-codes","response_status_codes":[200,201]},"status_code":302,"target":"/bar"}"#).expect("cannot deserialize");

0 commit comments

Comments
 (0)