1use std::time::Duration;
2
3use anyhow::Result;
4use reqwest::{Client, StatusCode, Url};
5
6pub struct HttpConnector {
8 client: Client,
9}
10
11impl HttpConnector {
12 pub fn new() -> Result<Self> {
14 let client = Client::builder().timeout(Duration::from_secs(30)).build()?;
15
16 Ok(Self { client })
17 }
18
19 pub fn with_timeout(timeout: Duration) -> Result<Self> {
21 let client = Client::builder().timeout(timeout).build()?;
22
23 Ok(Self { client })
24 }
25
26 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 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 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 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}