jasper_plugin_sdk/
host.rs1use crate::rt::{call_host, PluginError};
5use base64::Engine as _;
6use serde_json::{json, Value};
7use std::collections::BTreeMap;
8
9pub fn log(level: &str, message: &str) {
11 let _ = call_host("log", json!({ "level": level, "message": message }));
12}
13
14pub fn now_ms() -> Result<i64, PluginError> {
17 let r = call_host("time.now", json!({}))?;
18 r.get("unix_ms")
19 .and_then(Value::as_i64)
20 .ok_or_else(|| PluginError::internal("time.now 响应缺 unix_ms"))
21}
22
23pub fn settings_get(key: &str) -> Result<Value, PluginError> {
25 let result = call_host("settings.get", json!({ "key": key }))?;
26 Ok(result.get("value").cloned().unwrap_or(Value::Null))
27}
28
29pub fn settings_set(key: &str, value: Value) -> Result<(), PluginError> {
31 call_host("settings.set", json!({ "key": key, "value": value }))?;
32 Ok(())
33}
34
35#[derive(Debug, Clone, Default)]
37pub struct HttpRequest {
38 pub method: String,
40 pub url: String,
41 pub headers: BTreeMap<String, String>,
42 pub body: Option<Vec<u8>>,
43 pub timeout_ms: Option<u64>,
44}
45
46#[derive(Debug, Clone)]
47pub struct HttpResponse {
48 pub status: u16,
50 pub headers: BTreeMap<String, String>,
51 pub body: Vec<u8>,
52}
53
54impl HttpResponse {
55 pub fn is_success(&self) -> bool {
56 (200..300).contains(&self.status)
57 }
58 pub fn body_text(&self) -> String {
59 String::from_utf8_lossy(&self.body).into_owned()
60 }
61}
62
63pub fn http_request(req: &HttpRequest) -> Result<HttpResponse, PluginError> {
66 let b64 = base64::engine::general_purpose::STANDARD;
67 let mut params = json!({
68 "method": req.method,
69 "url": req.url,
70 "headers": req.headers,
71 });
72 if let Some(body) = &req.body {
73 params["body_b64"] = Value::String(b64.encode(body));
74 }
75 if let Some(t) = req.timeout_ms {
76 params["timeout_ms"] = json!(t);
77 }
78 let result = call_host("http.request", params)?;
79 let status = result
80 .get("status")
81 .and_then(Value::as_u64)
82 .ok_or_else(|| PluginError::internal("http.request 响应缺 status"))? as u16;
83 let headers = result
84 .get("headers")
85 .and_then(Value::as_object)
86 .map(|m| {
87 m.iter()
88 .filter_map(|(k, v)| v.as_str().map(|s| (k.clone(), s.to_string())))
89 .collect()
90 })
91 .unwrap_or_default();
92 let body = match result.get("body_b64").and_then(Value::as_str) {
93 Some(s) => b64
94 .decode(s)
95 .map_err(|e| PluginError::internal(format!("body_b64 解码失败: {e}")))?,
96 None => Vec::new(),
97 };
98 Ok(HttpResponse { status, headers, body })
99}