diff options
| author | Guillaume Pasquet <dev@etenil.net> | 2022-03-03 23:18:08 +0000 | 
|---|---|---|
| committer | Guillaume Pasquet <dev@etenil.net> | 2022-03-03 23:18:08 +0000 | 
| commit | 57af17cfa6e08a6fe9bf6d73d401af17dccfa3bb (patch) | |
| tree | cd550ccf0eb78f360e6813ffdfd3c89d817eb21f /src | |
| parent | f797f10c2eda28a221759fc26ddf483f41232604 (diff) | |
Introduce JSONPath and potentially break old stuff.
Diffstat (limited to 'src')
| -rw-r--r-- | src/barbfile.rs | 76 | ||||
| -rw-r--r-- | src/executor.rs | 8 | ||||
| -rw-r--r-- | src/main.rs | 3 | 
3 files changed, 70 insertions, 17 deletions
diff --git a/src/barbfile.rs b/src/barbfile.rs index 91ffd0a..f3cb58f 100644 --- a/src/barbfile.rs +++ b/src/barbfile.rs @@ -2,6 +2,11 @@ use regex::Regex;  use std::str::FromStr;  use std::string::ToString;  use std::{error::Error, fmt}; + +use jsonpath_rust::JsonPathQuery; +use serde_json::{json, Value}; + +#[cfg(feature = "jq")]  use jq_rs;  #[derive(Debug)] @@ -86,16 +91,22 @@ impl Header {      }  } +enum FilterType { +    JQ, +    PATH, +} +  pub struct BarbFilter {      name: Option<String>,      filter: String, +    filter_type: FilterType,  }  impl FromStr for BarbFilter {      type Err = BarbParseError;      fn from_str(s: &str) -> Result<Self, Self::Err> { -        let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)\\|(?P<filter>.+)$").unwrap(); +        let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)(?P<type>[|$])(?P<filter>.+)$").unwrap();          let groups = re.captures(s).ok_or(BarbParseError {})?;          Ok(BarbFilter::new( @@ -104,20 +115,36 @@ impl FromStr for BarbFilter {                  any => Some(String::from(any)),              },              String::from(&groups["filter"]), +            match &groups["type"] { +                "|" => FilterType::JQ, +                _ => FilterType::PATH, +            },          ))      }  }  impl PreambleLine for BarbFilter {      fn is_match(s: String) -> bool { -        let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)\\|(?P<filter>.+)$").unwrap(); +        let re = Regex::new("^#(?P<name>[A-Za-z0-9_]*)[|$](?P<filter>.+)$").unwrap();          re.is_match(s.as_str())      }  }  impl BarbFilter { -    pub fn new(name: Option<String>, filter: String) -> BarbFilter { -        BarbFilter { name, filter } +    fn new(name: Option<String>, filter: String, filter_type: FilterType) -> BarbFilter { +        BarbFilter { +            name, +            filter, +            filter_type, +        } +    } + +    pub fn from_path(filter: String) -> BarbFilter { +        BarbFilter { +            name: None, +            filter_type: FilterType::PATH, +            filter, +        }      }      pub fn name(&self) -> &Option<String> { @@ -128,11 +155,38 @@ impl BarbFilter {          &self.filter      } -    pub fn apply(&self, body: &String) -> Result<String, String> { +    #[cfg(feature = "jq")] +    fn apply_jq(&self, body: &String) -> Result<String, String> {          jq_rs::run(self.filter.as_str(), body.as_str())              .map_err(|x| x.to_string())              .map(|x| String::from(x.trim().trim_matches('"')))      } + +    fn apply_path(&self, body: &String) -> Result<String, String> { +        let json: Value = serde_json::from_str(body.as_str()) +            .map_err(|_| String::from("Failed to decode body"))?; +        let path = &json.path(self.filter.as_str())?; +        Ok(match path { +            Value::Array(val) => match val.len() { +                1 => val.first().unwrap(), +                _ => path, +            }, +            _ => path, +        } +        .to_string() +        .trim() +        .trim_matches('"') +        .to_string()) +    } + +    pub fn apply(&self, body: &String) -> Result<String, String> { +        match self.filter_type { +            #[cfg(feature = "jq")] +            FilterType::JQ => self.apply_jq(body), +            FilterType::PATH => self.apply_path(body), +            _ => Ok(body.to_string()), +        } +    }  }  struct BarbPreamble { @@ -225,7 +279,7 @@ impl FromStr for BarbFile {              if BarbFilter::is_match(String::from(line)) {                  match BarbFilter::from_str(line) {                      Ok(filter) => filters.push(filter), -                    Err(_) => () +                    Err(_) => (),                  };              }          } @@ -277,7 +331,10 @@ mod tests {                  .unwrap();          assert!(matches!(barbfile.preamble.method, Method::GET));          assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); -        assert_eq!(barbfile.preamble.filters[0].filter(), &String::from("filtr")); +        assert_eq!( +            barbfile.preamble.filters[0].filter(), +            &String::from("filtr") +        );          assert_eq!(barbfile.preamble.headers.len(), 1);          assert_eq!(barbfile.preamble.headers[0].name, "Authorization");          assert_eq!(barbfile.preamble.headers[0].value, "BLAH"); @@ -291,7 +348,10 @@ mod tests {                  .unwrap();          assert!(matches!(barbfile.preamble.method, Method::POST));          assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); -        assert_eq!(barbfile.preamble.filters[0].filter(), &String::from("filtr")); +        assert_eq!( +            barbfile.preamble.filters[0].filter(), +            &String::from("filtr") +        );          assert_eq!(barbfile.preamble.headers.len(), 1);          assert_eq!(barbfile.preamble.headers[0].name, "Authorization");          assert_eq!(barbfile.preamble.headers[0].value, "BLAH"); diff --git a/src/executor.rs b/src/executor.rs index 15704c2..eccab39 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -89,7 +89,7 @@ impl Executor {          arg_filter: &Option<String>,      ) -> Result<String, String> {          if let Some(filter) = arg_filter { -            return Ok(BarbFilter::new(None, filter.to_string()).apply(&body)?); +            return Ok(BarbFilter::from_path(filter.to_string()).apply(&body)?);          } else if bfile.filters().len() > 0 {              let mut end_body: String = body.clone();              for filter in bfile.filters().iter() { @@ -144,11 +144,7 @@ impl Executor {          }          output.end_resp_hdr(); -        output.body(self.apply_filters( -            &bfile, -            response.into_string().unwrap(), -            filter, -        )?); +        output.body(self.apply_filters(&bfile, response.into_string().unwrap(), filter)?);          Ok(())      } diff --git a/src/main.rs b/src/main.rs index 2973b27..1738391 100644 --- a/src/main.rs +++ b/src/main.rs @@ -27,8 +27,6 @@ struct Args {      #[clap(short, long)]      filter: Option<String>,      #[clap(short, long)] -    path: Option<String>, -    #[clap(short, long)]      no_color: bool,      files: Vec<String>,  } @@ -62,7 +60,6 @@ fn main() {      for file in args.files_iter() {          match executor.execute(file, &output, args.jq_filter()) { -        //match run_file(&args, &mut executor, file) {              Ok(()) => (),              Err(err) => println!("{}", err),          }  | 
