mattermost_api_rust_driver/api/
mod.rs

1#![allow(dead_code)]
2
3pub mod users;
4pub mod auth;
5
6use reqwest::Method;
7use serde::Deserialize;
8use thiserror::Error;
9
10pub struct ApiClient {
11    client: reqwest::Client,
12    base_url: String,
13}
14
15// Обновленная структура ошибки API
16#[derive(Debug, Error)]
17pub enum ApiError {
18    #[error("Request failed: {0}")]
19    RequestError(#[from] reqwest::Error),
20
21    #[error("Server returned error: {status_code} - {message}")]
22    ServerError {
23        id: String,
24        message: String,
25        detailed_error: String,
26        request_id: String,
27        status_code: u16,
28    },
29
30    #[error("Unsupported HTTP method")]
31    UnsupportedMethod,
32}
33
34// Структура для десериализации ответа сервера при ошибке
35#[derive(Deserialize)]
36pub struct ServerErrorResponse {
37    id: String,
38    message: String,
39    detailed_error: String,
40    request_id: String,
41}
42
43// ApiClient с универсальным запросом
44impl ApiClient {
45    pub fn new(base_url: String) -> Result<Self, reqwest::Error> {
46        let client = reqwest::Client::new();
47        println!("{}", base_url);
48        Ok(ApiClient { client, base_url })
49    }
50    pub async fn send_request<T: for<'de> Deserialize<'de>>(
51        &self,
52        method: Method,
53        path: &str,
54        body: Option<impl serde::Serialize>, // Данные для POST/PUT
55    ) -> Result<T, ApiError> {
56        let url = self.get_api_route(path); // Генерация полного URL
57        println!("{} {}", method.as_str(), url);
58
59        let client = &self.client;
60
61        // Отправляем запрос в зависимости от метода
62        let request = match method {
63            Method::GET => client.get(&url),
64            Method::POST => {
65                let mut req = client.post(&url);
66                if let Some(b) = body {
67                    req = req.json(&b);
68                }
69                req
70            }
71
72            Method::PUT => {
73                let mut req = client.put(&url);
74                if let Some(b) = body {
75                    req = req.json(&b);
76                }
77                req
78            }
79
80            Method::DELETE => client.delete(&url),
81
82            // Возвращаем кастомную ошибку
83            _ => return Err(ApiError::UnsupportedMethod),
84        };
85
86        // Отправляем запрос и обрабатываем результат
87        let response = request.send().await?;
88
89        self.handle_response(response).await
90    }
91
92    async fn handle_response<T: for<'de> Deserialize<'de>>(
93        &self,
94        response: reqwest::Response,
95    ) -> Result<T, ApiError> {
96        let status = response.status();
97
98        if status.is_success() {
99            Ok(response.json::<T>().await?)
100        } else {
101            let error_response = response.json::<ServerErrorResponse>().await?;
102            Err(ApiError::ServerError {
103                id: error_response.id,
104                message: error_response.message,
105                detailed_error: error_response.detailed_error,
106                request_id: error_response.request_id,
107                status_code: status.into(),
108            })
109        }
110    }
111
112    pub fn get_route(&self, path: &str) -> String {
113        format!("{}{}", self.base_url, path)
114    }
115
116    pub fn get_api_route(&self, path: &str) -> String {
117        format!("{}/api/v4{}", self.base_url, path)
118    }
119}