diff --git a/integration/hurlfmt/tests_export/filter.html b/integration/hurlfmt/tests_export/filter.html index 05b9701cf79..7d01a1b5d32 100644 --- a/integration/hurlfmt/tests_export/filter.html +++ b/integration/hurlfmt/tests_export/filter.html @@ -4,6 +4,8 @@ [Captures] count: jsonpath "$.books" count [Asserts] +jsonpath "$.data" base64Decode == hex,48656c6c6f; # base64Decode +bytes base64Encode == "SGVsbG8=" # base64Encode jsonpath "$.books" count == 12 # count certificate "Expire-Date" daysAfterNow > 15 # daysAfterNow certificate "Start-Date" daysBeforeNow < 100 # daysBeforeNow diff --git a/integration/hurlfmt/tests_export/filter.hurl b/integration/hurlfmt/tests_export/filter.hurl index 1ee475fac31..b85c325fbf1 100644 --- a/integration/hurlfmt/tests_export/filter.hurl +++ b/integration/hurlfmt/tests_export/filter.hurl @@ -4,6 +4,8 @@ HTTP 200 [Captures] count: jsonpath "$.books" count [Asserts] +jsonpath "$.data" base64Decode == hex,48656c6c6f; # base64Decode +bytes base64Encode == "SGVsbG8=" # base64Encode jsonpath "$.books" count == 12 # count certificate "Expire-Date" daysAfterNow > 15 # daysAfterNow certificate "Start-Date" daysBeforeNow < 100 # daysBeforeNow diff --git a/integration/hurlfmt/tests_export/filter.json b/integration/hurlfmt/tests_export/filter.json index 2464c1bdaa5..f55b2ae4c12 100644 --- a/integration/hurlfmt/tests_export/filter.json +++ b/integration/hurlfmt/tests_export/filter.json @@ -1 +1 @@ -{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/dummy"},"response":{"status":200,"captures":[{"name":"count","query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"count"}]}],"asserts":[{"query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"count"}],"predicate":{"type":"equal","value":12}},{"query":{"type":"certificate","expr":"Expire-Date"},"filters":[{"type":"daysAfterNow"}],"predicate":{"type":"greater","value":15}},{"query":{"type":"certificate","expr":"Start-Date"},"filters":[{"type":"daysBeforeNow"}],"predicate":{"type":"less","value":100}},{"query":{"type":"bytes"},"filters":[{"type":"decode","encoding":"iso-8859-1"}],"predicate":{"type":"equal","value":"café"}},{"query":{"type":"cookie","expr":"LSID[Expires]"},"filters":[{"type":"format","fmt":"%a, %d %b %Y %H:%M:%S"}],"predicate":{"type":"equal","value":"Wed, 13 Jan 2021 22:23:01"}},{"query":{"type":"jsonpath","expr":"$.text"},"filters":[{"type":"htmlEscape"}],"predicate":{"type":"equal","value":"a > b"}},{"query":{"type":"jsonpath","expr":"$.escaped_html[1]"},"filters":[{"type":"htmlUnescape"}],"predicate":{"type":"equal","value":"

Hello

