terminal_jarvis/api/
api_client.rs1#![allow(dead_code)]
2
3use crate::api::api_base::ApiBase;
10use anyhow::{anyhow, Result};
11use reqwest::{Client, ClientBuilder, Response};
12use serde::de::DeserializeOwned;
13use std::time::Duration;
14
15pub struct ApiClient {
17 client: Client,
18 config: ApiBase,
19}
20
21impl Default for ApiClient {
22 fn default() -> Self {
23 Self::new()
24 }
25}
26
27impl ApiClient {
28 pub fn new() -> Self {
29 let config = ApiBase::new();
30 let client = ClientBuilder::new()
31 .timeout(Duration::from_secs(config.timeout_seconds))
32 .build()
33 .expect("Failed to create HTTP client");
34
35 Self { client, config }
36 }
37
38 pub fn with_config(config: ApiBase) -> Self {
39 let client = ClientBuilder::new()
40 .timeout(Duration::from_secs(config.timeout_seconds))
41 .build()
42 .expect("Failed to create HTTP client");
43
44 Self { client, config }
45 }
46
47 pub async fn get<T>(&self, path: &str) -> Result<T>
49 where
50 T: DeserializeOwned,
51 {
52 let url = self.config.endpoint_url(path);
53 let response = self.client.get(&url).send().await?;
54
55 self.handle_response(response).await
56 }
57
58 pub async fn post<T, B>(&self, path: &str, body: &B) -> Result<T>
60 where
61 T: DeserializeOwned,
62 B: serde::Serialize,
63 {
64 let url = self.config.endpoint_url(path);
65 let response = self.client.post(&url).json(body).send().await?;
66
67 self.handle_response(response).await
68 }
69
70 pub async fn put<T, B>(&self, path: &str, body: &B) -> Result<T>
72 where
73 T: DeserializeOwned,
74 B: serde::Serialize,
75 {
76 let url = self.config.endpoint_url(path);
77 let response = self.client.put(&url).json(body).send().await?;
78
79 self.handle_response(response).await
80 }
81
82 pub async fn delete<T>(&self, path: &str) -> Result<T>
84 where
85 T: DeserializeOwned,
86 {
87 let url = self.config.endpoint_url(path);
88 let response = self.client.delete(&url).send().await?;
89
90 self.handle_response(response).await
91 }
92
93 async fn handle_response<T>(&self, response: Response) -> Result<T>
95 where
96 T: DeserializeOwned,
97 {
98 let status = response.status();
99
100 if !status.is_success() {
101 let error_text = response
102 .text()
103 .await
104 .unwrap_or_else(|_| "Unknown error".to_string());
105 return Err(anyhow!("HTTP {} error: {}", status, error_text));
106 }
107
108 let json = response.json::<T>().await?;
109 Ok(json)
110 }
111
112 pub fn config(&self) -> &ApiBase {
114 &self.config
115 }
116}