diff options
author | Guillaume Pasquet <dev@etenil.net> | 2022-02-21 00:18:38 +0000 |
---|---|---|
committer | Guillaume Pasquet <dev@etenil.net> | 2022-02-21 00:18:38 +0000 |
commit | 883b9c65fce7f8596b7da5616efab8c4ecc616a4 (patch) | |
tree | 538ec099430b9e83577b3849a509d924cd3f97ec | |
parent | f69d2801069850b48c6424b50d0107799d56e2f8 (diff) |
Added support for JQ filtering.
-rw-r--r-- | Cargo.lock | 25 | ||||
-rw-r--r-- | Cargo.toml | 1 | ||||
-rw-r--r-- | src/barbfile.rs | 46 | ||||
-rw-r--r-- | src/executor.rs | 4 | ||||
-rw-r--r-- | src/main.rs | 26 | ||||
-rw-r--r-- | test-filter.barb | 5 |
6 files changed, 80 insertions, 27 deletions
@@ -39,6 +39,7 @@ name = "barb" version = "0.1.3" dependencies = [ "clap 3.0.14", + "jq-rs", "jsonformat", "serde", "serde_json", @@ -206,6 +207,24 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" [[package]] +name = "jq-rs" +version = "0.4.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c9cfaeae42ef96b227ab787558cc7bbd5f1dfe96b4df7c63f92853017751b0e4" +dependencies = [ + "jq-sys", +] + +[[package]] +name = "jq-sys" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81b65b7e54bd2fffc8cb20cbcf19f40d3158dab5cf5b5adb1f65f9b35eba4c48" +dependencies = [ + "pkg-config", +] + +[[package]] name = "js-sys" version = "0.3.56" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -288,6 +307,12 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "d4fd5641d01c8f18a23da7b6fe29298ff4b55afcccdf78973b24cf3175fee32e" [[package]] +name = "pkg-config" +version = "0.3.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" + +[[package]] name = "proc-macro-error" version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" @@ -17,3 +17,4 @@ clap = { version = "3.0.14", features = ["derive"] } serde = "1.0.130" serde_json = "1.0.70" jsonformat = "1.2.0" +jq-rs = "0.4.1" diff --git a/src/barbfile.rs b/src/barbfile.rs index 1a17796..19a24cd 100644 --- a/src/barbfile.rs +++ b/src/barbfile.rs @@ -80,16 +80,16 @@ impl Header { } } -struct BarbHeader { +struct BarbPreamble { pub method: Method, pub url: String, pub headers: Vec<Header>, pub filter: Option<String>, } -impl BarbHeader { +impl BarbPreamble { fn new(method: Method, url: String, headers: Vec<Header>, filter: Option<String>) -> Self { - BarbHeader { + BarbPreamble { method: method, url: url, headers: headers, @@ -99,25 +99,29 @@ impl BarbHeader { } pub struct BarbFile { - header: BarbHeader, + preamble: BarbPreamble, body: Option<String>, } impl BarbFile { pub fn headers(&self) -> &Vec<Header> { - &self.header.headers + &self.preamble.headers } pub fn method(&self) -> &Method { - &self.header.method + &self.preamble.method } pub fn method_as_string(&self) -> String { - self.header.method.to_string() + self.preamble.method.to_string() } pub fn url(&self) -> &String { - &self.header.url + &self.preamble.url + } + + pub fn filter(&self) -> &Option<String> { + &self.preamble.filter } pub fn body(&self) -> &Option<String> { @@ -172,7 +176,7 @@ impl FromStr for BarbFile { let body = lines.fold(String::from(""), |acc, x| acc + x); Ok(BarbFile { - header: BarbHeader::new(method, url, headers, filter), + preamble: BarbPreamble::new(method, url, headers, filter), body: if body == "" { None } else { Some(body) }, }) } @@ -214,12 +218,12 @@ mod tests { let barbfile = BarbFile::from_str("#GET^https://blah.com/api/blah\n#Authorization: BLAH\n#|filtr\n") .unwrap(); - assert!(matches!(barbfile.header.method, Method::GET)); - assert_eq!(barbfile.header.url, "https://blah.com/api/blah"); - assert_eq!(barbfile.header.filter, Some(String::from("filtr"))); - assert_eq!(barbfile.header.headers.len(), 1); - assert_eq!(barbfile.header.headers[0].name, "Authorization"); - assert_eq!(barbfile.header.headers[0].value, "BLAH"); + assert!(matches!(barbfile.preamble.method, Method::GET)); + assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); + assert_eq!(barbfile.preamble.filter, Some(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"); assert_eq!(barbfile.body, None); } @@ -228,12 +232,12 @@ mod tests { let barbfile = BarbFile::from_str("#POST^https://blah.com/api/blah\n#Authorization: BLAH\n#|filtr\n\n{\"key\":\"value\"}\n") .unwrap(); - assert!(matches!(barbfile.header.method, Method::POST)); - assert_eq!(barbfile.header.url, "https://blah.com/api/blah"); - assert_eq!(barbfile.header.filter, Some(String::from("filtr"))); - assert_eq!(barbfile.header.headers.len(), 1); - assert_eq!(barbfile.header.headers[0].name, "Authorization"); - assert_eq!(barbfile.header.headers[0].value, "BLAH"); + assert!(matches!(barbfile.preamble.method, Method::POST)); + assert_eq!(barbfile.preamble.url, "https://blah.com/api/blah"); + assert_eq!(barbfile.preamble.filter, Some(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"); assert_eq!(barbfile.body, Some(String::from("{\"key\":\"value\"}"))) } } diff --git a/src/executor.rs b/src/executor.rs index 4930c5f..bd9767b 100644 --- a/src/executor.rs +++ b/src/executor.rs @@ -95,8 +95,8 @@ impl Executor { } } - pub fn execute(&mut self, bfile: BarbFile, print_headers: bool) -> Result<ureq::Response, String> { - self.run(&bfile, self.make_req(&bfile, print_headers)) + pub fn execute(&mut self, bfile: &BarbFile, print_headers: bool) -> Result<ureq::Response, String> { + self.run(bfile, self.make_req(&bfile, print_headers)) } } diff --git a/src/main.rs b/src/main.rs index f3891ad..a35ad7d 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,6 +1,7 @@ mod barbfile; mod executor; +use jq_rs; use jsonformat::{format_json, Indentation}; use std::slice::Iter; @@ -24,6 +25,8 @@ struct Args { body: bool, #[clap(short, long)] raw: bool, + #[clap(short, long)] + filter: Option<String>, files: Vec<String>, } @@ -48,6 +51,20 @@ impl Args { { self.files.iter() } + + pub fn jq_filter(&self) -> &Option<String> + { + &self.filter + } +} + +fn apply_filters(args: &Args, bfile: &BarbFile, body: String) -> Result<String, String> { + if let Some(filter) = args.jq_filter() { + return Ok(jq_rs::run(filter.as_str(), body.as_str()).map_err(|x| x.to_string())?); + } else if let Some(filter) = bfile.filter() { + return Ok(jq_rs::run(filter.as_str(), body.as_str()).map_err(|x| x.to_string())?); + } + Ok(String::from(body)) } fn run_file(args: &Args, executor: &mut Executor, file_name: &String) -> Result<(), String> { @@ -56,7 +73,7 @@ fn run_file(args: &Args, executor: &mut Executor, file_name: &String) -> Result< .map_err(|_| format!("Failed to read file '{}'", file_name))? .as_str(), ).map_err(|_| format!("Failed to parse file '{}'", file_name))?; - let response = executor.execute(bfile, args.req_headers())?; + let response = executor.execute(&bfile, args.req_headers())?; if args.print_headers() { println!("{} {}", response.status(), response.status_text()); @@ -71,12 +88,13 @@ fn run_file(args: &Args, executor: &mut Executor, file_name: &String) -> Result< } if args.print_body() { + let body = apply_filters(args, &bfile, response.into_string().unwrap())?; println!( "{}", match args.raw_body() { - true => String::from(response.into_string().unwrap().as_str()), + true => body, false => format_json( - response.into_string().unwrap().as_str(), + body.as_str(), Indentation::Default ), } @@ -92,7 +110,7 @@ fn main() { let mut executor = Executor::new(Context::new(env::vars())); for file in args.files_iter() { - match run_file(&args, &mut executor, &file) { + match run_file(&args, &mut executor, file) { Ok(()) => (), Err(err) => println!("{}", err) } diff --git a/test-filter.barb b/test-filter.barb new file mode 100644 index 0000000..28a9955 --- /dev/null +++ b/test-filter.barb @@ -0,0 +1,5 @@ +#GET^https://catfact.ninja/fact +#Foo: Bar +#Baz: {TERM} +#|.fact + |