1use crate::Result;
4use reqwest::Client;
5use serde_json::Value;
6use std::sync::OnceLock;
7
8static HTTP_CLIENT: OnceLock<Client> = OnceLock::new();
10
11pub fn get_http_client() -> &'static Client {
13 HTTP_CLIENT.get_or_init(|| {
14 Client::builder()
15 .user_agent("vx-tool-manager/1.0")
16 .timeout(std::time::Duration::from_secs(30))
17 .build()
18 .expect("Failed to create HTTP client")
19 })
20}
21
22pub struct HttpUtils;
24
25impl HttpUtils {
26 pub async fn fetch_json(url: &str) -> Result<Value> {
28 let client = get_http_client();
29 let response = client.get(url).send().await?;
30 let json = response.json().await?;
31 Ok(json)
32 }
33
34 pub async fn download_bytes(url: &str) -> Result<Vec<u8>> {
36 let client = get_http_client();
37 let response = client.get(url).send().await?;
38 let bytes = response.bytes().await?;
39 Ok(bytes.to_vec())
40 }
41
42 pub async fn download_file(url: &str) -> Result<Vec<u8>> {
44 Self::download_bytes(url).await
45 }
46
47 pub async fn check_url(url: &str) -> Result<bool> {
49 let client = get_http_client();
50 match client.head(url).send().await {
51 Ok(response) => Ok(response.status().is_success()),
52 Err(_) => Ok(false),
53 }
54 }
55}
56
57#[cfg(test)]
58mod tests {
59 use super::*;
60
61 #[test]
62 fn test_http_client_creation() {
63 let _client = get_http_client();
64 }
66
67 #[tokio::test]
68 async fn test_fetch_json_mock() {
69 let result = HttpUtils::fetch_json("https://httpbin.org/json").await;
72 let _ = result;
74 }
75}