Skip to main content

rsiot/components_config/http_client/
request_input.rs

1use std::fmt::Debug;
2
3use tracing::warn;
4
5use crate::{
6    components_config::http_general::HttpDataBound,
7    message::MsgDataBound,
8    serde_utils::{SerdeAlg, SerdeAlgKind},
9};
10
11use super::{
12    FnCreateRequest, FnProcessResponseError, FnProcessResponseSuccess, MsgRequest, MsgResponse,
13    RequestKind,
14};
15
16// ANCHOR: RequestInputConfig
17/// Параметры запроса на основе входящего потока сообщений
18#[derive(Clone, Debug)]
19pub struct RequestInputConfig<TMsg, TServerToClient, TClientToServer> {
20    /// Алгоритм сериализации / десериализации
21    pub serde_alg: SerdeAlgKind,
22    /// Тип HTTP-запроса
23    pub request_kind: RequestKind,
24    /// Путь к ресурсу
25    pub endpoint: String,
26    /// Функция выдает параметры запроса, на основе входных сообщений
27    pub fn_create_request: FnCreateRequest<TMsg, TClientToServer>,
28    /// Функция обработки корректного ответа
29    pub fn_process_response_success: FnProcessResponseSuccess<TMsg, TServerToClient>,
30    /// Функция обработки ошибки ответа
31    pub fn_process_response_error: FnProcessResponseError<TMsg>,
32}
33// ANCHOR: RequestInputConfig
34
35/// Трейт для реализации запросов на основе входящего потока сообщений
36pub trait RequestInput<TMsg>
37where
38    Self: Debug + Send + Sync,
39{
40    /// Создание запроса
41    fn create_request(&self, msg: &TMsg) -> Option<MsgRequest>;
42
43    /// Обработка ответа
44    fn process_response(&self, msg_response: &MsgResponse) -> Option<Vec<TMsg>>;
45
46    /// Поддержка клонирования
47    fn clone_dyn(&self) -> Box<dyn RequestInput<TMsg>>;
48}
49
50impl<TMsg> Clone for Box<dyn RequestInput<TMsg>> {
51    fn clone(&self) -> Self {
52        self.clone_dyn()
53    }
54}
55
56impl<TMsg, TServerToClient, TClientToServer> RequestInput<TMsg>
57    for RequestInputConfig<TMsg, TServerToClient, TClientToServer>
58where
59    TMsg: 'static + MsgDataBound,
60    TClientToServer: 'static + HttpDataBound,
61    TServerToClient: 'static + HttpDataBound,
62{
63    fn create_request(&self, msg: &TMsg) -> Option<MsgRequest> {
64        let body = (self.fn_create_request)(msg)?;
65
66        let serde_alg = SerdeAlg::new(self.serde_alg);
67        let body_bytes = serde_alg.serialize(&body);
68        let body_bytes = match body_bytes {
69            Ok(v) => v,
70            Err(e) => {
71                warn!("Error serializing http request: {}", e);
72                return None;
73            }
74        };
75
76        let msg_request = MsgRequest::new(self.request_kind, self.endpoint.clone(), body_bytes);
77        Some(msg_request)
78    }
79
80    fn process_response(&self, msg_response: &MsgResponse) -> Option<Vec<TMsg>> {
81        if msg_response.get_endpoint() != &self.endpoint {
82            return None;
83        }
84
85        super::process_response::process_response(
86            self.serde_alg,
87            self.fn_process_response_success,
88            self.fn_process_response_error,
89            msg_response,
90        )
91    }
92
93    fn clone_dyn(&self) -> Box<dyn RequestInput<TMsg>> {
94        Box::new(self.clone())
95    }
96}