reactive_graph_net_http/behaviour/component/
http.rs

1use reactive_graph_behaviour_model_api::behaviour_validator;
2use reactive_graph_behaviour_model_api::prelude::*;
3use reactive_graph_behaviour_model_impl::entity_behaviour;
4use reactive_graph_graph::prelude::*;
5use reactive_graph_reactive_model_impl::ReactiveEntity;
6use serde_json::Value;
7use serde_json::json;
8use uuid::Uuid;
9
10use log::error;
11
12use reactive_graph_net_http_model::RequestProperties::METHOD;
13use reactive_graph_net_http_model::RequestProperties::PAYLOAD;
14use reactive_graph_net_http_model::RequestProperties::REQUEST_HEADERS;
15use reactive_graph_net_http_model::ResponseProperties::RESPONSE_HEADERS;
16use reactive_graph_net_http_model::ResponseProperties::STATUS;
17use reactive_graph_net_http_model::UrlProperties::URL;
18use reactive_graph_runtime_model::ActionProperties::TRIGGER;
19use reactive_graph_std_result_model::ResultObjectProperties::RESULT;
20
21entity_behaviour!(Http, HttpFactory, HttpFsm, HttpBehaviourTransitions, HttpValidator);
22
23behaviour_validator!(
24    HttpValidator,
25    Uuid,
26    ReactiveEntity,
27    METHOD.as_ref(),
28    PAYLOAD.as_ref(),
29    REQUEST_HEADERS.as_ref(),
30    RESPONSE_HEADERS.as_ref(),
31    RESULT.as_ref(),
32    STATUS.as_ref(),
33    URL.as_ref()
34);
35
36impl BehaviourInit<Uuid, ReactiveEntity> for HttpBehaviourTransitions {
37    fn init(&self) -> Result<(), BehaviourInitializationFailed> {
38        if self.reactive_instance.as_bool(TRIGGER).unwrap_or(false) {
39            send_request(&self.reactive_instance);
40        }
41        Ok(())
42    }
43}
44
45impl BehaviourConnect<Uuid, ReactiveEntity> for HttpBehaviourTransitions {
46    fn connect(&self) -> Result<(), BehaviourConnectFailed> {
47        let reactive_instance = self.reactive_instance.clone();
48        self.property_observers.observe_with_handle(TRIGGER.as_ref(), move |trigger: &Value| {
49            if !trigger.as_bool().unwrap_or(false) {
50                return;
51            }
52            send_request(&reactive_instance);
53        });
54        Ok(())
55    }
56}
57
58impl BehaviourShutdown<Uuid, ReactiveEntity> for HttpBehaviourTransitions {}
59impl BehaviourTransitions<Uuid, ReactiveEntity> for HttpBehaviourTransitions {}
60
61fn send_request(reactive_instance: &ReactiveEntity) {
62    let Some(method) = reactive_instance.as_string(METHOD) else {
63        return;
64    };
65    let Some(url) = reactive_instance.as_string(URL) else {
66        return;
67    };
68    let Some(request_headers) = reactive_instance.as_object(REQUEST_HEADERS) else {
69        return;
70    };
71    let Some(payload) = reactive_instance.get(PAYLOAD) else {
72        return;
73    };
74    let mut request = ureq::request(method.as_str(), url.as_str());
75    for (request_header, value) in request_headers.into_iter() {
76        if let Some(value) = value.as_str() {
77            request = request.set(request_header.as_ref(), value);
78        }
79    }
80    let result = request.send_json(payload);
81    match result {
82        Ok(response) => {
83            reactive_instance.set(STATUS, json!(response.status()));
84            let mut response_headers = json!({});
85            for header_name in response.headers_names() {
86                response_headers[header_name] = json!(response.header(header_name.as_str()));
87            }
88            reactive_instance.set(RESPONSE_HEADERS, response_headers);
89            match response.into_json() {
90                Ok(result) => {
91                    reactive_instance.set(RESULT, result);
92                }
93                Err(e) => error!("Failed to parse response as JSON: {}", e.to_string()),
94            }
95        }
96        Err(e) => {
97            error!("Failed to send request: {}", e.to_string());
98        }
99    }
100}