ironflow_engine/config/
http.rs1use ironflow_core::retry::RetryPolicy;
4use serde::{Deserialize, Serialize};
5use serde_json::Value;
6
7#[derive(Debug, Clone, Serialize, Deserialize)]
17pub struct HttpConfig {
18 pub method: String,
20 pub url: String,
22 pub headers: Vec<(String, String)>,
24 pub body: Option<Value>,
26 pub timeout_secs: Option<u64>,
28 #[serde(default)]
30 pub allow_failure: bool,
31 #[serde(default, skip_serializing_if = "Option::is_none")]
33 pub retry: Option<RetryPolicy>,
34}
35
36impl HttpConfig {
37 pub fn get(url: &str) -> Self {
48 Self::new("GET", url)
49 }
50
51 pub fn post(url: &str) -> Self {
53 Self::new("POST", url)
54 }
55
56 pub fn put(url: &str) -> Self {
58 Self::new("PUT", url)
59 }
60
61 pub fn patch(url: &str) -> Self {
63 Self::new("PATCH", url)
64 }
65
66 pub fn delete(url: &str) -> Self {
68 Self::new("DELETE", url)
69 }
70
71 fn new(method: &str, url: &str) -> Self {
72 Self {
73 method: method.to_string(),
74 url: url.to_string(),
75 headers: Vec::new(),
76 body: None,
77 timeout_secs: None,
78 allow_failure: false,
79 retry: None,
80 }
81 }
82
83 pub fn header(mut self, name: &str, value: &str) -> Self {
85 self.headers.push((name.to_string(), value.to_string()));
86 self
87 }
88
89 pub fn json(mut self, body: Value) -> Self {
91 self.body = Some(body);
92 self
93 }
94
95 pub fn timeout_secs(mut self, secs: u64) -> Self {
97 self.timeout_secs = Some(secs);
98 self
99 }
100
101 pub fn allow_failure(mut self) -> Self {
112 self.allow_failure = true;
113 self
114 }
115
116 pub fn retry_policy(mut self, policy: RetryPolicy) -> Self {
129 self.retry = Some(policy);
130 self
131 }
132}
133
134#[cfg(test)]
135mod tests {
136 use super::*;
137 use serde_json::json;
138
139 #[test]
140 fn methods() {
141 assert_eq!(HttpConfig::get("http://x").method, "GET");
142 assert_eq!(HttpConfig::post("http://x").method, "POST");
143 assert_eq!(HttpConfig::put("http://x").method, "PUT");
144 assert_eq!(HttpConfig::patch("http://x").method, "PATCH");
145 assert_eq!(HttpConfig::delete("http://x").method, "DELETE");
146 }
147
148 #[test]
149 fn builder() {
150 let config = HttpConfig::post("http://api.example.com")
151 .header("Authorization", "Bearer token")
152 .json(json!({"key": "value"}))
153 .timeout_secs(10);
154
155 assert_eq!(config.headers.len(), 1);
156 assert!(config.body.is_some());
157 assert_eq!(config.timeout_secs, Some(10));
158 }
159
160 #[test]
161 fn a_config_predating_retry_still_deserializes() {
162 let config: HttpConfig = serde_json::from_str(
163 r#"{"url":"http://x","method":"GET","headers":[],"body":null,"timeout_secs":null}"#,
164 )
165 .expect("deserialize");
166 assert!(config.retry.is_none());
167 }
168
169 #[test]
170 fn retry_policy_roundtrip() {
171 use ironflow_core::retry::RetryPolicy;
172
173 let config = HttpConfig::get("http://api").retry_policy(RetryPolicy::new(3));
174 let json = serde_json::to_string(&config).expect("serialize");
175 let back: HttpConfig = serde_json::from_str(&json).expect("deserialize");
176 assert_eq!(back.retry.as_ref().unwrap().max_retries(), 3);
177 }
178}