Skip to content

Commit 9b37150

Browse files
authored
Move response filters into Rust (#755)
1 parent 19908b1 commit 9b37150

42 files changed

Lines changed: 15538 additions & 399 deletions

File tree

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

‎Cargo.lock‎

Lines changed: 46 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

‎Cargo.toml‎

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -11,6 +11,7 @@ members = [
1111
"crates/yaak-core",
1212
"crates/yaak-common",
1313
"crates/yaak-crypto",
14+
"crates/yaak-filter",
1415
"crates/yaak-git",
1516
"crates/yaak-grpc",
1617
"crates/yaak-http",
@@ -86,6 +87,7 @@ yaak = { path = "crates/yaak" }
8687
yaak-commands = { path = "crates/yaak-commands" }
8788
yaak-common = { path = "crates/yaak-common" }
8889
yaak-crypto = { path = "crates/yaak-crypto" }
90+
yaak-filter = { path = "crates/yaak-filter" }
8991
yaak-git = { path = "crates/yaak-git" }
9092
yaak-grpc = { path = "crates/yaak-grpc" }
9193
yaak-http = { path = "crates/yaak-http" }
Lines changed: 85 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,85 @@
1+
mod common;
2+
3+
use common::http_server::TestHttpServer;
4+
use common::{cli_cmd, query_manager, seed_workspace};
5+
use predicates::str::contains;
6+
use std::fs;
7+
use tempfile::TempDir;
8+
use yaak_models::models::{HttpRequest, HttpRequestHeader};
9+
use yaak_models::util::UpdateSource;
10+
11+
/// A template function that runs `ctx.filter` and returns the host's reply as JSON.
12+
const PROBE_PLUGIN: &str = r#"exports.plugin = {
13+
templateFunctions: [{
14+
name: "filter_probe",
15+
args: [
16+
{ type: "text", name: "language" },
17+
{ type: "text", name: "text" },
18+
{ type: "text", name: "query" },
19+
],
20+
async onRender(ctx, args) {
21+
const { language, text, query } = args.values;
22+
const result = language === "xpath"
23+
? await ctx.filter.xPath(text, query)
24+
: await ctx.filter.jsonPath(text, query);
25+
return JSON.stringify(result);
26+
},
27+
}],
28+
};"#;
29+
30+
/// The plugin runtime, the CLI's plugin host, and yaak-filter, end to end: the
31+
/// rendered header values are what the host replied to the plugin.
32+
#[test]
33+
fn plugins_filter_text_through_the_host() {
34+
let temp_dir = TempDir::new().expect("Failed to create temp dir");
35+
let data_dir = temp_dir.path();
36+
37+
// Bundled plugins are extracted next to this on launch; extras are kept.
38+
let probe_dir = data_dir.join("vendored-plugins").join("filter-probe");
39+
fs::create_dir_all(probe_dir.join("build")).expect("Failed to create probe plugin dir");
40+
fs::write(probe_dir.join("package.json"), r#"{"name":"@yaak/filter-probe","version":"0.0.0"}"#)
41+
.expect("Failed to write probe package.json");
42+
fs::write(probe_dir.join("build").join("index.js"), PROBE_PLUGIN)
43+
.expect("Failed to write probe plugin");
44+
45+
seed_workspace(data_dir, "wk_test");
46+
let server = TestHttpServer::spawn_ok("ok");
47+
let header = |name: &str, value: &str| HttpRequestHeader {
48+
enabled: true,
49+
name: name.to_string(),
50+
value: value.to_string(),
51+
id: None,
52+
};
53+
let request = HttpRequest {
54+
id: "rq_filter".to_string(),
55+
workspace_id: "wk_test".to_string(),
56+
method: "GET".to_string(),
57+
url: server.url.clone(),
58+
headers: vec![
59+
header(
60+
"x-json",
61+
r#"${[ filter_probe(language='jsonpath', text='{"a":[1,2]}', query='$.a[1]') ]}"#,
62+
),
63+
header(
64+
"x-xml",
65+
"${[ filter_probe(language='xpath', text='<a><b>x</b></a>', query='//b') ]}",
66+
),
67+
header(
68+
"x-bad",
69+
"${[ filter_probe(language='jsonpath', text='{}', query='$[?(@ ==)]') ]}",
70+
),
71+
],
72+
..Default::default()
73+
};
74+
query_manager(data_dir)
75+
.with_tx(|tx| tx.upsert_http_request(&request, &UpdateSource::Sync))
76+
.expect("Failed to seed request");
77+
78+
cli_cmd(data_dir)
79+
.args(["--verbose", "request", "send", "rq_filter"])
80+
.assert()
81+
.success()
82+
.stdout(contains(r#"> x-json: {"content":"[\n 2\n]"}"#))
83+
.stdout(contains(r#"> x-xml: {"content":"<b>x</b>"}"#))
84+
.stdout(contains(r#"> x-bad: {"content":"","error":"Invalid filter: "#));
85+
}

‎crates-tauri/yaak-app-client/Cargo.toml‎

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ yaak-core = { workspace = true }
8383
yaak = { workspace = true }
8484
yaak-commands = { workspace = true }
8585
yaak-crypto = { workspace = true }
86+
yaak-filter = { workspace = true }
8687
yaak-fonts = { workspace = true }
8788
yaak-git = { workspace = true }
8889
yaak-grpc = { workspace = true }

‎crates-tauri/yaak-app-client/src/lib.rs‎

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1004,10 +1004,11 @@ async fn cmd_http_response_body<R: Runtime>(
10041004
.ok_or(GenericError("Failed to find response body".to_string()))?;
10051005

10061006
match filter {
1007-
Some(filter) if !filter.is_empty() => Ok(plugins_ext::plugin_manager(&window)
1008-
.await?
1009-
.filter_data(&window.plugin_context(), filter, &body, content_type)
1010-
.await?),
1007+
Some(filter) if !filter.is_empty() => {
1008+
let language = yaak_filter::Language::for_content_type(content_type);
1009+
let result = yaak_filter::filter(language, &body, filter);
1010+
Ok(FilterResponse { content: result.content, error: result.error })
1011+
}
10111012
_ => Ok(FilterResponse { content: body, error: None }),
10121013
}
10131014
}

‎crates/yaak-filter/Cargo.toml‎

Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
[package]
2+
name = "yaak-filter"
3+
version = "0.1.0"
4+
edition = "2024"
5+
publish = false
6+
7+
[dependencies]
8+
fancy-regex = "0.17"
9+
indexmap = "2"
10+
sxd-document = "0.3.2"
11+
sxd-xpath = "0.4.2"
12+
13+
[dev-dependencies]
14+
serde_json = { workspace = true, features = ["preserve_order"] }

0 commit comments

Comments
 (0)