Skip to main content

ironflow_engine/config/
http.rs

1//! [`HttpConfig`] — serializable configuration for an HTTP step.
2
3use serde::{Deserialize, Serialize};
4use serde_json::Value;
5
6/// Serializable configuration for an HTTP step.
7///
8/// # Examples
9///
10/// ```
11/// use ironflow_engine::config::HttpConfig;
12///
13/// let config = HttpConfig::get("https://api.example.com/health");
14/// ```
15#[derive(Debug, Clone, Serialize, Deserialize)]
16pub struct HttpConfig {
17    /// HTTP method (GET, POST, PUT, PATCH, DELETE).
18    pub method: String,
19    /// Request URL.
20    pub url: String,
21    /// Request headers.
22    pub headers: Vec<(String, String)>,
23    /// Request body as JSON.
24    pub body: Option<Value>,
25    /// Timeout in seconds (default: 30).
26    pub timeout_secs: Option<u64>,
27    /// When `true`, a failure of this step does not fail the run.
28    #[serde(default)]
29    pub allow_failure: bool,
30}
31
32impl HttpConfig {
33    /// Create a GET request config.
34    ///
35    /// # Examples
36    ///
37    /// ```
38    /// use ironflow_engine::config::HttpConfig;
39    ///
40    /// let config = HttpConfig::get("https://example.com");
41    /// assert_eq!(config.method, "GET");
42    /// ```
43    pub fn get(url: &str) -> Self {
44        Self::new("GET", url)
45    }
46
47    /// Create a POST request config.
48    pub fn post(url: &str) -> Self {
49        Self::new("POST", url)
50    }
51
52    /// Create a PUT request config.
53    pub fn put(url: &str) -> Self {
54        Self::new("PUT", url)
55    }
56
57    /// Create a PATCH request config.
58    pub fn patch(url: &str) -> Self {
59        Self::new("PATCH", url)
60    }
61
62    /// Create a DELETE request config.
63    pub fn delete(url: &str) -> Self {
64        Self::new("DELETE", url)
65    }
66
67    fn new(method: &str, url: &str) -> Self {
68        Self {
69            method: method.to_string(),
70            url: url.to_string(),
71            headers: Vec::new(),
72            body: None,
73            timeout_secs: None,
74            allow_failure: false,
75        }
76    }
77
78    /// Add a request header.
79    pub fn header(mut self, name: &str, value: &str) -> Self {
80        self.headers.push((name.to_string(), value.to_string()));
81        self
82    }
83
84    /// Set the request body as JSON.
85    pub fn json(mut self, body: Value) -> Self {
86        self.body = Some(body);
87        self
88    }
89
90    /// Set the timeout in seconds.
91    pub fn timeout_secs(mut self, secs: u64) -> Self {
92        self.timeout_secs = Some(secs);
93        self
94    }
95
96    /// Mark this step as allowed to fail without stopping the run.
97    ///
98    /// # Examples
99    ///
100    /// ```
101    /// use ironflow_engine::config::HttpConfig;
102    ///
103    /// let config = HttpConfig::get("https://example.com").allow_failure();
104    /// assert!(config.allow_failure);
105    /// ```
106    pub fn allow_failure(mut self) -> Self {
107        self.allow_failure = true;
108        self
109    }
110}
111
112#[cfg(test)]
113mod tests {
114    use super::*;
115    use serde_json::json;
116
117    #[test]
118    fn methods() {
119        assert_eq!(HttpConfig::get("http://x").method, "GET");
120        assert_eq!(HttpConfig::post("http://x").method, "POST");
121        assert_eq!(HttpConfig::put("http://x").method, "PUT");
122        assert_eq!(HttpConfig::patch("http://x").method, "PATCH");
123        assert_eq!(HttpConfig::delete("http://x").method, "DELETE");
124    }
125
126    #[test]
127    fn builder() {
128        let config = HttpConfig::post("http://api.example.com")
129            .header("Authorization", "Bearer token")
130            .json(json!({"key": "value"}))
131            .timeout_secs(10);
132
133        assert_eq!(config.headers.len(), 1);
134        assert!(config.body.is_some());
135        assert_eq!(config.timeout_secs, Some(10));
136    }
137}