bw_web_api_rs/
client.rs

1use reqwest::Client;
2use serde::{de::DeserializeOwned, Serialize};
3use std::time::Duration;
4
5use crate::config::ApiConfig;
6use crate::error::ApiError;
7use crate::endpoints::Endpoint;
8
9pub struct ApiClient {
10    client: reqwest::Client,
11    config: ApiConfig,
12}
13
14impl ApiClient {
15    pub fn new(config: ApiConfig) -> Result<Self, ApiError> {
16        let client = Client::builder()
17            .timeout(Duration::from_secs(30))
18            .build()
19            .map_err(|e| ApiError::ClientCreationError(e.to_string()))?;
20
21        Ok(Self { client, config })
22    }
23
24    pub async fn request<E>(&self, endpoint: &E, params: &E::Request) -> Result<E::Response, ApiError>
25    where
26        E: Endpoint,
27        E::Request: Serialize,
28        E::Response: DeserializeOwned,
29    {
30        let url = format!("{}{}", self.config.base_url, endpoint.endpoint());
31        
32        let mut request_builder = self.client.get(&url);
33        request_builder = request_builder.header("Accept", "application/json");
34
35        if let Some(ref api_key) = self.config.api_key {
36            request_builder = request_builder.header("x-api-key", format!("Bearer {}", api_key));
37        }
38
39        let response = request_builder
40            .query(params)
41            .send()
42            .await?;
43        
44        if !response.status().is_success() {
45            return Err(ApiError::ApiError { 
46                status: response.status().as_u16(),
47                message: response.text().await.unwrap_or_default(),
48            });
49        }
50
51        let text = response.text().await?;
52        
53        serde_json::from_str(&text)
54            .map_err(|e| ApiError::DeserializationError(
55                format!("Failed to deserialize: {}. Response starts with: {}", 
56                    e, 
57                    &text[..text.len().min(200)]
58                )
59            ))
60    }
61}