diff --git a/plugins/wasm-rust/Cargo.lock b/plugins/wasm-rust/Cargo.lock index 9cf5140c77..63272f9a61 100644 --- a/plugins/wasm-rust/Cargo.lock +++ b/plugins/wasm-rust/Cargo.lock @@ -20,11 +20,23 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cfg-if" @@ -32,6 +44,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -44,6 +66,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -74,6 +105,7 @@ dependencies = [ "lazy_static", "multimap", "proxy-wasm", + "redis", "serde", "serde_json", "uuid", @@ -90,6 +122,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "1.0.11" @@ -104,9 +146,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -129,12 +171,46 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "proc-macro2" version = "1.0.88" @@ -147,7 +223,7 @@ dependencies = [ [[package]] name = "proxy-wasm" version = "0.2.2" -source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#6735737fad486c8a7cc324241f58df4a160e7887" +source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#8c902102091698bec953471c850bdf9799bc344d" dependencies = [ "downcast-rs", "hashbrown", @@ -163,6 +239,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redis" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +dependencies = [ + "arc-swap", + "combine", + "itoa", + "num-bigint", + "percent-encoding", + "ryu", + "url", +] + [[package]] name = "ryu" version = "1.0.18" @@ -171,18 +262,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -191,9 +282,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -203,21 +294,62 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.11.0" diff --git a/plugins/wasm-rust/Cargo.toml b/plugins/wasm-rust/Cargo.toml index e4fc274311..f58f2c8069 100644 --- a/plugins/wasm-rust/Cargo.toml +++ b/plugins/wasm-rust/Cargo.toml @@ -14,3 +14,4 @@ multimap = "0" http = "1" lazy_static = "1" downcast-rs="1" +redis={version = "0", default-features = false} diff --git a/plugins/wasm-rust/example/sse-timing/src/lib.rs b/plugins/wasm-rust/example/sse-timing/src/lib.rs index ab1fa4f6c4..fbff5daf9e 100644 --- a/plugins/wasm-rust/example/sse-timing/src/lib.rs +++ b/plugins/wasm-rust/example/sse-timing/src/lib.rs @@ -60,10 +60,10 @@ impl SseTimingRoot { impl Context for SseTimingRoot {} impl RootContext for SseTimingRoot { - fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { + fn on_configure(&mut self, plugin_configuration_size: usize) -> bool { on_configure( self, - _plugin_configuration_size, + plugin_configuration_size, self.rule_matcher.borrow_mut().deref_mut(), &self.log, ) diff --git a/plugins/wasm-rust/extensions/ai-data-masking/Cargo.lock b/plugins/wasm-rust/extensions/ai-data-masking/Cargo.lock index 914d5b9689..e635ae454f 100644 --- a/plugins/wasm-rust/extensions/ai-data-masking/Cargo.lock +++ b/plugins/wasm-rust/extensions/ai-data-masking/Cargo.lock @@ -46,6 +46,18 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bit-set" version = "0.5.3" @@ -84,15 +96,15 @@ checksum = "1fd0f2584146f6f2ef48085050886acf353beff7305ebd1ae69500e27c67f64b" [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cc" -version = "1.1.30" +version = "1.1.31" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "b16803a61b81d9eabb7eae2588776c4c1e584b738ede45fdbb4c972cec1e9945" +checksum = "c2e7962b54006dcfcc61cb72735f4d89bb97061dd6a7ed882ec6b8ee53714c6f" dependencies = [ "shlex", ] @@ -112,6 +124,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "cpufeatures" version = "0.2.14" @@ -230,6 +252,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "fxhash" version = "0.2.1" @@ -295,6 +326,7 @@ dependencies = [ "lazy_static", "multimap", "proxy-wasm", + "redis", "serde", "serde_json", "uuid", @@ -317,6 +349,16 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b9e0384b61958566e926dc50660321d12159025e767c18e043daf26b70104c39" +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "1.0.11" @@ -359,9 +401,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -390,6 +432,34 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.20.2" @@ -418,6 +488,12 @@ dependencies = [ "pkg-config", ] +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "pest" version = "2.7.14" @@ -519,7 +595,7 @@ dependencies = [ [[package]] name = "proxy-wasm" version = "0.2.2" -source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#6735737fad486c8a7cc324241f58df4a160e7887" +source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#8c902102091698bec953471c850bdf9799bc344d" dependencies = [ "downcast-rs", "hashbrown", @@ -550,6 +626,21 @@ version = "0.6.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "ec0be4795e2f6a28069bec0b5ff3e2ac9bafc99e6a9a7dc3547996c5c816922c" +[[package]] +name = "redis" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +dependencies = [ + "arc-swap", + "combine", + "itoa", + "num-bigint", + "percent-encoding", + "ryu", + "url", +] + [[package]] name = "regex" version = "1.11.0" @@ -630,18 +721,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -650,9 +741,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -697,9 +788,9 @@ checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", @@ -726,6 +817,21 @@ dependencies = [ "syn", ] +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + [[package]] name = "typenum" version = "1.17.0" @@ -738,12 +844,38 @@ version = "0.1.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "2896d95c02a80c6d6a5d6e953d479f5ddf2dfdb6a244441010e373ac0fb88971" +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.11.0" diff --git a/plugins/wasm-rust/extensions/ai-data-masking/src/lib.rs b/plugins/wasm-rust/extensions/ai-data-masking/src/lib.rs index 89c0da5219..2f2999d673 100644 --- a/plugins/wasm-rust/extensions/ai-data-masking/src/lib.rs +++ b/plugins/wasm-rust/extensions/ai-data-masking/src/lib.rs @@ -97,13 +97,13 @@ where D: Deserializer<'de>, { let value: Value = Deserialize::deserialize(deserializer)?; - if let Some(_type) = value.as_str() { - if _type == "replace" { + if let Some(t) = value.as_str() { + if t == "replace" { Ok(Type::Replace) - } else if _type == "hash" { + } else if t == "hash" { Ok(Type::Hash) } else { - Err(Error::custom(format!("regexp error value {}", _type))) + Err(Error::custom(format!("regexp error value {}", t))) } } else { Err(Error::custom("type error not string".to_string())) @@ -238,8 +238,8 @@ impl DenyWord { let mut deny_word = DenyWord::empty(); for word in words { - let _w = word.into(); - let w = _w.trim(); + let word_s = word.into(); + let w = word_s.trim(); if w.is_empty() { continue; } @@ -314,12 +314,12 @@ impl System { fn grok_to_pattern(&self, pattern: &str) -> (String, bool) { let mut ok = true; let mut ret = pattern.to_string(); - for _c in self.grok_regex.captures_iter(pattern) { - if _c.is_err() { + for capture in self.grok_regex.captures_iter(pattern) { + if capture.is_err() { ok = false; continue; } - let c = _c.unwrap(); + let c = capture.unwrap(); if let (Some(full), Some(name)) = (c.get(0), c.name("pattern")) { if let Some(p) = self.grok_patterns.get(name.as_str()) { if let Some(alias) = c.name("alias") { @@ -347,16 +347,16 @@ impl AiDataMaskingRoot { impl Context for AiDataMaskingRoot {} impl RootContext for AiDataMaskingRoot { - fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { + fn on_configure(&mut self, plugin_configuration_size: usize) -> bool { on_configure( self, - _plugin_configuration_size, + plugin_configuration_size, self.rule_matcher.borrow_mut().deref_mut(), &self.log, ) } - fn create_http_context(&self, _context_id: u32) -> Option> { - self.create_http_context_use_wrapper(_context_id) + fn create_http_context(&self, context_id: u32) -> Option> { + self.create_http_context_use_wrapper(context_id) } fn get_type(&self) -> Option { Some(ContextType::HttpContext) @@ -491,11 +491,11 @@ impl AiDataMasking { if rule.type_ == Type::Replace && !rule.restore { msg = rule.regex.replace_all(&msg, &rule.value).to_string(); } else { - for _m in rule.regex.find_iter(&msg) { - if _m.is_err() { + for mc in rule.regex.find_iter(&msg) { + if mc.is_err() { continue; } - let m = _m.unwrap(); + let m = mc.unwrap(); let from_word = m.as_str(); let to_word = match rule.type_ { diff --git a/plugins/wasm-rust/extensions/demo-wasm/Cargo.lock b/plugins/wasm-rust/extensions/demo-wasm/Cargo.lock index c1e197caf6..1c6c135617 100644 --- a/plugins/wasm-rust/extensions/demo-wasm/Cargo.lock +++ b/plugins/wasm-rust/extensions/demo-wasm/Cargo.lock @@ -20,11 +20,23 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cfg-if" @@ -32,6 +44,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "demo-wasm" version = "0.1.0" @@ -40,7 +62,9 @@ dependencies = [ "http", "multimap", "proxy-wasm", + "redis", "serde", + "serde_json", ] [[package]] @@ -55,6 +79,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -85,6 +118,7 @@ dependencies = [ "lazy_static", "multimap", "proxy-wasm", + "redis", "serde", "serde_json", "uuid", @@ -101,6 +135,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "1.0.11" @@ -115,9 +159,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -140,12 +184,46 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "proc-macro2" version = "1.0.88" @@ -158,7 +236,7 @@ dependencies = [ [[package]] name = "proxy-wasm" version = "0.2.2" -source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#6735737fad486c8a7cc324241f58df4a160e7887" +source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#8c902102091698bec953471c850bdf9799bc344d" dependencies = [ "downcast-rs", "hashbrown", @@ -174,6 +252,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redis" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +dependencies = [ + "arc-swap", + "combine", + "itoa", + "num-bigint", + "percent-encoding", + "ryu", + "url", +] + [[package]] name = "ryu" version = "1.0.18" @@ -182,18 +275,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -202,9 +295,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -214,21 +307,62 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.11.0" diff --git a/plugins/wasm-rust/extensions/demo-wasm/Cargo.toml b/plugins/wasm-rust/extensions/demo-wasm/Cargo.toml index a517c2b531..3f1e3fd864 100644 --- a/plugins/wasm-rust/extensions/demo-wasm/Cargo.toml +++ b/plugins/wasm-rust/extensions/demo-wasm/Cargo.toml @@ -11,5 +11,7 @@ crate-type = ["cdylib"] higress-wasm-rust = { path = "../../", version = "0.1.0" } proxy-wasm = { git="https://github.com/higress-group/proxy-wasm-rust-sdk", branch="main", version="0.2.2" } serde = { version = "1.0", features = ["derive"] } +serde_json = "1.0" multimap = "*" -http = "*" \ No newline at end of file +http = "*" +redis={version = "0", default-features = false} \ No newline at end of file diff --git a/plugins/wasm-rust/extensions/demo-wasm/src/lib.rs b/plugins/wasm-rust/extensions/demo-wasm/src/lib.rs index 62dfa055d0..ed432e69ad 100644 --- a/plugins/wasm-rust/extensions/demo-wasm/src/lib.rs +++ b/plugins/wasm-rust/extensions/demo-wasm/src/lib.rs @@ -1,13 +1,16 @@ -use higress_wasm_rust::cluster_wrapper::DnsCluster; +use higress_wasm_rust::cluster_wrapper::{DnsCluster, StaticIpCluster}; use higress_wasm_rust::log::Log; use higress_wasm_rust::plugin_wrapper::{HttpContextWrapper, RootContextWrapper}; +use higress_wasm_rust::redis_wrapper::{RedisClient, RedisClientBuilder, RedisClientConfig}; use higress_wasm_rust::rule_matcher::{on_configure, RuleMatcher, SharedRuleMatcher}; use http::Method; use multimap::MultiMap; use proxy_wasm::traits::{Context, HttpContext, RootContext}; use proxy_wasm::types::{Bytes, ContextType, DataAction, HeaderAction, LogLevel}; +use redis::Value; use serde::Deserialize; +use serde_json::json; use std::cell::RefCell; use std::ops::DerefMut; use std::rc::{Rc, Weak}; @@ -24,6 +27,8 @@ const PLUGIN_NAME: &str = "demo-wasm"; struct DemoWasmConfig { // 配置文件结构体 test: String, + #[serde(default)] + password: Option, } fn format_body(body: Option>) -> String { @@ -40,6 +45,8 @@ struct DemoWasm { log: Log, config: Option>, weak: Weak>>>, + redis_client: Option, + cid: i64, } impl Context for DemoWasm {} @@ -58,7 +65,7 @@ impl HttpContextWrapper for DemoWasm { fn on_config(&mut self, config: Rc) { // 获取config self.log.info(&format!("on_config {}", config.test)); - self.config = Some(config.clone()) + self.config = Some(config.clone()); } fn on_http_request_complete_headers( &mut self, @@ -67,6 +74,55 @@ impl HttpContextWrapper for DemoWasm { // 请求header获取完成回调 self.log .info(&format!("on_http_request_complete_headers {:?}", headers)); + if let Some(config) = &self.config { + let _redis_client = RedisClientBuilder::new( + &StaticIpCluster::new("redis", 80, ""), + Duration::from_secs(5), + ) + .password(config.password.as_ref()) + .build(); + + let redis_client = RedisClient::new( + RedisClientConfig::new( + &StaticIpCluster::new("redis", 80, ""), + Duration::from_secs(5), + ) + .password(config.password.as_ref()), + ); + + if let Some(self_rc) = self.weak.upgrade() { + let init_res = redis_client.init(); + self.log.info(&format!("redis init {:?}", init_res)); + if init_res.is_ok() { + let incr_res = redis_client.incr( + "connect", + Box::new(move |res, status, token_id| { + self_rc.borrow().log().info(&format!( + "redis incr finish value_res:{:?}, status: {}, token_id: {}", + res, status, token_id + )); + if let Some(this) = self_rc.borrow_mut().downcast_mut::() { + if let Ok(Value::Int(value)) = res { + this.cid = *value; + } + } + self_rc.borrow().resume_http_request(); + }), + ); + match incr_res { + Ok(s) => { + self.log.info(&format!("redis incr ok {}", s)); + return HeaderAction::StopAllIterationAndBuffer; + } + Err(e) => self.log.info(&format!("redis incr error {:?}", e)), + }; + } + self.redis_client = Some(redis_client); + } else { + self.log.error("self_weak upgrade error"); + } + } + HeaderAction::Continue } fn on_http_response_complete_headers( @@ -76,6 +132,38 @@ impl HttpContextWrapper for DemoWasm { // 返回header获取完成回调 self.log .info(&format!("on_http_response_complete_headers {:?}", headers)); + self.set_http_response_header("Content-Length", None); + let self_rc = match self.weak.upgrade() { + Some(rc) => rc.clone(), + None => { + self.log.error("self_weak upgrade error"); + return HeaderAction::Continue; + } + }; + if let Some(redis_client) = &self.redis_client { + match redis_client.get( + "connect", + Box::new(move |res, status, token_id| { + if let Some(this) = self_rc.borrow().downcast_ref::() { + this.log.info(&format!( + "redis get connect value_res:{:?}, status: {}, token_id: {}", + res, status, token_id + )); + this.resume_http_response(); + } else { + self_rc.borrow().resume_http_response(); + } + }), + ) { + Ok(o) => { + self.log.info(&format!("redis get ok {}", o)); + return HeaderAction::StopIteration; + } + Err(e) => { + self.log.info(&format!("redis get fail {:?}", e)); + } + } + } HeaderAction::Continue } fn cache_request_body(&self) -> bool { @@ -92,6 +180,16 @@ impl HttpContextWrapper for DemoWasm { "on_http_request_complete_body {}", String::from_utf8(req_body.clone()).unwrap_or("".to_string()) )); + DataAction::Continue + } + fn on_http_response_complete_body(&mut self, res_body: &Bytes) -> DataAction { + // 返回body获取完成回调 + let res_body_string = String::from_utf8(res_body.clone()).unwrap_or("".to_string()); + self.log.info(&format!( + "on_http_response_complete_body {}", + res_body_string + )); + let cluster = DnsCluster::new("httpbin", "httpbin.org", 80); let self_rc = match self.weak.upgrade() { @@ -101,6 +199,7 @@ impl HttpContextWrapper for DemoWasm { return DataAction::Continue; } }; + let http_call_res = self.http_call( &cluster, &Method::POST, @@ -108,34 +207,29 @@ impl HttpContextWrapper for DemoWasm { MultiMap::new(), Some("test_body".as_bytes()), Box::new(move |status_code, headers, body| { - if let Some(this) = self_rc.borrow().downcast_ref::() { + if let Some(this) = self_rc.borrow_mut().downcast_mut::() { + let body_string = format_body(body); this.log.info(&format!( "test_callback status_code:{}, headers: {:?}, body: {}", status_code, headers, - format_body(body) + body_string )); - this.resume_http_request(); + let data = json!({"redis_cid": this.cid, "http_call_body": body_string, "res_body": res_body_string}); + this.replace_http_response_body(data.to_string().as_bytes()); + this.resume_http_response(); } else { - self_rc.borrow().resume_http_request(); + self_rc.borrow().resume_http_response(); } }), Duration::from_secs(5), ); match http_call_res { - Ok(_) => DataAction::StopIterationAndBuffer, + Ok(_) => return DataAction::StopIterationAndBuffer, Err(e) => { self.log.info(&format!("http_call fail {:?}", e)); - DataAction::Continue } } - } - fn on_http_response_complete_body(&mut self, res_body: &Bytes) -> DataAction { - // 返回body获取完成回调 - self.log.info(&format!( - "on_http_response_complete_body {}", - String::from_utf8(res_body.clone()).unwrap_or("".to_string()) - )); DataAction::Continue } } @@ -147,6 +241,7 @@ impl DemoWasmRoot { fn new() -> Self { let log = Log::new(PLUGIN_NAME.to_string()); log.info("DemoWasmRoot::new"); + DemoWasmRoot { log, rule_matcher: Rc::new(RefCell::new(RuleMatcher::default())), @@ -171,6 +266,7 @@ impl RootContext for DemoWasmRoot { "DemoWasmRoot::create_http_context({})", context_id )); + self.create_http_context_use_wrapper(context_id) } fn get_type(&self) -> Option { @@ -191,6 +287,8 @@ impl RootContextWrapper for DemoWasmRoot { config: None, log: Log::new(PLUGIN_NAME.to_string()), weak: Weak::default(), + redis_client: None, + cid: -1, })) } } diff --git a/plugins/wasm-rust/extensions/request-block/Cargo.lock b/plugins/wasm-rust/extensions/request-block/Cargo.lock index 243fe87a49..36c0b812b7 100644 --- a/plugins/wasm-rust/extensions/request-block/Cargo.lock +++ b/plugins/wasm-rust/extensions/request-block/Cargo.lock @@ -29,11 +29,23 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cfg-if" @@ -41,6 +53,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -53,6 +75,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -83,6 +114,7 @@ dependencies = [ "lazy_static", "multimap", "proxy-wasm", + "redis", "serde", "serde_json", "uuid", @@ -99,6 +131,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "1.0.11" @@ -113,9 +155,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -138,12 +180,46 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "proc-macro2" version = "1.0.88" @@ -156,7 +232,7 @@ dependencies = [ [[package]] name = "proxy-wasm" version = "0.2.2" -source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#6735737fad486c8a7cc324241f58df4a160e7887" +source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#8c902102091698bec953471c850bdf9799bc344d" dependencies = [ "downcast-rs", "hashbrown", @@ -172,6 +248,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redis" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +dependencies = [ + "arc-swap", + "combine", + "itoa", + "num-bigint", + "percent-encoding", + "ryu", + "url", +] + [[package]] name = "regex" version = "1.11.0" @@ -221,18 +312,18 @@ checksum = "f3cb5ba0dc43242ce17de99c180e96db90b235b8a9fdc9543c96d2209116bd9f" [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -241,9 +332,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -253,21 +344,62 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.11.0" diff --git a/plugins/wasm-rust/extensions/request-block/src/lib.rs b/plugins/wasm-rust/extensions/request-block/src/lib.rs index d120acb902..822601cd76 100644 --- a/plugins/wasm-rust/extensions/request-block/src/lib.rs +++ b/plugins/wasm-rust/extensions/request-block/src/lib.rs @@ -104,17 +104,17 @@ impl RquestBlockRoot { impl Context for RquestBlockRoot {} impl RootContext for RquestBlockRoot { - fn on_configure(&mut self, _plugin_configuration_size: usize) -> bool { + fn on_configure(&mut self, plugin_configuration_size: usize) -> bool { let ret = on_configure( self, - _plugin_configuration_size, + plugin_configuration_size, self.rule_matcher.borrow_mut().deref_mut(), &self.log, ); ret } - fn create_http_context(&self, _context_id: u32) -> Option> { - self.create_http_context_use_wrapper(_context_id) + fn create_http_context(&self, context_id: u32) -> Option> { + self.create_http_context_use_wrapper(context_id) } fn get_type(&self) -> Option { Some(ContextType::HttpContext) diff --git a/plugins/wasm-rust/extensions/say-hello/Cargo.lock b/plugins/wasm-rust/extensions/say-hello/Cargo.lock index dc98fd709a..758fc617e3 100644 --- a/plugins/wasm-rust/extensions/say-hello/Cargo.lock +++ b/plugins/wasm-rust/extensions/say-hello/Cargo.lock @@ -20,11 +20,23 @@ version = "0.2.18" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5c6cb57a04249c6480766f7f7cef5467412af1490f8d1e243141daddada3264f" +[[package]] +name = "arc-swap" +version = "1.7.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "69f7f8c3906b62b754cd5326047894316021dcfe5a194c8ea52bdd94934a3457" + +[[package]] +name = "autocfg" +version = "1.4.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ace50bade8e6234aa140d9a2f552bbee1db4d353f69b8217bc503490fc1a9f26" + [[package]] name = "bytes" -version = "1.7.2" +version = "1.8.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "428d9aa8fbc0670b7b8d6030a7fadd0f86151cae55e4dbbece15f3780a3dfaf3" +checksum = "9ac0150caa2ae65ca5bd83f25c7de183dea78d4d366469f148435e2acfbad0da" [[package]] name = "cfg-if" @@ -32,6 +44,16 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "baf1de4339761588bc0619e3cbc0120ee582ebb74b53b4efbf79117bd2da40fd" +[[package]] +name = "combine" +version = "4.6.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "ba5a308b75df32fe02788e748662718f03fde005016435c444eea572398219fd" +dependencies = [ + "bytes", + "memchr", +] + [[package]] name = "downcast-rs" version = "1.2.1" @@ -44,6 +66,15 @@ version = "1.0.7" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "3f9eec918d3f24069decb9af1554cad7c880e2da24a9afd88aca000531ab82c1" +[[package]] +name = "form_urlencoded" +version = "1.2.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e13624c2627564efccf4934284bdd98cbaa14e79b0b5a141218e507b3a823456" +dependencies = [ + "percent-encoding", +] + [[package]] name = "getrandom" version = "0.2.15" @@ -74,6 +105,7 @@ dependencies = [ "lazy_static", "multimap", "proxy-wasm", + "redis", "serde", "serde_json", "uuid", @@ -90,6 +122,16 @@ dependencies = [ "itoa", ] +[[package]] +name = "idna" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "634d9b1461af396cad843f47fdba5597a4f9e6ddd4bfb6ff5d85028c25cb12f6" +dependencies = [ + "unicode-bidi", + "unicode-normalization", +] + [[package]] name = "itoa" version = "1.0.11" @@ -104,9 +146,9 @@ checksum = "bbd2bcb4c963f2ddae06a2efc7e9f3591312473c50c6685e1f298068316e66fe" [[package]] name = "libc" -version = "0.2.159" +version = "0.2.161" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "561d97a539a36e26a9a5fad1ea11a3039a67714694aaa379433e580854bc3dc5" +checksum = "8e9489c2807c139ffd9c1794f4af0ebe86a828db53ecdc7fea2111d0fed085d1" [[package]] name = "log" @@ -129,12 +171,46 @@ dependencies = [ "serde", ] +[[package]] +name = "num-bigint" +version = "0.4.6" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a5e44f723f1133c9deac646763579fdb3ac745e418f2a7af9cd0c431da1f20b9" +dependencies = [ + "num-integer", + "num-traits", +] + +[[package]] +name = "num-integer" +version = "0.1.46" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7969661fd2958a5cb096e56c8e1ad0444ac2bbcd0061bd28660485a44879858f" +dependencies = [ + "num-traits", +] + +[[package]] +name = "num-traits" +version = "0.2.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "071dfc062690e90b734c0b2273ce72ad0ffa95f0c74596bc250dcfd960262841" +dependencies = [ + "autocfg", +] + [[package]] name = "once_cell" version = "1.20.2" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "1261fe7e33c73b354eab43b1273a57c8f967d0391e80353e51f764ac02cf6775" +[[package]] +name = "percent-encoding" +version = "2.3.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e3148f5046208a5d56bcfc03053e3ca6334e51da8dfb19b6cdc8b306fae3283e" + [[package]] name = "proc-macro2" version = "1.0.88" @@ -147,7 +223,7 @@ dependencies = [ [[package]] name = "proxy-wasm" version = "0.2.2" -source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#6735737fad486c8a7cc324241f58df4a160e7887" +source = "git+https://github.com/higress-group/proxy-wasm-rust-sdk?branch=main#8c902102091698bec953471c850bdf9799bc344d" dependencies = [ "downcast-rs", "hashbrown", @@ -163,6 +239,21 @@ dependencies = [ "proc-macro2", ] +[[package]] +name = "redis" +version = "0.27.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "81cccf17a692ce51b86564334614d72dcae1def0fd5ecebc9f02956da74352b5" +dependencies = [ + "arc-swap", + "combine", + "itoa", + "num-bigint", + "percent-encoding", + "ryu", + "url", +] + [[package]] name = "ryu" version = "1.0.18" @@ -181,18 +272,18 @@ dependencies = [ [[package]] name = "serde" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c8e3592472072e6e22e0a54d5904d9febf8508f65fb8552499a1abc7d1078c3a" +checksum = "1ac55e59090389fb9f0dd9e0f3c09615afed1d19094284d0b200441f13550793" dependencies = [ "serde_derive", ] [[package]] name = "serde_derive" -version = "1.0.210" +version = "1.0.211" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "243902eda00fad750862fc144cea25caca5e20d615af0a81bee94ca738f1df1f" +checksum = "54be4f245ce16bc58d57ef2716271d0d4519e0f6defa147f6e081005bcb278ff" dependencies = [ "proc-macro2", "quote", @@ -201,9 +292,9 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.128" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "6ff5456707a1de34e7e37f2a6fd3d3f808c318259cbd01ab6377795054b483d8" +checksum = "d726bfaff4b320266d395898905d0eba0345aae23b54aee3a737e260fd46db03" dependencies = [ "itoa", "memchr", @@ -213,21 +304,62 @@ dependencies = [ [[package]] name = "syn" -version = "2.0.79" +version = "2.0.82" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "89132cd0bf050864e1d38dc3bbc07a0eb8e7530af26344d3d2bbbef83499f590" +checksum = "83540f837a8afc019423a8edb95b52a8effe46957ee402287f4292fae35be021" dependencies = [ "proc-macro2", "quote", "unicode-ident", ] +[[package]] +name = "tinyvec" +version = "1.8.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "445e881f4f6d382d5f27c034e25eb92edd7c784ceab92a0937db7f2e9471b938" +dependencies = [ + "tinyvec_macros", +] + +[[package]] +name = "tinyvec_macros" +version = "0.1.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1f3ccbac311fea05f86f61904b462b55fb3df8837a366dfc601a0161d0532f20" + +[[package]] +name = "unicode-bidi" +version = "0.3.17" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5ab17db44d7388991a428b2ee655ce0c212e862eff1768a455c58f9aad6e7893" + [[package]] name = "unicode-ident" version = "1.0.13" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "e91b56cd4cadaeb79bbf1a5645f6b4f8dc5bde8834ad5894a8db35fda9efa1fe" +[[package]] +name = "unicode-normalization" +version = "0.1.24" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "5033c97c4262335cded6d6fc3e5c18ab755e1a3dc96376350f3d8e9f009ad956" +dependencies = [ + "tinyvec", +] + +[[package]] +name = "url" +version = "2.5.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "22784dbdf76fdde8af1aeda5622b546b422b6fc585325248a2bf9f5e41e94d6c" +dependencies = [ + "form_urlencoded", + "idna", + "percent-encoding", +] + [[package]] name = "uuid" version = "1.11.0" diff --git a/plugins/wasm-rust/src/cluster_wrapper.rs b/plugins/wasm-rust/src/cluster_wrapper.rs index 2891293fb3..8d3e204458 100644 --- a/plugins/wasm-rust/src/cluster_wrapper.rs +++ b/plugins/wasm-rust/src/cluster_wrapper.rs @@ -4,10 +4,12 @@ pub trait Cluster { fn cluster_name(&self) -> String; fn host_name(&self) -> String; } + #[derive(Debug, Clone)] pub struct RouteCluster { host: String, } + impl RouteCluster { pub fn new(host: &str) -> Self { RouteCluster { @@ -15,6 +17,7 @@ impl RouteCluster { } } } + impl Cluster for RouteCluster { fn cluster_name(&self) -> String { if let Some(res) = get_property(vec!["cluster_name"]) { @@ -111,6 +114,7 @@ impl NacosCluster { } } } + impl Cluster for NacosCluster { fn cluster_name(&self) -> String { let group = if self.group.is_empty() { @@ -154,6 +158,7 @@ impl StaticIpCluster { } } } + impl Cluster for StaticIpCluster { fn cluster_name(&self) -> String { format!("outbound|{}||{}.static", self.port, self.service_name) @@ -184,6 +189,7 @@ impl DnsCluster { } } } + impl Cluster for DnsCluster { fn cluster_name(&self) -> String { format!("outbound|{}||{}.dns", self.port, self.service_name) @@ -212,6 +218,7 @@ impl ConsulCluster { } } } + impl Cluster for ConsulCluster { fn cluster_name(&self) -> String { format!( @@ -245,10 +252,12 @@ impl FQDNCluster { } } } + impl Cluster for FQDNCluster { fn cluster_name(&self) -> String { format!("outbound|{}||{}", self.port, self.fqdn) } + fn host_name(&self) -> String { if self.host.is_empty() { self.fqdn.clone() diff --git a/plugins/wasm-rust/src/event_stream.rs b/plugins/wasm-rust/src/event_stream.rs index f28846317a..97715dcac1 100644 --- a/plugins/wasm-rust/src/event_stream.rs +++ b/plugins/wasm-rust/src/event_stream.rs @@ -28,29 +28,15 @@ /// However, in the rules of event and field, there is an ambiguous grammar in the judgment of eol, /// and it will bring ambiguity (whether the field ends). In order to eliminate this ambiguity, /// we believe that CRLF as CR+LF belongs to event and field respectively. + +#[derive(Default)] pub struct EventStream { buffer: Vec, processed_offset: usize, } -impl EventStream { - pub fn new() -> Self { - EventStream { - buffer: Vec::new(), - processed_offset: 0, - } - } - - /// Update the event stream by adding new data to the buffer and resetting processed offset if needed. - pub fn update(&mut self, data: Vec) { - if self.processed_offset > 0 { - self.buffer.drain(0..self.processed_offset); - self.processed_offset = 0; - } - - self.buffer.extend(data); - } - +impl Iterator for EventStream { + type Item = Vec; /// Get the next event from the event stream. Return the event data if available, otherwise return None. /// Next will consume all the data in the current buffer. However, if there is a valid event at the end of the buffer, /// it will return the event directly even if the data after the next `update` could be considered part of the same event @@ -71,7 +57,8 @@ impl EventStream { /// } /// } /// ``` - pub fn next(&mut self) -> Option> { + /// + fn next(&mut self) -> Option { let mut i = self.processed_offset; while i < self.buffer.len() { @@ -86,6 +73,18 @@ impl EventStream { None } +} + +impl EventStream { + /// Update the event stream by adding new data to the buffer and resetting processed offset if needed. + pub fn update(&mut self, data: Vec) { + if self.processed_offset > 0 { + self.buffer.drain(0..self.processed_offset); + self.processed_offset = 0; + } + + self.buffer.extend(data); + } /// Flush the event stream and return any remaining unprocessed event data. Return None if there is none. pub fn flush(&mut self) -> Option> { @@ -138,7 +137,7 @@ mod tests { #[test] fn test_crlf_events() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"event1\n\nevent2\n\n".to_vec()); assert_eq!(parser.next(), Some(b"event1".to_vec())); @@ -147,7 +146,7 @@ mod tests { #[test] fn test_lf_events() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"event3\n\r\nevent4\r\n".to_vec()); assert_eq!(parser.next(), Some(b"event3".to_vec())); @@ -156,7 +155,7 @@ mod tests { #[test] fn test_partial_event() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"partial_event1".to_vec()); assert_eq!(parser.next(), None); @@ -167,7 +166,7 @@ mod tests { #[test] fn test_mixed_eol_events() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"event5\r\nevent6\r\n\r\nevent7\r\n".to_vec()); assert_eq!(parser.next(), Some(b"event5".to_vec())); @@ -177,7 +176,7 @@ mod tests { #[test] fn test_mixed2_eol_events() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"event5\r\nevent6\r\n".to_vec()); assert_eq!(parser.next(), Some(b"event5".to_vec())); assert_eq!(parser.next(), Some(b"event6".to_vec())); @@ -188,7 +187,7 @@ mod tests { #[test] fn test_no_event() { - let mut parser = EventStream::new(); + let mut parser = EventStream::default(); parser.update(b"no_eol_in_this_string".to_vec()); assert_eq!(parser.next(), None); diff --git a/plugins/wasm-rust/src/internal.rs b/plugins/wasm-rust/src/internal.rs index 4116c5d798..5a562419d4 100644 --- a/plugins/wasm-rust/src/internal.rs +++ b/plugins/wasm-rust/src/internal.rs @@ -14,7 +14,7 @@ #![allow(dead_code)] -use proxy_wasm::hostcalls; +use proxy_wasm::hostcalls::{self, RedisCallbackFn}; use proxy_wasm::types::{BufferType, Bytes, MapType, Status}; use std::time::{Duration, SystemTime}; @@ -381,3 +381,24 @@ pub(crate) fn send_http_response( ) { hostcalls::send_http_response(status_code, headers, body).unwrap() } + +pub(crate) fn redis_init( + upstream: &str, + username: Option<&[u8]>, + password: Option<&[u8]>, + timeout: Duration, +) -> Result<(), Status> { + hostcalls::redis_init(upstream, username, password, timeout) +} + +pub(crate) fn dispatch_redis_call( + upstream: &str, + query: &[u8], + call_fn: Box, +) -> Result { + hostcalls::dispatch_redis_call(upstream, query, call_fn) +} + +pub(crate) fn get_redis_call_response(start: usize, max_size: usize) -> Option { + hostcalls::get_buffer(BufferType::RedisCallResponse, start, max_size).unwrap() +} diff --git a/plugins/wasm-rust/src/lib.rs b/plugins/wasm-rust/src/lib.rs index f6a92be89b..2e6993e040 100644 --- a/plugins/wasm-rust/src/lib.rs +++ b/plugins/wasm-rust/src/lib.rs @@ -18,5 +18,6 @@ pub mod event_stream; mod internal; pub mod log; pub mod plugin_wrapper; +pub mod redis_wrapper; pub mod request_wrapper; pub mod rule_matcher; diff --git a/plugins/wasm-rust/src/plugin_wrapper.rs b/plugins/wasm-rust/src/plugin_wrapper.rs index abe188a99f..832cdbce5c 100644 --- a/plugins/wasm-rust/src/plugin_wrapper.rs +++ b/plugins/wasm-rust/src/plugin_wrapper.rs @@ -30,6 +30,7 @@ use serde::de::DeserializeOwned; lazy_static! { static ref LOG: Log = Log::new("plugin_wrapper".to_string()); } + thread_local! { static HTTP_CALLBACK_DISPATCHER: HttpCallbackDispatcher = HttpCallbackDispatcher::new(); } @@ -49,7 +50,9 @@ where None => None, } } + fn rule_matcher(&self) -> &SharedRuleMatcher; + fn create_http_context_wrapper( &self, _context_id: u32, @@ -63,20 +66,24 @@ pub type HttpCallbackFn = dyn FnOnce(u16, &MultiMap, Option>>, } + impl Default for HttpCallbackDispatcher { fn default() -> Self { Self::new() } } + impl HttpCallbackDispatcher { pub fn new() -> Self { HttpCallbackDispatcher { call_fns: RefCell::new(HashMap::new()), } } + pub fn set(&self, token_id: u32, arg: Box) { self.call_fns.borrow_mut().insert(token_id, arg); } + pub fn pop(&self, token_id: u32) -> Option> { self.call_fns.borrow_mut().remove(&token_id) } @@ -91,31 +98,39 @@ where _self_weak: Weak>>>, ) { } + fn log(&self) -> &Log { &LOG } + fn on_config(&mut self, _config: Rc) {} + fn on_http_request_complete_headers( &mut self, _headers: &MultiMap, ) -> HeaderAction { HeaderAction::Continue } + fn on_http_response_complete_headers( &mut self, _headers: &MultiMap, ) -> HeaderAction { HeaderAction::Continue } + fn cache_request_body(&self) -> bool { false } + fn cache_response_body(&self) -> bool { false } + fn on_http_request_complete_body(&mut self, _req_body: &Bytes) -> DataAction { DataAction::Continue } + fn on_http_response_complete_body(&mut self, _res_body: &Bytes) -> DataAction { DataAction::Continue } @@ -123,6 +138,7 @@ where fn replace_http_request_body(&mut self, body: &[u8]) { self.set_http_request_body(0, i32::MAX as usize, body) } + fn replace_http_response_body(&mut self, body: &[u8]) { self.set_http_response_body(0, i32::MAX as usize, body) } @@ -164,8 +180,8 @@ where if let Ok(token_id) = ret { HTTP_CALLBACK_DISPATCHER.with(|dispatcher| dispatcher.set(token_id, call_fn)); - self.log().debug( - &format!( + self.log().debugf( + format_args!( "http call start, id: {}, cluster: {}, method: {}, url: {}, body: {:?}, timeout: {:?}", token_id, cluster.cluster_name(), method.as_str(), raw_url, body, timeout ) @@ -173,7 +189,8 @@ where } ret } else { - self.log().critical(&format!("invalid raw_url:{}", raw_url)); + self.log() + .criticalf(format_args!("invalid raw_url:{}", raw_url)); Err(Status::ParseFailure) } } @@ -182,14 +199,13 @@ where downcast_rs::impl_downcast!(HttpContextWrapper where PluginConfig: Default + DeserializeOwned + Clone); pub struct PluginHttpWrapper { - req_headers: MultiMap, - res_headers: MultiMap, req_body_len: usize, res_body_len: usize, config: Option>, rule_matcher: SharedRuleMatcher, http_content: Rc>>>, } + impl PluginHttpWrapper where PluginConfig: Default + DeserializeOwned + Clone + 'static, @@ -203,8 +219,6 @@ where .borrow_mut() .init_self_weak(Rc::downgrade(&rc_content)); PluginHttpWrapper { - req_headers: MultiMap::new(), - res_headers: MultiMap::new(), req_body_len: 0, res_body_len: 0, config: None, @@ -212,10 +226,12 @@ where http_content: rc_content, } } + fn get_http_call_fn(&mut self, token_id: u32) -> Option> { HTTP_CALLBACK_DISPATCHER.with(|dispatcher| dispatcher.pop(token_id)) } } + impl Context for PluginHttpWrapper where PluginConfig: Default + DeserializeOwned + Clone + 'static, @@ -240,24 +256,24 @@ where status_code = code; normal_response = true; } else { - self.http_content - .borrow() - .log() - .error(&format!("failed to parse status: {}", header_value)); + self.http_content.borrow().log().errorf(format_args!( + "failed to parse status: {}", + header_value + )); status_code = 500; } } headers.insert(k, header_value); } Err(_) => { - self.http_content.borrow().log().warn(&format!( + self.http_content.borrow().log().warnf(format_args!( "http call response header contains non-ASCII characters header: {}", k )); } } } - self.http_content.borrow().log().warn(&format!( + self.http_content.borrow().log().debugf(format_args!( "http call end, id: {}, code: {}, normal: {}, body: {:?}", /* */ token_id, status_code, normal_response, body )); @@ -277,21 +293,25 @@ where .borrow_mut() .on_grpc_call_response(token_id, status_code, response_size) } + fn on_grpc_stream_initial_metadata(&mut self, token_id: u32, num_elements: u32) { self.http_content .borrow_mut() .on_grpc_stream_initial_metadata(token_id, num_elements) } + fn on_grpc_stream_message(&mut self, token_id: u32, message_size: usize) { self.http_content .borrow_mut() .on_grpc_stream_message(token_id, message_size) } + fn on_grpc_stream_trailing_metadata(&mut self, token_id: u32, num_elements: u32) { self.http_content .borrow_mut() .on_grpc_stream_trailing_metadata(token_id, num_elements) } + fn on_grpc_stream_close(&mut self, token_id: u32, status_code: u32) { self.http_content .borrow_mut() @@ -302,6 +322,7 @@ where self.http_content.borrow_mut().on_done() } } + impl HttpContext for PluginHttpWrapper where PluginConfig: Default + DeserializeOwned + Clone + 'static, @@ -312,13 +333,15 @@ where if self.config.is_none() { return HeaderAction::Continue; } + + let mut req_headers = MultiMap::new(); for (k, v) in self.get_http_request_headers_bytes() { match String::from_utf8(v) { Ok(header_value) => { - self.req_headers.insert(k, header_value); + req_headers.insert(k, header_value); } Err(_) => { - self.http_content.borrow().log().warn(&format!( + self.http_content.borrow().log().warnf(format_args!( "request http header contains non-ASCII characters header: {}", k )); @@ -338,7 +361,7 @@ where } self.http_content .borrow_mut() - .on_http_request_complete_headers(&self.req_headers) + .on_http_request_complete_headers(&req_headers) } fn on_http_request_body(&mut self, body_size: usize, end_of_stream: bool) -> DataAction { @@ -383,13 +406,15 @@ where if self.config.is_none() { return HeaderAction::Continue; } + + let mut res_headers = MultiMap::new(); for (k, v) in self.get_http_response_headers_bytes() { match String::from_utf8(v) { Ok(header_value) => { - self.res_headers.insert(k, header_value); + res_headers.insert(k, header_value); } Err(_) => { - self.http_content.borrow().log().warn(&format!( + self.http_content.borrow().log().warnf(format_args!( "response http header contains non-ASCII characters header: {}", k )); @@ -406,7 +431,7 @@ where } self.http_content .borrow_mut() - .on_http_response_complete_headers(&self.res_headers) + .on_http_response_complete_headers(&res_headers) } fn on_http_response_body(&mut self, body_size: usize, end_of_stream: bool) -> DataAction { diff --git a/plugins/wasm-rust/src/redis_wrapper.rs b/plugins/wasm-rust/src/redis_wrapper.rs new file mode 100644 index 0000000000..50d30a1f5c --- /dev/null +++ b/plugins/wasm-rust/src/redis_wrapper.rs @@ -0,0 +1,724 @@ +use std::{collections::HashMap, time::Duration}; + +use proxy_wasm::{hostcalls::RedisCallbackFn, types::Status}; +use redis::{Cmd, ToRedisArgs, Value}; + +use crate::{cluster_wrapper::Cluster, internal}; + +pub type RedisValueCallbackFn = dyn FnOnce(&Result, usize, u32); + +fn gen_callback(call_fn: Box) -> Box { + Box::new(move |token_id, status, response_size| { + let res = match internal::get_redis_call_response(0, response_size) { + Some(data) => match redis::parse_redis_value(&data) { + Ok(v) => Ok(v), + Err(e) => Err(e.to_string()), + }, + None => Err("response data not found".to_string()), + }; + call_fn(&res, status, token_id); + }) +} + +pub struct RedisClientBuilder { + upstream: String, + username: Option, + password: Option, + timeout: Duration, +} + +impl RedisClientBuilder { + pub fn new(cluster: &dyn Cluster, timeout: Duration) -> Self { + RedisClientBuilder { + upstream: cluster.cluster_name(), + username: None, + password: None, + timeout, + } + } + + pub fn username>(mut self, username: Option) -> Self { + self.username = username.map(|u| u.as_ref().to_string()); + self + } + + pub fn password>(mut self, password: Option) -> Self { + self.password = password.map(|p| p.as_ref().to_string()); + self + } + + pub fn build(self) -> RedisClient { + RedisClient { + upstream: self.upstream, + username: self.username, + password: self.password, + timeout: self.timeout, + } + } +} + +pub struct RedisClientConfig { + upstream: String, + username: Option, + password: Option, + timeout: Duration, +} + +impl RedisClientConfig { + pub fn new(cluster: &dyn Cluster, timeout: Duration) -> Self { + RedisClientConfig { + upstream: cluster.cluster_name(), + username: None, + password: None, + timeout, + } + } + + pub fn username>(&mut self, username: Option) -> &Self { + self.username = username.map(|u| u.as_ref().to_string()); + self + } + + pub fn password>(&mut self, password: Option) -> &Self { + self.password = password.map(|p| p.as_ref().to_string()); + self + } +} + +#[derive(Debug, Clone)] +pub struct RedisClient { + upstream: String, + username: Option, + password: Option, + timeout: Duration, +} + +impl RedisClient { + pub fn new(config: &RedisClientConfig) -> Self { + RedisClient { + upstream: config.upstream.clone(), + username: config.username.clone(), + password: config.password.clone(), + timeout: config.timeout, + } + } + + pub fn init(&self) -> Result<(), Status> { + internal::redis_init( + &self.upstream, + self.username.as_ref().map(|u| u.as_bytes()), + self.password.as_ref().map(|p| p.as_bytes()), + self.timeout, + ) + } + + fn call(&self, query: &[u8], call_fn: Box) -> Result { + internal::dispatch_redis_call(&self.upstream, query, gen_callback(call_fn)) + } + + pub fn command(&self, cmd: &Cmd, call_fn: Box) -> Result { + self.call(&cmd.get_packed_command(), call_fn) + } + + pub fn eval( + &self, + script: &str, + numkeys: i32, + keys: Vec<&str>, + args: Vec, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("eval"); + cmd.arg(script).arg(numkeys); + for key in keys { + cmd.arg(key); + } + for arg in args { + cmd.arg(arg); + } + self.command(&cmd, call_fn) + } + + // Key + pub fn del(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("del"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn exists(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("exists"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn expire( + &self, + key: &str, + ttl: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("expire"); + cmd.arg(key).arg(ttl); + self.command(&cmd, call_fn) + } + + pub fn persist(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("persist"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + // String + pub fn get(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("get"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn set( + &self, + key: &str, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("set"); + cmd.arg(key).arg(value); + self.command(&cmd, call_fn) + } + + pub fn setex( + &self, + key: &str, + value: T, + ttl: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("setex"); + cmd.arg(key).arg(ttl).arg(value); + self.command(&cmd, call_fn) + } + + pub fn mget(&self, keys: Vec<&str>, call_fn: Box) -> Result { + let mut cmd = redis::cmd("mget"); + for key in keys { + cmd.arg(key); + } + self.command(&cmd, call_fn) + } + + pub fn mset( + &self, + kv_map: HashMap<&str, T>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("mset"); + for (k, v) in kv_map { + cmd.arg(k).arg(v); + } + self.command(&cmd, call_fn) + } + + pub fn incr(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("incr"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn decr(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("decr"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn incrby( + &self, + key: &str, + delta: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("incrby"); + cmd.arg(key).arg(delta); + self.command(&cmd, call_fn) + } + + pub fn decrby( + &self, + key: &str, + delta: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("decrby"); + cmd.arg(key).arg(delta); + self.command(&cmd, call_fn) + } + + // List + pub fn llen(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("llen"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn rpush( + &self, + key: &str, + vals: Vec, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("rpush"); + cmd.arg(key); + for val in vals { + cmd.arg(val); + } + self.command(&cmd, call_fn) + } + + pub fn rpop(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("rpop"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn lpush( + &self, + key: &str, + vals: Vec, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("lpush"); + cmd.arg(key); + for val in vals { + cmd.arg(val); + } + self.command(&cmd, call_fn) + } + + pub fn lpop(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("lpop"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn lindex( + &self, + key: &str, + index: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("lindex"); + cmd.arg(key).arg(index); + self.command(&cmd, call_fn) + } + + pub fn lrange( + &self, + key: &str, + start: i32, + stop: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("lrange"); + cmd.arg(key).arg(start).arg(stop); + self.command(&cmd, call_fn) + } + + pub fn lrem( + &self, + key: &str, + count: i32, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("lrem"); + cmd.arg(key).arg(count).arg(value); + self.command(&cmd, call_fn) + } + + pub fn linsert_before( + &self, + key: &str, + pivot: T, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("linsert"); + cmd.arg(key).arg("before").arg(pivot).arg(value); + self.command(&cmd, call_fn) + } + + pub fn linsert_after( + &self, + key: &str, + pivot: T, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("linsert"); + cmd.arg(key).arg("after").arg(pivot).arg(value); + + self.command(&cmd, call_fn) + } + + // Hash + pub fn hexists( + &self, + key: &str, + field: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hexists"); + cmd.arg(key).arg(field); + self.command(&cmd, call_fn) + } + + pub fn hdel( + &self, + key: &str, + fields: Vec<&str>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hdel"); + cmd.arg(key); + for field in fields { + cmd.arg(field); + } + self.command(&cmd, call_fn) + } + + pub fn hlen(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("hlen"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn hget( + &self, + key: &str, + field: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hget"); + cmd.arg(key).arg(field); + self.command(&cmd, call_fn) + } + + pub fn hset( + &self, + key: &str, + field: &str, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hset"); + cmd.arg(key).arg(field).arg(value); + self.command(&cmd, call_fn) + } + + pub fn hmget( + &self, + key: &str, + fields: Vec<&str>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hmget"); + cmd.arg(key); + for field in fields { + cmd.arg(field); + } + self.command(&cmd, call_fn) + } + + pub fn hmset( + &self, + key: &str, + kv_map: HashMap<&str, T>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hmset"); + cmd.arg(key); + for (k, v) in kv_map { + cmd.arg(k).arg(v); + } + self.command(&cmd, call_fn) + } + + pub fn hkeys(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("hkeys"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn hvals(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("hvals"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn hgetall(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("hgetall"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn hincrby( + &self, + key: &str, + field: &str, + delta: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hincrby"); + cmd.arg(key).arg(field).arg(delta); + self.command(&cmd, call_fn) + } + + pub fn hincrbyfloat( + &self, + key: &str, + field: &str, + delta: f64, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("hincrbyfloat"); + cmd.arg(key).arg(field).arg(delta); + self.command(&cmd, call_fn) + } + + // Set + pub fn scard(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("scard"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn sadd( + &self, + key: &str, + vals: Vec, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sadd"); + cmd.arg(key); + for val in vals { + cmd.arg(val); + } + self.command(&cmd, call_fn) + } + + pub fn srem( + &self, + key: &str, + vals: Vec, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("srem"); + cmd.arg(key); + for val in vals { + cmd.arg(val); + } + self.command(&cmd, call_fn) + } + + pub fn sismember( + &self, + key: &str, + value: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sismember"); + cmd.arg(key).arg(value); + self.command(&cmd, call_fn) + } + + pub fn smembers(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("smembers"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn sdiff( + &self, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sdiff"); + cmd.arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + pub fn sdiffstore( + &self, + destination: &str, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sdiffstore"); + cmd.arg(destination).arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + pub fn sinter( + &self, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sinter"); + cmd.arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + pub fn sinterstore( + &self, + destination: &str, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sinterstore"); + cmd.arg(destination).arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + pub fn sunion( + &self, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sunion"); + cmd.arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + pub fn sunion_store( + &self, + destination: &str, + key1: &str, + key2: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("sunionstore"); + cmd.arg(destination).arg(key1).arg(key2); + self.command(&cmd, call_fn) + } + + // Sorted Set + pub fn zcard(&self, key: &str, call_fn: Box) -> Result { + let mut cmd = redis::cmd("zcard"); + cmd.arg(key); + self.command(&cmd, call_fn) + } + + pub fn zadd( + &self, + key: &str, + ms_map: HashMap<&str, T>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zadd"); + cmd.arg(key); + for (m, s) in ms_map { + cmd.arg(s).arg(m); + } + self.command(&cmd, call_fn) + } + + pub fn zcount( + &self, + key: &str, + min: T, + max: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zcount"); + cmd.arg(key).arg(min).arg(max); + self.command(&cmd, call_fn) + } + + pub fn zincrby( + &self, + key: &str, + member: &str, + delta: T, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zincrby"); + cmd.arg(key).arg(delta).arg(member); + self.command(&cmd, call_fn) + } + + pub fn zscore( + &self, + key: &str, + member: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zscore"); + cmd.arg(key).arg(member); + self.command(&cmd, call_fn) + } + + pub fn zrank( + &self, + key: &str, + member: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zrank"); + cmd.arg(key).arg(member); + self.command(&cmd, call_fn) + } + + pub fn zrev_rank( + &self, + key: &str, + member: &str, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zrevrank"); + cmd.arg(key).arg(member); + self.command(&cmd, call_fn) + } + + pub fn zrem( + &self, + key: &str, + members: Vec<&str>, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zrem"); + cmd.arg(key); + for member in members { + cmd.arg(member); + } + self.command(&cmd, call_fn) + } + + pub fn zrange( + &self, + key: &str, + start: i32, + stop: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zrange"); + cmd.arg(key).arg(start).arg(stop); + self.command(&cmd, call_fn) + } + + pub fn zrevrange( + &self, + key: &str, + start: i32, + stop: i32, + call_fn: Box, + ) -> Result { + let mut cmd = redis::cmd("zrevrange"); + cmd.arg(key).arg(start).arg(stop); + self.command(&cmd, call_fn) + } +} diff --git a/plugins/wasm-rust/src/request_wrapper.rs b/plugins/wasm-rust/src/request_wrapper.rs index c9a997456c..f37fd8f498 100644 --- a/plugins/wasm-rust/src/request_wrapper.rs +++ b/plugins/wasm-rust/src/request_wrapper.rs @@ -14,6 +14,7 @@ fn get_request_head(head: &str, log_flag: &str) -> String { String::new() } } + pub fn get_request_scheme() -> String { get_request_head(":scheme", "head") } @@ -57,6 +58,7 @@ pub fn is_binary_response_body() -> bool { } false } + pub fn has_request_body() -> bool { let content_type = internal::get_http_request_header("content-type"); let content_length_str = internal::get_http_request_header("content-length");