1use reqwest::{
2 Method, Response,
3 header::{HeaderMap, HeaderValue},
4};
5use serde::{
6 Deserialize, Serialize,
7 de::{DeserializeOwned, Error},
8};
9use std::collections::HashMap;
10
11use crate::{
12 KiteConnect,
13 KiteConnectErrorKind::SerializationError,
14 constants::app_constants::*,
15 models::{KiteConnectError, KiteError},
16};
17
18#[derive(Debug, Clone, Serialize, Deserialize)]
19struct ApiResponse<T> {
20 status: String,
21 data: T,
22}
23
24#[derive(Debug, Clone, Serialize, Deserialize)]
25struct DataOnlyResponse<T> {
26 data: T,
27}
28
29pub enum RequestBody<T: Serialize> {
30 Form(T),
31 Json(T),
32}
33
34impl KiteConnect {
35 async fn do_envelope<T, K: Serialize>(
37 &self,
38 method: Method,
39 endpoint: &str,
40 query_params: Option<HashMap<String, String>>,
41 body: Option<RequestBody<K>>,
42 headers: Option<HeaderMap>,
43 ) -> Result<T, KiteConnectError>
44 where
45 T: DeserializeOwned,
46 {
47 let url = format!("{}{}", self.base_url, endpoint);
48 let mut request_headers = self.get_default_headers()?;
49
50 if let Some(ref token) = self.access_token {
52 request_headers.insert(
53 "Authorization",
54 HeaderValue::from_str(&format!("token {}:{}", self.api_key, token))?,
55 );
56 }
57
58 if let Some(custom_headers) = headers {
60 for (key, value) in custom_headers.iter() {
61 request_headers.insert(key, value.clone());
62 }
63 }
64
65 let mut request_builder = self
66 .http_client
67 .request(method, &url)
68 .headers(request_headers);
69
70 if let Some(query) = query_params {
72 request_builder = request_builder.query(&query);
73 }
74
75 if let Some(body) = body {
77 match body {
78 RequestBody::Form(form_params) => {
79 request_builder = request_builder.form(&form_params);
80 }
81 RequestBody::Json(json_body) => {
82 request_builder = request_builder.json(&json_body);
83 }
84 }
85 }
86
87 let response = request_builder.send().await?;
88 self.handle_response(response).await
89 }
90
91 async fn handle_response<T>(&self, response: Response) -> Result<T, KiteConnectError>
93 where
94 T: DeserializeOwned,
95 {
96 let status = response.status();
97 let response_text = response.text().await?;
98
99 if status.is_success() {
100 if let Ok(api_response) = serde_json::from_str::<ApiResponse<T>>(&response_text) {
102 Ok(api_response.data)
103 } else if let Ok(data_response) =
104 serde_json::from_str::<DataOnlyResponse<T>>(&response_text)
105 {
106 Ok(data_response.data)
107 } else if let Ok(result) = serde_json::from_str::<T>(&response_text) {
108 Ok(result)
109 } else if let Ok(result) =
110 serde_json::from_value(serde_json::Value::String(response_text.clone()))
111 {
112 Ok(result)
114 } else {
115 let type_name = std::any::type_name::<T>();
117
118 Err(KiteConnectError::new(SerializationError(Error::custom(
119 format!(
120 "Failed to parse response as {}. Response (first 500 chars): {}",
121 type_name,
122 &response_text.chars().take(500).collect::<String>()
123 ),
124 ))))
125 }
126 } else {
127 let error: KiteError = serde_json::from_str(&response_text)?;
129 Err(error.into())
130 }
131 }
132
133 fn get_default_headers(&self) -> Result<HeaderMap, KiteConnectError> {
135 let mut headers = HeaderMap::new();
136 headers.insert(
137 "X-Kite-Version",
138 HeaderValue::from_static(KITE_HEADER_VERSION),
139 );
140
141 let user_agent = HeaderValue::from_str(&format!(
142 "{}/{}",
143 KITE_CONNECT_RS_NAME, KITE_CONNECT_RS_VERSION
144 ))?;
145 headers.insert("User-Agent", user_agent);
146
147 Ok(headers)
148 }
149
150 pub async fn get<T>(&self, endpoint: &str) -> Result<T, KiteConnectError>
151 where
152 T: DeserializeOwned,
153 {
154 self.do_envelope::<T, ()>(Method::GET, endpoint, None, None, None)
155 .await
156 }
157
158 pub async fn put<T>(&self, endpoint: &str) -> Result<T, KiteConnectError>
159 where
160 T: DeserializeOwned,
161 {
162 self.do_envelope::<T, ()>(Method::PUT, endpoint, None, None, None)
163 .await
164 }
165 pub async fn post<T>(&self, endpoint: &str) -> Result<T, KiteConnectError>
166 where
167 T: DeserializeOwned,
168 {
169 self.do_envelope::<T, ()>(Method::POST, endpoint, None, None, None)
170 .await
171 }
172 pub async fn delete<T>(&self, endpoint: &str) -> Result<T, KiteConnectError>
173 where
174 T: DeserializeOwned,
175 {
176 self.do_envelope::<T, ()>(Method::DELETE, endpoint, None, None, None)
177 .await
178 }
179
180 pub async fn post_form<T, K: Serialize>(
182 &self,
183 endpoint: &str,
184 params: K,
185 ) -> Result<T, KiteConnectError>
186 where
187 T: DeserializeOwned,
188 {
189 self.do_envelope(
190 Method::POST,
191 endpoint,
192 None,
193 Some(RequestBody::Form(params)),
194 None,
195 )
196 .await
197 }
198
199 pub async fn post_json<T, K: Serialize>(
201 &self,
202 endpoint: &str,
203 json_body: K,
204 ) -> Result<T, KiteConnectError>
205 where
206 T: DeserializeOwned,
207 {
208 self.do_envelope(
209 Method::POST,
210 endpoint,
211 None,
212 Some(RequestBody::Json(json_body)),
213 None,
214 )
215 .await
216 }
217
218 pub async fn delete_form<T, K: Serialize>(
220 &self,
221 endpoint: &str,
222 params: K,
223 ) -> Result<T, KiteConnectError>
224 where
225 T: DeserializeOwned,
226 {
227 self.do_envelope(
228 Method::DELETE,
229 endpoint,
230 None,
231 Some(RequestBody::Form(params)),
232 None,
233 )
234 .await
235 }
236
237 pub async fn put_form<T, K: Serialize>(
239 &self,
240 endpoint: &str,
241 params: K,
242 ) -> Result<T, KiteConnectError>
243 where
244 T: DeserializeOwned,
245 {
246 self.do_envelope(
247 Method::PUT,
248 endpoint,
249 None,
250 Some(RequestBody::Form(params)),
251 None,
252 )
253 .await
254 }
255
256 pub async fn put_json<T, K: Serialize>(
258 &self,
259 endpoint: &str,
260 json_body: K,
261 ) -> Result<T, KiteConnectError>
262 where
263 T: DeserializeOwned,
264 {
265 self.do_envelope(
266 Method::PUT,
267 endpoint,
268 None,
269 Some(RequestBody::Json(json_body)),
270 None,
271 )
272 .await
273 }
274
275 pub async fn get_with_query<T>(
277 &self,
278 endpoint: &str,
279 params: HashMap<String, String>,
280 ) -> Result<T, KiteConnectError>
281 where
282 T: DeserializeOwned,
283 {
284 self.do_envelope::<T, ()>(Method::GET, endpoint, Some(params), None, None)
285 .await
286 }
287
288 pub async fn delete_with_query<T>(
290 &self,
291 endpoint: &str,
292 params: HashMap<String, String>,
293 ) -> Result<T, KiteConnectError>
294 where
295 T: DeserializeOwned,
296 {
297 self.do_envelope::<T, ()>(Method::DELETE, endpoint, Some(params), None, None)
298 .await
299 }
300}