vx_core/
http.rs

1//! HTTP utilities for tool version fetching and downloading
2
3use crate::Result;
4use reqwest::Client;
5use serde_json::Value;
6use std::sync::OnceLock;
7
8/// Global HTTP client instance
9static HTTP_CLIENT: OnceLock<Client> = OnceLock::new();
10
11/// Get the global HTTP client
12pub 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
22/// HTTP utilities for common operations
23pub struct HttpUtils;
24
25impl HttpUtils {
26    /// Fetch JSON from a URL
27    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    /// Download a file to bytes
35    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    /// Download a file (alias for download_bytes)
43    pub async fn download_file(url: &str) -> Result<Vec<u8>> {
44        Self::download_bytes(url).await
45    }
46
47    /// Check if a URL is accessible (HEAD request)
48    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        // Client is configured with timeout
65    }
66
67    #[tokio::test]
68    async fn test_fetch_json_mock() {
69        // This would require a mock server in a real test
70        // For now, just test that the function exists and compiles
71        let result = HttpUtils::fetch_json("https://httpbin.org/json").await;
72        // Don't assert success since we don't want network dependency in tests
73        let _ = result;
74    }
75}