"}},{"query":{"type":"variable","name":"books"},"filters":[{"type":"jsonpath","expr":"$[0].name"}],"predicate":{"type":"equal","value":"Dune"}},{"query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"nth","n":2}],"predicate":{"type":"equal","value":"Children of Dune"}},{"query":{"type":"body"},"filters":[{"type":"regex","expr":{"type":"regex","value":"Hello ([0-9]+)!"}}],"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$.ips"},"filters":[{"type":"replace","old_value":", ","new_value":"|"}],"predicate":{"type":"equal","value":"192.168.2.1|10.0.0.20|10.0.0.10"}},{"query":{"type":"jsonpath","expr":"$.ips"},"filters":[{"type":"split","sep":", "},{"type":"count"}],"predicate":{"type":"equal","value":3}},{"query":{"type":"header","name":"Expires"},"filters":[{"type":"toDate","fmt":"%a, %d %b %Y %H:%M:%S GMT"},{"type":"daysBeforeNow"}],"predicate":{"type":"greater","value":1000}},{"query":{"type":"jsonpath","expr":"$.pi"},"filters":[{"type":"toFloat"}],"predicate":{"type":"equal","value":3.14}},{"query":{"type":"jsonpath","expr":"$.id"},"filters":[{"type":"toInt"}],"predicate":{"type":"equal","value":123}},{"query":{"type":"jsonpath","expr":"$.encoded_url"},"filters":[{"type":"urlDecode"}],"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"jsonpath","expr":"$.url"},"filters":[{"type":"urlEncode"}],"predicate":{"type":"equal","value":"https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"}},{"query":{"type":"bytes"},"filters":[{"type":"decode","encoding":"iso-8859-1"},{"type":"xpath","expr":"string(//p)"}],"predicate":{"type":"equal","value":"Hello"}}]}}]} +{"entries":[{"request":{"method":"GET","url":"http://localhost:8000/dummy"},"response":{"status":200,"captures":[{"name":"count","query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"count"}]}],"asserts":[{"query":{"type":"jsonpath","expr":"$.data"},"filters":[{"type":"base64Decode"}],"predicate":{"type":"equal","value":"SGVsbG8=","encoding":"base64"}},{"query":{"type":"bytes"},"filters":[{"type":"base64Encode"}],"predicate":{"type":"equal","value":"SGVsbG8="}},{"query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"count"}],"predicate":{"type":"equal","value":12}},{"query":{"type":"certificate","expr":"Expire-Date"},"filters":[{"type":"daysAfterNow"}],"predicate":{"type":"greater","value":15}},{"query":{"type":"certificate","expr":"Start-Date"},"filters":[{"type":"daysBeforeNow"}],"predicate":{"type":"less","value":100}},{"query":{"type":"bytes"},"filters":[{"type":"decode","encoding":"iso-8859-1"}],"predicate":{"type":"equal","value":"café"}},{"query":{"type":"cookie","expr":"LSID[Expires]"},"filters":[{"type":"format","fmt":"%a, %d %b %Y %H:%M:%S"}],"predicate":{"type":"equal","value":"Wed, 13 Jan 2021 22:23:01"}},{"query":{"type":"jsonpath","expr":"$.text"},"filters":[{"type":"htmlEscape"}],"predicate":{"type":"equal","value":"a > b"}},{"query":{"type":"jsonpath","expr":"$.escaped_html[1]"},"filters":[{"type":"htmlUnescape"}],"predicate":{"type":"equal","value":"

Hello

"}},{"query":{"type":"variable","name":"books"},"filters":[{"type":"jsonpath","expr":"$[0].name"}],"predicate":{"type":"equal","value":"Dune"}},{"query":{"type":"jsonpath","expr":"$.books"},"filters":[{"type":"nth","n":2}],"predicate":{"type":"equal","value":"Children of Dune"}},{"query":{"type":"body"},"filters":[{"type":"regex","expr":{"type":"regex","value":"Hello ([0-9]+)!"}}],"predicate":{"type":"equal","value":"Bob"}},{"query":{"type":"jsonpath","expr":"$.ips"},"filters":[{"type":"replace","old_value":", ","new_value":"|"}],"predicate":{"type":"equal","value":"192.168.2.1|10.0.0.20|10.0.0.10"}},{"query":{"type":"jsonpath","expr":"$.ips"},"filters":[{"type":"split","sep":", "},{"type":"count"}],"predicate":{"type":"equal","value":3}},{"query":{"type":"header","name":"Expires"},"filters":[{"type":"toDate","fmt":"%a, %d %b %Y %H:%M:%S GMT"},{"type":"daysBeforeNow"}],"predicate":{"type":"greater","value":1000}},{"query":{"type":"jsonpath","expr":"$.pi"},"filters":[{"type":"toFloat"}],"predicate":{"type":"equal","value":3.14}},{"query":{"type":"jsonpath","expr":"$.id"},"filters":[{"type":"toInt"}],"predicate":{"type":"equal","value":123}},{"query":{"type":"jsonpath","expr":"$.encoded_url"},"filters":[{"type":"urlDecode"}],"predicate":{"type":"equal","value":"https://mozilla.org/?x=шеллы"}},{"query":{"type":"jsonpath","expr":"$.url"},"filters":[{"type":"urlEncode"}],"predicate":{"type":"equal","value":"https%3A//mozilla.org/%3Fx%3D%D1%88%D0%B5%D0%BB%D0%BB%D1%8B"}},{"query":{"type":"bytes"},"filters":[{"type":"decode","encoding":"iso-8859-1"},{"type":"xpath","expr":"string(//p)"}],"predicate":{"type":"equal","value":"Hello"}}]}}]} diff --git a/integration/hurlfmt/tests_export/filter.lint.hurl b/integration/hurlfmt/tests_export/filter.lint.hurl index 1ee475fac31..b85c325fbf1 100644 --- a/integration/hurlfmt/tests_export/filter.lint.hurl +++ b/integration/hurlfmt/tests_export/filter.lint.hurl @@ -4,6 +4,8 @@ HTTP 200 [Captures] count: jsonpath "$.books" count [Asserts] +jsonpath "$.data" base64Decode == hex,48656c6c6f; # base64Decode +bytes base64Encode == "SGVsbG8=" # base64Encode jsonpath "$.books" count == 12 # count certificate "Expire-Date" daysAfterNow > 15 # daysAfterNow certificate "Start-Date" daysBeforeNow < 100 # daysBeforeNow diff --git a/packages/hurl/src/runner/filter/eval.rs b/packages/hurl/src/runner/filter/eval.rs index 2a3d79864d0..d898bba1dd0 100644 --- a/packages/hurl/src/runner/filter/eval.rs +++ b/packages/hurl/src/runner/filter/eval.rs @@ -68,6 +68,8 @@ pub fn eval_filter( in_assert: bool, ) -> Result, RunnerError> { match &filter.value { + FilterValue::Base64Decode => todo!(), + FilterValue::Base64Encode => todo!(), FilterValue::Count => eval_count(value, filter.source_info, in_assert), FilterValue::DaysAfterNow => eval_days_after_now(value, filter.source_info, in_assert), FilterValue::DaysBeforeNow => eval_days_before_now(value, filter.source_info, in_assert), diff --git a/packages/hurl_core/src/ast/core.rs b/packages/hurl_core/src/ast/core.rs index efdfd7ec613..e538afc692f 100644 --- a/packages/hurl_core/src/ast/core.rs +++ b/packages/hurl_core/src/ast/core.rs @@ -955,6 +955,8 @@ pub struct Filter { #[derive(Clone, Debug, PartialEq, Eq)] pub enum FilterValue { + Base64Decode, + Base64Encode, Count, DaysAfterNow, DaysBeforeNow, diff --git a/packages/hurl_core/src/format/html.rs b/packages/hurl_core/src/format/html.rs index ff42a616180..805d4354912 100644 --- a/packages/hurl_core/src/format/html.rs +++ b/packages/hurl_core/src/format/html.rs @@ -802,6 +802,8 @@ impl HtmlFormatter { fn fmt_filter_value(&mut self, filter_value: &FilterValue) { let class = "filter-type"; match filter_value { + FilterValue::Base64Decode => self.fmt_span(class, "base64Decode"), + FilterValue::Base64Encode => self.fmt_span(class, "base64Encode"), FilterValue::Count => self.fmt_span(class, "count"), FilterValue::DaysAfterNow => self.fmt_span(class, "daysAfterNow"), FilterValue::DaysBeforeNow => self.fmt_span(class, "daysBeforeNow"), diff --git a/packages/hurl_core/src/parser/filter.rs b/packages/hurl_core/src/parser/filter.rs index a40b674adcb..bd310a3fdfe 100644 --- a/packages/hurl_core/src/parser/filter.rs +++ b/packages/hurl_core/src/parser/filter.rs @@ -53,6 +53,8 @@ pub fn filter(reader: &mut Reader) -> ParseResult { let start = reader.cursor(); let value = choice( &[ + base64_decode_filter, + base64_encode_filter, count_filter, days_after_now_filter, days_before_now_filter, @@ -92,6 +94,16 @@ pub fn filter(reader: &mut Reader) -> ParseResult { Ok(Filter { source_info, value }) } +fn base64_decode_filter(reader: &mut Reader) -> ParseResult { + try_literal("base64Decode", reader)?; + Ok(FilterValue::Base64Decode) +} + +fn base64_encode_filter(reader: &mut Reader) -> ParseResult { + try_literal("base64Encode", reader)?; + Ok(FilterValue::Base64Encode) +} + fn count_filter(reader: &mut Reader) -> ParseResult { try_literal("count", reader)?; Ok(FilterValue::Count) diff --git a/packages/hurlfmt/src/format/json.rs b/packages/hurlfmt/src/format/json.rs index 3eba4a9231d..67990d49bf8 100644 --- a/packages/hurlfmt/src/format/json.rs +++ b/packages/hurlfmt/src/format/json.rs @@ -709,6 +709,12 @@ impl ToJson for FilterValue { let mut attributes = vec![]; let att_name = "type".to_string(); match self { + FilterValue::Base64Decode => { + attributes.push((att_name, JValue::String("base64Decode".to_string()))); + } + FilterValue::Base64Encode => { + attributes.push((att_name, JValue::String("base64Encode".to_string()))); + } FilterValue::Count => { attributes.push((att_name, JValue::String("count".to_string()))); } diff --git a/packages/hurlfmt/src/format/token.rs b/packages/hurlfmt/src/format/token.rs index bd0bfa62558..1a626640d01 100644 --- a/packages/hurlfmt/src/format/token.rs +++ b/packages/hurlfmt/src/format/token.rs @@ -1079,6 +1079,8 @@ impl Tokenizable for VariableValue { impl Tokenizable for Filter { fn tokenize(&self) -> Vec { match self.value.clone() { + FilterValue::Base64Decode => vec![Token::FilterType(String::from("base64Decode"))], + FilterValue::Base64Encode => vec![Token::FilterType(String::from("base64Encode"))], FilterValue::Count => vec![Token::FilterType(String::from("count"))], FilterValue::DaysAfterNow => vec![Token::FilterType(String::from("daysAfterNow"))], FilterValue::DaysBeforeNow => vec![Token::FilterType(String::from("daysBeforeNow"))],