vectorizer_sdk/
http_transport.rs

1//! HTTP transport implementation using reqwest
2
3use crate::error::{VectorizerError, Result};
4use crate::transport::{Protocol, Transport};
5use async_trait::async_trait;
6use reqwest::{Client, ClientBuilder, header::{HeaderMap, HeaderValue, CONTENT_TYPE}};
7use serde_json::Value;
8
9/// HTTP transport client
10pub struct HttpTransport {
11    client: Client,
12    base_url: String,
13}
14
15impl HttpTransport {
16    /// Create a new HTTP transport
17    pub fn new(base_url: &str, api_key: Option<&str>, timeout_secs: u64) -> Result<Self> {
18        let mut headers = HeaderMap::new();
19        headers.insert(CONTENT_TYPE, HeaderValue::from_static("application/json"));
20
21        if let Some(key) = api_key {
22            headers.insert(
23                "Authorization",
24                HeaderValue::from_str(&format!("Bearer {}", key))
25                    .map_err(|e| VectorizerError::configuration(format!("Invalid API key: {}", e)))?,
26            );
27        }
28
29        let client = ClientBuilder::new()
30            .timeout(std::time::Duration::from_secs(timeout_secs))
31            .default_headers(headers)
32            .build()
33            .map_err(|e| VectorizerError::configuration(format!("Failed to create HTTP client: {}", e)))?;
34
35        Ok(Self {
36            client,
37            base_url: base_url.to_string(),
38        })
39    }
40
41    /// Make a generic request
42    async fn request(&self, method: &str, path: &str, body: Option<&Value>) -> Result<String> {
43        let url = format!("{}{}", self.base_url, path);
44
45        let mut request = match method {
46            "GET" => self.client.get(&url),
47            "POST" => self.client.post(&url),
48            "PUT" => self.client.put(&url),
49            "DELETE" => self.client.delete(&url),
50            _ => return Err(VectorizerError::configuration(format!("Unsupported HTTP method: {}", method))),
51        };
52
53        if let Some(data) = body {
54            request = request.json(data);
55        }
56
57        let response = request.send().await
58            .map_err(|e| VectorizerError::network(format!("HTTP request failed: {}", e)))?;
59
60        if !response.status().is_success() {
61            let status = response.status();
62            let error_text = response.text().await.unwrap_or_else(|_| "Unknown error".to_string());
63            return Err(VectorizerError::server(format!("HTTP {}: {}", status, error_text)));
64        }
65
66        response.text().await
67            .map_err(|e| VectorizerError::network(format!("Failed to read response: {}", e)))
68    }
69}
70
71#[async_trait]
72impl Transport for HttpTransport {
73    async fn get(&self, path: &str) -> Result<String> {
74        self.request("GET", path, None).await
75    }
76
77    async fn post(&self, path: &str, data: Option<&Value>) -> Result<String> {
78        self.request("POST", path, data).await
79    }
80
81    async fn put(&self, path: &str, data: Option<&Value>) -> Result<String> {
82        self.request("PUT", path, data).await
83    }
84
85    async fn delete(&self, path: &str) -> Result<String> {
86        self.request("DELETE", path, None).await
87    }
88
89    fn protocol(&self) -> Protocol {
90        Protocol::Http
91    }
92}
93