sal_net/
http.rs

1use std::time::Duration;
2
3use anyhow::Result;
4use reqwest::{Client, StatusCode, Url};
5
6/// HTTP Connectivity module for checking HTTP/HTTPS connections
7pub struct HttpConnector {
8    client: Client,
9}
10
11impl HttpConnector {
12    /// Create a new HTTP connector with the default configuration
13    pub fn new() -> Result<Self> {
14        let client = Client::builder().timeout(Duration::from_secs(30)).build()?;
15
16        Ok(Self { client })
17    }
18
19    /// Create a new HTTP connector with a custom timeout
20    pub fn with_timeout(timeout: Duration) -> Result<Self> {
21        let client = Client::builder().timeout(timeout).build()?;
22
23        Ok(Self { client })
24    }
25
26    /// Check if a URL is reachable
27    pub async fn check_url<U: AsRef<str>>(&self, url: U) -> Result<bool> {
28        let url_str = url.as_ref();
29        let url = Url::parse(url_str)?;
30
31        let result = self.client.head(url).send().await;
32
33        Ok(result.is_ok())
34    }
35
36    /// Check a URL and return the status code if reachable
37    pub async fn check_status<U: AsRef<str>>(&self, url: U) -> Result<Option<StatusCode>> {
38        let url_str = url.as_ref();
39        let url = Url::parse(url_str)?;
40
41        let result = self.client.head(url).send().await;
42
43        match result {
44            Ok(response) => Ok(Some(response.status())),
45            Err(_) => Ok(None),
46        }
47    }
48
49    /// Get the content of a URL
50    pub async fn get_content<U: AsRef<str>>(&self, url: U) -> Result<String> {
51        let url_str = url.as_ref();
52        let url = Url::parse(url_str)?;
53
54        let response = self.client.get(url).send().await?;
55
56        if !response.status().is_success() {
57            return Err(anyhow::anyhow!(
58                "HTTP request failed with status: {}",
59                response.status()
60            ));
61        }
62
63        let content = response.text().await?;
64        Ok(content)
65    }
66
67    /// Verify that a URL responds with a specific status code
68    pub async fn verify_status<U: AsRef<str>>(
69        &self,
70        url: U,
71        expected_status: StatusCode,
72    ) -> Result<bool> {
73        match self.check_status(url).await? {
74            Some(status) => Ok(status == expected_status),
75            None => Ok(false),
76        }
77    }
78}
79
80impl Default for HttpConnector {
81    fn default() -> Self {
82        Self::new().expect("Failed to create default HttpConnector")
83    }
84}