botx_api/api/utils/
request_manager.rs

1use std::{fmt::{
2    Display,
3    Debug
4}, sync::Arc};
5
6use log::{error, info};
7use reqwest::{StatusCode, IntoUrl, header::CONTENT_TYPE};
8use serde::{Serialize, Deserialize};
9use async_lock::RwLock;
10
11use crate::api::{
12    result::{
13        BotXApiError,
14        ExpressResult,
15        BotXApiResult,
16    },
17    context::BotXApiContext, v2::token::api::token, models::FileResponse
18};
19
20#[derive(Debug)]
21pub struct MultipartPartData {
22    pub name: String,
23    pub file_name: Option<String>,
24    pub content: MultipartPartDataContent,
25    pub mime_type: Option<String>,
26}
27
28#[derive(Debug)]
29pub enum MultipartPartDataContent {
30    Bytes(Vec<u8>),
31    Text(String)
32}
33
34pub struct RequestManager {}
35
36impl RequestManager {
37    pub const JSON_CONTENT_TYPE: &str = "application/json";
38    pub const MULTIPART_CONTENT_TYPE: &str = "multipart/form-data";
39
40    pub async fn post<TRequest, TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, request: &TRequest, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
41    where
42        TRequest: Serialize,
43        for<'a> TResponse: Deserialize<'a> + Debug,
44        for<'a> TError: Deserialize<'a> + Debug,
45    {
46        log::info!("{request_name} request url [{url:?}]");
47        log::debug!("{request_name} request data [{}]", serde_json::to_string(request).unwrap());
48
49        let context_read_lock = context.read().await;
50
51        let raw_response = if context_read_lock.auth_token.is_some() {
52            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
53
54            let raw_response = context_read_lock.client.post(url)
55                .bearer_auth(auth_token)
56                .header(reqwest::header::CONTENT_TYPE, content_type.into())
57                .json(request)
58                .send()
59                .await
60                .map_err::<BotXApiError<TError>, _>(|e| {
61                    log::error!("{request_name}  request error:[{e:#?}]");
62                    e.into()
63                })?;
64                
65            drop(context_read_lock);
66
67            raw_response
68        } else {            
69            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
70
71            drop(context_read_lock);
72
73            let mut context_write_lock = context.write().await;
74
75            let token_response = token(&mut *context_write_lock).await;
76
77            let Ok(token_result) = token_response else {
78                error!("Не удалось повторить запрос с пере авторизацией");
79                return Err(BotXApiError::Unauthorized);
80            };
81
82            context_write_lock.auth_token = Some(token_result.token.clone());
83
84            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
85
86            let auth_token = token_result.token;
87
88            let raw_response = context_read_lock.client.post(url)
89                .bearer_auth(auth_token)
90                .header(reqwest::header::CONTENT_TYPE, content_type.into())
91                .json(request)
92                .send()
93                .await
94                .map_err::<BotXApiError<TError>, _>(|e| {
95                    log::error!("{request_name}  request error:[{e:#?}]");
96                    e.into()
97                })?;
98                
99            drop(context_read_lock);
100
101            raw_response
102        };
103    
104        let status_code = raw_response.status();
105        let response_body = raw_response.text()
106            .await
107            .map_err::<BotXApiError<TError>, _>(|e| {
108                log::error!("{request_name}  read response error:[{e:#?}]");
109                e.into()
110            })?;
111    
112        if status_code == StatusCode::UNAUTHORIZED {
113            log::debug!("{request_name}  request Unauthorized {response_body}");
114            return Err(BotXApiError::Unauthorized);
115        }
116    
117        let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
118            .map_err(|e| {
119                log::error!("{request_name} response body deserialization error: [{response_body}]");
120                BotXApiError::SerdeError(e)
121            })?;
122    
123        if !response.is_ok() {
124            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
125        } else {
126            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
127        }
128    
129        response.into()
130    } 
131
132    pub async fn put<TRequest, TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, request: &TRequest, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
133    where
134        TRequest: Serialize,
135        for<'a> TResponse: Deserialize<'a> + Debug,
136        for<'a> TError: Deserialize<'a> + Debug,
137    {
138        log::info!("{request_name} request url [{url:?}]");
139        log::debug!("{request_name} request data [{}]", serde_json::to_string(request).unwrap());
140
141        let context_read_lock = context.read().await;
142
143        let raw_response = if context_read_lock.auth_token.is_some() {
144            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
145
146            let raw_response = context_read_lock.client.put(url)
147                .bearer_auth(auth_token)
148                .header(reqwest::header::CONTENT_TYPE, content_type.into())
149                .json(request)
150                .send()
151                .await
152                .map_err::<BotXApiError<TError>, _>(|e| {
153                    log::error!("{request_name}  request error:[{e:#?}]");
154                    e.into()
155                })?;
156                
157            drop(context_read_lock);
158
159            raw_response
160        } else {            
161            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
162
163            drop(context_read_lock);
164
165            let mut context_write_lock = context.write().await;
166
167            let token_response = token(&mut *context_write_lock).await;
168
169            let Ok(token_result) = token_response else {
170                error!("Не удалось повторить запрос с пере авторизацией");
171                return Err(BotXApiError::Unauthorized);
172            };
173
174            context_write_lock.auth_token = Some(token_result.token.clone());
175
176            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
177
178            let auth_token = token_result.token;
179
180            let raw_response = context_read_lock.client.put(url)
181                .bearer_auth(auth_token)
182                .header(reqwest::header::CONTENT_TYPE, content_type.into())
183                .json(request)
184                .send()
185                .await
186                .map_err::<BotXApiError<TError>, _>(|e| {
187                    log::error!("{request_name}  request error:[{e:#?}]");
188                    e.into()
189                })?;
190                
191            drop(context_read_lock);
192
193            raw_response
194        };
195    
196        let status_code = raw_response.status();
197        let response_body = raw_response.text()
198            .await
199            .map_err::<BotXApiError<TError>, _>(|e| {
200                log::error!("{request_name}  read response error:[{e:#?}]");
201                e.into()
202            })?;
203    
204        if status_code == StatusCode::UNAUTHORIZED {
205            log::debug!("{request_name}  request Unauthorized {response_body}");
206            return Err(BotXApiError::Unauthorized);
207        }
208    
209        let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
210            .map_err(|e| {
211                log::error!("{request_name} response body deserialization error: [{response_body}]");
212                BotXApiError::SerdeError(e)
213            })?;
214    
215        if !response.is_ok() {
216            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
217        } else {
218            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
219        }
220    
221        response.into()
222    } 
223
224    pub async fn get<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
225    where
226        for<'a> TResponse: Deserialize<'a> + Debug,
227        for<'a> TError: Deserialize<'a> + Debug,
228    {
229        log::info!("{request_name} request url [{url:?}]");
230
231        let context_read_lock = context.read().await;
232
233        let raw_response = if context_read_lock.auth_token.is_some() {
234            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
235
236            let raw_response = context_read_lock.client.get(url)
237                .bearer_auth(auth_token)
238                .header(reqwest::header::CONTENT_TYPE, content_type.into())
239                .send()
240                .await
241                .map_err::<BotXApiError<TError>, _>(|e| {
242                    log::error!("{request_name}  request error:[{e:#?}]");
243                    e.into()
244                })?;
245                
246            drop(context_read_lock);
247
248            raw_response
249        } else {            
250            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
251
252            drop(context_read_lock);
253
254            let mut context_write_lock = context.write().await;
255
256            let token_response = token(&mut *context_write_lock).await;
257
258            let Ok(token_result) = token_response else {
259                error!("Не удалось повторить запрос с пере авторизацией");
260                return Err(BotXApiError::Unauthorized);
261            };
262
263            context_write_lock.auth_token = Some(token_result.token.clone());
264
265            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
266
267            let auth_token = token_result.token;
268
269            let raw_response = context_read_lock.client.get(url)
270                .bearer_auth(auth_token)
271                .header(reqwest::header::CONTENT_TYPE, content_type.into())
272                .send()
273                .await
274                .map_err::<BotXApiError<TError>, _>(|e| {
275                    log::error!("{request_name}  request error:[{e:#?}]");
276                    e.into()
277                })?;
278                
279            drop(context_read_lock);
280
281            raw_response
282        };
283    
284        let status_code = raw_response.status();
285        let response_body = raw_response.text()
286            .await
287            .map_err::<BotXApiError<TError>, _>(|e| {
288                log::error!("{request_name}  read response error:[{e:#?}]");
289                e.into()
290            })?;
291    
292        if status_code == StatusCode::UNAUTHORIZED {
293            log::debug!("{request_name}  request Unauthorized {response_body}");
294            return Err(BotXApiError::Unauthorized);
295        }
296    
297        let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
298            .map_err(|e| {
299                log::error!("{request_name} response body deserialization error: [{response_body}]");
300                BotXApiError::SerdeError(e)
301            })?;
302    
303        if !response.is_ok() {
304            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
305        } else {
306            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
307        }
308    
309        response.into()
310    }
311
312    pub async fn get_file<TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<FileResponse, TError>
313    where
314        for<'a> TError: Deserialize<'a> + Debug,
315    {
316        log::info!("{request_name} request url [{url:?}]");
317
318        let context_read_lock = context.read().await;
319
320        let raw_response = if context_read_lock.auth_token.is_some() {
321            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
322
323            let raw_response = context_read_lock.client.get(url)
324                .bearer_auth(auth_token)
325                .header(reqwest::header::CONTENT_TYPE, content_type.into())
326                .send()
327                .await
328                .map_err::<BotXApiError<TError>, _>(|e| {
329                    log::error!("{request_name}  request error:[{e:#?}]");
330                    e.into()
331                })?;
332                
333            drop(context_read_lock);
334
335            raw_response
336        } else {            
337            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
338
339            drop(context_read_lock);
340
341            let mut context_write_lock = context.write().await;
342
343            let token_response = token(&mut *context_write_lock).await;
344
345            let Ok(token_result) = token_response else {
346                error!("Не удалось повторить запрос с пере авторизацией");
347                return Err(BotXApiError::Unauthorized);
348            };
349
350            context_write_lock.auth_token = Some(token_result.token.clone());
351
352            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
353
354            let auth_token = token_result.token;
355
356            let raw_response = context_read_lock.client.get(url)
357                .bearer_auth(auth_token)
358                .header(reqwest::header::CONTENT_TYPE, content_type.into())
359                .send()
360                .await
361                .map_err::<BotXApiError<TError>, _>(|e| {
362                    log::error!("{request_name}  request error:[{e:#?}]");
363                    e.into()
364                })?;
365                
366            drop(context_read_lock);
367
368            raw_response
369        };
370    
371        let status_code = raw_response.status();
372
373        // Нельзя сделать проверку на 2xx статусы, т.к. есть ошибка со статусом 204 (файл удален)
374        let result = if [200u16, 201u16].contains(&raw_response.status().as_u16()) {
375            let content_type = raw_response.headers()
376                .get(CONTENT_TYPE)
377                .map(|x| x.to_str()
378                    .unwrap()
379                    .to_string())
380                .unwrap_or("text/plain".to_string());
381            
382            let data = raw_response.bytes()
383                .await
384                .map_err::<BotXApiError<TError>, _>(|e| {
385                    log::error!("{request_name}  read response error:[{e:#?}]");
386                    e.into()
387                })?
388                .to_vec();
389
390            ExpressResult::Ok(FileResponse { content_type: serde_json::from_str(&*format!("\"{content_type}\"")).unwrap(), data })
391        } else {
392            let response_body = raw_response.text()
393                .await
394                .map_err::<BotXApiError<TError>, _>(|e| {
395                    log::error!("{request_name}  read response error:[{e:#?}]");
396                    e.into()
397                })?;
398
399            if status_code == StatusCode::UNAUTHORIZED {
400                log::debug!("{request_name} request Unauthorized {response_body}");
401                return Err(BotXApiError::Unauthorized);
402            }
403
404            let response_error = serde_json::from_str::<TError>(&*response_body).map_err(|e| {
405                    log::error!("{request_name} response body deserialization error: [{response_body}]");
406                    BotXApiError::SerdeError(e)
407                })?;
408    
409            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response_error:#?}]");
410        
411            ExpressResult::Err(response_error)
412        };
413
414        result.into()
415    }
416
417    pub async fn get_csv<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<Vec<TResponse>, TError>
418    where
419        for<'a> TResponse: Deserialize<'a> + Debug,
420        for<'a> TError: Deserialize<'a> + Debug,
421    {
422        log::info!("{request_name} request url [{url:?}]");
423
424        let context_read_lock = context.read().await;
425
426        let raw_response = if context_read_lock.auth_token.is_some() {
427            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
428
429            let raw_response = context_read_lock.client.get(url)
430                .bearer_auth(auth_token)
431                .header(reqwest::header::CONTENT_TYPE, content_type.into())
432                .send()
433                .await
434                .map_err::<BotXApiError<TError>, _>(|e| {
435                    log::error!("{request_name}  request error:[{e:#?}]");
436                    e.into()
437                })?;
438                
439            drop(context_read_lock);
440
441            raw_response
442        } else {            
443            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
444
445            drop(context_read_lock);
446
447            let mut context_write_lock = context.write().await;
448
449            let token_response = token(&mut *context_write_lock).await;
450
451            let Ok(token_result) = token_response else {
452                error!("Не удалось повторить запрос с пере авторизацией");
453                return Err(BotXApiError::Unauthorized);
454            };
455
456            context_write_lock.auth_token = Some(token_result.token.clone());
457
458            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
459
460            let auth_token = token_result.token;
461
462            let raw_response = context_read_lock.client.get(url)
463                .bearer_auth(auth_token)
464                .header(reqwest::header::CONTENT_TYPE, content_type.into())
465                .send()
466                .await
467                .map_err::<BotXApiError<TError>, _>(|e| {
468                    log::error!("{request_name}  request error:[{e:#?}]");
469                    e.into()
470                })?;
471                
472            drop(context_read_lock);
473
474            raw_response
475        };
476    
477        let status_code = raw_response.status();
478        let response_body = raw_response.text()
479            .await
480            .map_err::<BotXApiError<TError>, _>(|e| {
481                log::error!("{request_name}  read response error:[{e:#?}]");
482                e.into()
483            })?;
484    
485        if status_code == StatusCode::UNAUTHORIZED {
486            log::debug!("{request_name}  request Unauthorized {response_body}");
487            return Err(BotXApiError::Unauthorized);
488        }
489
490        if status_code.is_success() {
491            let mut reader = csv::Reader::from_reader(response_body.as_bytes());
492        
493            let mut rows = vec![];
494            for record in reader.deserialize() {
495                let record: Result::<TResponse, _> = record;
496                match record {
497                    Ok(row) => rows.push(row),
498                    Err(err) => log::error!("Invalid data format, skip row:[{:?}]", err),
499                }
500            }
501
502            return ExpressResult::<Vec::<TResponse>, TError>::Ok(rows).into();
503        }
504    
505        let response = serde_json::from_str::<ExpressResult<Vec<TResponse>, TError>>(&*response_body)
506            .map_err(|e| {
507                log::error!("{request_name} response body deserialization error: [{response_body}]");
508                BotXApiError::SerdeError(e)
509            })?;
510    
511        if !response.is_ok() {
512            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
513        } else {
514            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
515        }
516    
517        response.into()
518    }
519
520    pub async fn delete<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, content_type: impl Into<String> + Display, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
521    where
522        for<'a> TResponse: Deserialize<'a> + Debug,
523        for<'a> TError: Deserialize<'a> + Debug,
524    {
525        log::info!("{request_name} request url [{url:?}]");
526
527        let context_read_lock = context.read().await;
528
529        let raw_response = if context_read_lock.auth_token.is_some() {
530            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
531
532            let raw_response = context_read_lock.client.delete(url)
533                .bearer_auth(auth_token)
534                .header(reqwest::header::CONTENT_TYPE, content_type.into())
535                .send()
536                .await
537                .map_err::<BotXApiError<TError>, _>(|e| {
538                    log::error!("{request_name}  request error:[{e:#?}]");
539                    e.into()
540                })?;
541                
542            drop(context_read_lock);
543
544            raw_response
545        } else {            
546            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
547
548            drop(context_read_lock);
549
550            let mut context_write_lock = context.write().await;
551
552            let token_response = token(&mut *context_write_lock).await;
553
554            let Ok(token_result) = token_response else {
555                error!("Не удалось повторить запрос с пере авторизацией");
556                return Err(BotXApiError::Unauthorized);
557            };
558
559            context_write_lock.auth_token = Some(token_result.token.clone());
560
561            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
562
563            let auth_token = token_result.token;
564
565            let raw_response = context_read_lock.client.delete(url)
566                .bearer_auth(auth_token)
567                .header(reqwest::header::CONTENT_TYPE, content_type.into())
568                .send()
569                .await
570                .map_err::<BotXApiError<TError>, _>(|e| {
571                    log::error!("{request_name}  request error:[{e:#?}]");
572                    e.into()
573                })?;
574                
575            drop(context_read_lock);
576
577            raw_response
578        };
579    
580        let status_code = raw_response.status();
581        let response_body = raw_response.text()
582            .await
583            .map_err::<BotXApiError<TError>, _>(|e| {
584                log::error!("{request_name}  read response error:[{e:#?}]");
585                e.into()
586            })?;
587    
588        if status_code == StatusCode::UNAUTHORIZED {
589            log::debug!("{request_name}  request Unauthorized {response_body}");
590            return Err(BotXApiError::Unauthorized);
591        }
592    
593        let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
594            .map_err(|e| {
595                log::error!("{request_name} response body deserialization error: [{response_body}]");
596                BotXApiError::SerdeError(e)
597            })?;
598    
599        if !response.is_ok() {
600            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
601        } else {
602            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
603        }
604    
605        response.into()
606    }
607
608    pub async fn post_multipart<TResponse, TError>(request_name: impl Into<String> + Display, url: impl IntoUrl + Debug, data: Vec<MultipartPartData>, context: &Arc<RwLock<BotXApiContext>>) -> BotXApiResult<TResponse, TError>
609    where
610        for<'a> TResponse: Deserialize<'a> + Debug,
611        for<'a> TError: Deserialize<'a> + Debug,
612    {
613        log::info!("{request_name} request url [{url:?}]");
614        log::debug!("{request_name} request data [{:#?}]", data);
615
616        let mut form = reqwest::multipart::Form::new();
617
618        for data in data.into_iter() {
619            let part = match data.content {
620                MultipartPartDataContent::Bytes(bytes) => reqwest::multipart::Part::bytes(bytes),
621                MultipartPartDataContent::Text(text) => reqwest::multipart::Part::text(text),
622            };
623            
624            let part = if let Some(file_name) = data.file_name {
625                part.file_name(file_name)
626            } else {
627                part
628            };
629
630            let part = if let Some(content_type) = data.mime_type {
631                part.mime_str(&*content_type).unwrap()
632            } else {
633                part
634            };
635
636            form = form.part(data.name, part);
637        }
638
639        log::debug!("{:#?}", form);
640
641        let context_read_lock = context.read().await;
642
643        let raw_response = if context_read_lock.auth_token.is_some() {
644            let auth_token = context_read_lock.auth_token.as_ref().map(|x| x.clone()).unwrap();
645
646            let raw_response = context_read_lock.client.post(url)
647                .bearer_auth(auth_token)
648                .multipart(form)
649                .send()
650                .await
651                .map_err::<BotXApiError<TError>, _>(|e| {
652                    log::error!("{request_name}  request error:[{e:#?}]");
653                    e.into()
654                })?;
655                
656            drop(context_read_lock);
657
658            raw_response
659        } else {            
660            info!("Не найден токен авторизации в контексте бота. Пере запрашиваем токен авторизации");
661
662            drop(context_read_lock);
663
664            let mut context_write_lock = context.write().await;
665
666            let token_response = token(&mut *context_write_lock).await;
667
668            let Ok(token_result) = token_response else {
669                error!("Не удалось повторить запрос с пере авторизацией");
670                return Err(BotXApiError::Unauthorized);
671            };
672
673            context_write_lock.auth_token = Some(token_result.token.clone());
674
675            let context_read_lock = async_lock::RwLockWriteGuard::<'_, BotXApiContext>::downgrade(context_write_lock);
676
677            let auth_token = token_result.token;
678
679            let raw_response = context_read_lock.client.post(url)
680                .bearer_auth(auth_token)
681                .multipart(form)
682                .send()
683                .await
684                .map_err::<BotXApiError<TError>, _>(|e| {
685                    log::error!("{request_name}  request error:[{e:#?}]");
686                    e.into()
687                })?;
688                
689            drop(context_read_lock);
690
691            raw_response
692        };
693    
694        let status_code = raw_response.status();
695        let response_body = raw_response.text()
696            .await
697            .map_err::<BotXApiError<TError>, _>(|e| {
698                log::error!("{request_name}  read response error:[{e:#?}]");
699                e.into()
700            })?;
701    
702        if status_code == StatusCode::UNAUTHORIZED {
703            log::debug!("{request_name}  request Unauthorized {response_body}");
704            return Err(BotXApiError::Unauthorized);
705        }
706    
707        let response = serde_json::from_str::<ExpressResult<TResponse, TError>>(&*response_body)
708            .map_err(|e| {
709                log::error!("{request_name} response body deserialization error: [{response_body}]");
710                BotXApiError::SerdeError(e)
711            })?;
712    
713        if !response.is_ok() {
714            log::error!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
715        } else {
716            log::debug!("{request_name} response status:[{status_code}] raw body:[{response_body}] deserialized body:[{response:#?}]");
717        }
718    
719        response.into()
720    } 
721}