Skip to main content

Module cmp_http_client

Module cmp_http_client 

Source
Expand description

Компонент для обмена данными со сторонними системами по протоколу HTTP.

Версия для выполнения на платформах x86-64 и ARM. Реализован на основе крейта reqwest.

Можно выполнять GET, POST, PUT и DELETE методы HTTP.

§Структура

MsgBusInputHttpClientPeriodic₁PeriodicₙResponseMsgBus

Компонент состоит из одной задачи InjectPeriodic. С периодом [Config::period] на основе функции [Config::fn_periodic] формируются исходящие сообщения и передаются в шину MsgBus.

НазваниеОписание
InputПринимает сообщения из шины сообщений MsgBus. На основе данных формируются HTTP-запросы. Запросы перенаправляются в задачу HttpClient. Конфигурирование осуществляется с помощью структуры RequestInputConfig
PeriodicЗадача периодически формирует HTTP-запросы и отправляет их в задачу HttpClient. Можно запусить несколько экземпляров. Конфигурирование осуществляется с помощью структуры RequestPeriodicConfig
HttpClientЗадача отправляет сформированные HTTP-запросы серверу. Реализация данной задачи отличается в разных компонентах (cmp_http_client, cmp_http_client_esp, cmp_http_client_wasm). Ответы от сервера отправляются в задачу Response
ResponseЗадача преобразует ответы от сервера в исходящие сообщения и отправляет в шину MsgBus.

§Конфигурация

Конфигурация задаётся структурой Config.

§Примеры

§Пример 1

Содержимое файла config_http_client/mod.rs:

//! Запуск:
//!
//! ```bash
//! cargo run --example cmp_http_client --features="cmp_http_client, serde_json"
//! ```

#[cfg(feature = "cmp_http_client")]
mod shared;

#[cfg(feature = "cmp_http_client")]
#[tokio::main]
async fn main() -> anyhow::Result<()> {
    use serde::{Deserialize, Serialize};
    use tokio::time::Duration;
    use tracing::{Level, level_filters::LevelFilter};

    use shared::{ClientToServer, ServerToClient};

    use rsiot::{
        components::{cmp_http_client, cmp_inject_periodic, cmp_logger},
        executor::{ComponentExecutor, ComponentExecutorConfig},
        message::{MsgDataBound, MsgKey},
        serde_utils::SerdeAlgKind,
    };

    // Message -------------------------------------------------------------------------------------
    #[derive(Clone, Debug, Deserialize, MsgKey, PartialEq, Serialize)]
    enum Data {
        CounterFromServer(f64),
        CounterFromClient(u8),
    }

    impl MsgDataBound for Data {}

    //----------------------------------------------------------------------------------------------

    tracing_subscriber::fmt()
        .with_max_level(LevelFilter::INFO)
        .init();

    let mut counter = 0;
    let inject_config = cmp_inject_periodic::Config {
        period: Duration::from_millis(100),
        fn_periodic: move || {
            let msg = Data::CounterFromClient(counter);
            counter = counter.wrapping_add(1);
            vec![msg]
        },
    };

    let logger_config = cmp_logger::Config {
        level: Level::INFO,
        fn_input: |msg| {
            let Some(msg) = msg.get_custom_data() else {
                return Ok(None);
            };
            let text = match msg {
                Data::CounterFromServer(data) => format!("Counter from server: {data}"),
                _ => return Ok(None),
            };
            Ok(Some(text))
        },
    };

    let http_config = cmp_http_client::Config::<Data> {
        serde_alg: SerdeAlgKind::Json,
        // Подключиться к cmp_esp_http_server
        // base_url: "http://192.168.71.1:8010".into(),
        // Подключиться к cmp_http_server
        base_url: "http://localhost:8010".into(),
        timeout: Duration::from_secs(5),
        requests_input: vec![Box::new(cmp_http_client::RequestInputConfig::<
            Data,
            (),
            ClientToServer,
        > {
            serde_alg: SerdeAlgKind::Json,
            request_kind: cmp_http_client::RequestKind::Put,
            endpoint: "/enter".to_string(),
            fn_create_request: |msg| match msg {
                Data::CounterFromClient(counter) => {
                    let c2s = ClientToServer::SetCounterFromClient(*counter);
                    Some(c2s)
                }
                _ => None,
            },
            fn_process_response_success: |_| vec![],
            fn_process_response_error: Vec::new,
        })],
        requests_periodic: vec![Box::new(cmp_http_client::RequestPeriodicConfig::<
            Data,
            ServerToClient,
            (),
        > {
            serde_alg: SerdeAlgKind::Json,
            request_kind: cmp_http_client::RequestKind::Get,
            endpoint: "/data/test".to_string(),
            period: Duration::from_millis(100),
            request_body: (),
            fn_process_response_success: |s2c| vec![Data::CounterFromServer(s2c.counter)],
            fn_process_response_error: Vec::new,
        })],
    };

    let executor_config = ComponentExecutorConfig {
        buffer_size: 10,
        fn_auth: |msg, _| Some(msg),
        delay_publish: Duration::from_millis(100),
        fn_tokio_metrics: |_| None,
    };

    ComponentExecutor::new(executor_config)
        .add_cmp(cmp_http_client::Cmp::new(http_config))
        .add_cmp(cmp_inject_periodic::Cmp::new(inject_config))
        .add_cmp(cmp_logger::Cmp::new(logger_config))
        .wait_result()
        .await?;

    Ok(())
}

#[cfg(not(feature = "cmp_http_client"))]
fn main() {}

Re-exports§

pub use crate::components_config::http_client::*;

Enums§

Error

Type Aliases§

Cmp
Компонент cmp_http_client