use serde_json::Value; // Extract http config: method, url, headers, query, body from a node pub fn extract_http_cfg(n: &Value) -> Option { let data = n.get("data"); let api = data.and_then(|d| d.get("api")); let method = api .and_then(|a| a.get("method")) .and_then(|v| v.as_str()) .unwrap_or("GET") .to_string(); let url_val = api.and_then(|a| a.get("url")); let raw_url = match url_val { Some(Value::String(s)) => s.clone(), Some(Value::Object(obj)) => obj .get("content") .and_then(|v| v.as_str()) .unwrap_or("") .to_string(), _ => String::new(), }; let url = super::sanitize_wrapped(&raw_url); if url.is_empty() { return None; } let mut http_obj = serde_json::Map::new(); http_obj.insert("method".into(), Value::String(method)); http_obj.insert("url".into(), Value::String(url)); // Optional: headers if let Some(hs) = api.and_then(|a| a.get("headers")).and_then(|v| v.as_object()) { let mut heads = serde_json::Map::new(); for (k, v) in hs.iter() { if let Some(s) = v.as_str() { heads.insert(k.clone(), Value::String(s.to_string())); } } if !heads.is_empty() { http_obj.insert("headers".into(), Value::Object(heads)); } } // Optional: query if let Some(qs) = api.and_then(|a| a.get("query")).and_then(|v| v.as_object()) { let mut query = serde_json::Map::new(); for (k, v) in qs.iter() { query.insert(k.clone(), v.clone()); } if !query.is_empty() { http_obj.insert("query".into(), Value::Object(query)); } } // Optional: body if let Some(body_obj) = data.and_then(|d| d.get("body")).and_then(|v| v.as_object()) { if let Some(Value::Object(json_body)) = body_obj.get("json") { http_obj.insert("body".into(), Value::Object(json_body.clone())); } else if let Some(Value::String(s)) = body_obj.get("content") { http_obj.insert("body".into(), Value::String(s.clone())); } } Some(Value::Object(http_obj)) }