poolster_plugin_java/
webhooks.rs1use super::*;
2use poolster_core::engine::{Meta, Plugin, PluginContext};
3pub struct Webhooks {
4 meta: Meta,
5}
6pub fn webhooks() -> Webhooks {
7 Webhooks { meta: Meta::new() }
8}
9impl Plugin<Java> for Webhooks {
10 fn kind(&self) -> &'static str {
11 "java-webhooks"
12 }
13 fn meta(&self) -> &Meta {
14 &self.meta
15 }
16 fn generate(&self, cx: &mut PluginContext<'_, Java>) -> Result<()> {
17 let namespace = java_package_name(
18 cx.settings
19 .package_name
20 .as_deref()
21 .unwrap_or(&format!("io.poolster.{}", package_segment(&cx.api.name))),
22 );
23 cx.files.emit(GeneratedFile::new(
24 format!(
25 "src/main/java/{}/StandardWebhooks.java",
26 namespace.replace('.', "/")
27 ),
28 include_str!("../templates/webhooks.java.tmpl").replace("__PACKAGE__", &namespace),
29 )?)
30 }
31}
32
33#[cfg(test)]
34mod tests {
35 use super::*;
36 use poolster_core::engine::Packages;
37 #[test]
38 fn opt_in_emits_standard_webhook_verifier() {
39 let tree = Packages::new()
40 .package(crate::package("sdk").with(crate::sdk()).with(webhooks()))
41 .generate(&Api::default(), None)
42 .unwrap();
43 let source = tree
44 .iter()
45 .find(|(path, _)| path.ends_with("StandardWebhooks.java"))
46 .unwrap()
47 .1;
48 assert!(source.contains("HmacSHA256") || source.contains("HMACSHA256"));
49 assert!(source.contains("does not match a trusted key"));
50 }
51 #[test]
52 #[ignore = "requires native JDK17; canonical Standard Webhooks verification probes"]
53 fn native_webhook_verification_executes_canonical_vectors() {
54 let vector: serde_json::Value =
55 serde_json::from_str(include_str!("../../python/testdata/webhook-vectors.json"))
56 .unwrap();
57 let dir = tempfile::tempdir().unwrap();
58 std::fs::write(
59 dir.path().join("StandardWebhooks.java"),
60 include_str!("../templates/webhooks.java.tmpl").replace("__PACKAGE__", "probe"),
61 )
62 .unwrap();
63 std::fs::write(
64 dir.path().join("Probe.java"),
65 include_str!("../tests/fixtures/webhooks_probe.java")
66 .replace(
67 "__BODY__",
68 &serde_json::to_string(&vector["raw_body"]).unwrap(),
69 )
70 .replace(
71 "__SECRET__",
72 &serde_json::to_string(&vector["secret"]).unwrap(),
73 )
74 .replace(
75 "__SIGNATURE__",
76 &serde_json::to_string(&vector["headers"]["webhook-signature"]).unwrap(),
77 ),
78 )
79 .unwrap();
80 let result = std::process::Command::new("javac")
81 .args(["-d", ".", "StandardWebhooks.java", "Probe.java"])
82 .current_dir(dir.path())
83 .output()
84 .unwrap();
85 assert!(
86 result.status.success(),
87 "{}",
88 String::from_utf8_lossy(&result.stderr)
89 );
90 let result = std::process::Command::new("java")
91 .args(["-cp", ".", "probe.Probe"])
92 .current_dir(dir.path())
93 .output()
94 .unwrap();
95 assert!(
96 result.status.success(),
97 "{}{}",
98 String::from_utf8_lossy(&result.stdout),
99 String::from_utf8_lossy(&result.stderr)
100 );
101 }
102}