From b44823c8d1e02b30b9f26af0c05be89cd9f02c9c Mon Sep 17 00:00:00 2001 From: Alex Snaps Date: Tue, 5 Nov 2024 14:48:42 -0500 Subject: [PATCH] Added second arg to skip param repeating Signed-off-by: Alex Snaps --- src/data/cel.rs | 46 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 10 deletions(-) diff --git a/src/data/cel.rs b/src/data/cel.rs index a4c0105..9ef0355 100644 --- a/src/data/cel.rs +++ b/src/data/cel.rs @@ -1,6 +1,6 @@ use crate::data::get_attribute; use crate::data::property::{host_get_map, Path}; -use cel_interpreter::extractors::This; +use cel_interpreter::extractors::{Arguments, This}; use cel_interpreter::objects::{Key, Map, ValueType}; use cel_interpreter::{Context, ExecutionError, ResolveResult, Value}; use cel_parser::{parse, Expression as CelExpression, Member, ParseError}; @@ -85,8 +85,17 @@ impl Expression { /// Decodes the query string and returns a Map where the key is the parameter's name and /// the value is either a [`Value::String`] or a [`Value::List`] if the parameter's name is repeated +/// and the second arg is set not set to `false`. /// see [`tests::decodes_query_string`] -fn decode_query_string(This(s): This>) -> ResolveResult { +fn decode_query_string(This(s): This>, Arguments(args): Arguments) -> ResolveResult { + let allow_repeats = if args.len() == 2 { + match &args[1] { + Value::Bool(b) => *b, + _ => true, + } + } else { + true + }; let mut map: HashMap = HashMap::default(); for part in s.split('&') { let mut kv = part.split('='); @@ -94,14 +103,16 @@ fn decode_query_string(This(s): This>) -> ResolveResult { let new_v: Value = decode(value).unwrap().into_owned().into(); match map.entry(decode(key).unwrap().into_owned().into()) { Entry::Occupied(mut e) => { - if let Value::List(ref mut list) = e.get_mut() { - Arc::get_mut(list) - .expect("This isn't ever shared!") - .push(new_v); - } else { - let v = e.get().clone(); - let list = Value::List([v, new_v].to_vec().into()); - e.insert(list); + if allow_repeats { + if let Value::List(ref mut list) = e.get_mut() { + Arc::get_mut(list) + .expect("This isn't ever shared!") + .push(new_v); + } else { + let v = e.get().clone(); + let list = Value::List([v, new_v].to_vec().into()); + e.insert(list); + } } } Entry::Vacant(e) => { @@ -652,6 +663,21 @@ mod tests { .expect("This is valid!"); assert!(predicate.test()); + property::test::TEST_PROPERTY_VALUE.set(Some(( + "request.query".into(), + "param1=%F0%9F%91%BE%20¶m2=Exterminate%21&%F0%9F%91%BE=123&%F0%9F%91%BE=456&%F0%9F%91%BE" + .bytes() + .collect(), + ))); + let predicate = Predicate::route_rule( + "decodeQueryString(request.query)['param1'] == '👾 ' && \ + decodeQueryString(request.query)['param2'] == 'Exterminate!' && \ + decodeQueryString(request.query, false)['👾'] == '123' \ + ", + ) + .expect("This is valid!"); + assert!(predicate.test()); + property::test::TEST_PROPERTY_VALUE.set(Some(( "request.query".into(), "%F0%9F%91%BE".bytes().collect(),