edgee_components_runtime/data_collection/versions/v1_0_1/
execute.rs

1use crate::config::DataCollectionComponents;
2use crate::context::HostState;
3use crate::data_collection::insert_expected_headers;
4use crate::data_collection::payload::EventType;
5use crate::data_collection::versions::v1_0_1::data_collection::exports::edgee::components1_0_1::data_collection as DC;
6use crate::{context::ComponentsContext, data_collection::payload};
7use http::{HeaderMap, HeaderName, HeaderValue};
8use std::collections::HashMap;
9use std::str::FromStr;
10use tracing::error;
11use wasmtime::Store;
12
13pub struct AuthMetadata {
14    pub token_duration: i64,
15    pub response_token_property_name: Option<String>,
16    pub component_token_setting_name: String,
17}
18
19pub async fn get_edgee_request(
20    event: &payload::Event,
21    component_ctx: &ComponentsContext,
22    cfg: &DataCollectionComponents,
23    store: &mut Store<HostState>,
24    client_headers: &HashMap<String, String>,
25) -> Result<(HeaderMap, String, String, String), anyhow::Error> {
26    let instance = match component_ctx
27        .get_data_collection_1_0_1_instance(&cfg.id, store)
28        .await
29    {
30        Ok(instance) => instance,
31        Err(err) => {
32            error!("Failed to get data collection instance. Error: {}", err);
33            return Err(err);
34        }
35    };
36    let component = instance.edgee_components1_0_1_data_collection();
37
38    let component_settings: Vec<(String, String)> = cfg
39        .settings
40        .additional_settings
41        .clone()
42        .into_iter()
43        .collect();
44
45    // call the corresponding method of the component
46    let request = match event.event_type {
47        EventType::Page => {
48            component
49                .call_page(store, &event.clone().into(), &component_settings)
50                .await
51        }
52        EventType::Track => {
53            component
54                .call_track(store, &event.clone().into(), &component_settings)
55                .await
56        }
57        EventType::User => {
58            component
59                .call_user(store, &event.clone().into(), &component_settings)
60                .await
61        }
62    };
63    let request = match request {
64        Ok(Ok(request)) => request,
65        Ok(Err(err)) => {
66            // todo: debug and trace response (error)
67            error!(
68                step = "request",
69                err = err.to_string(),
70                "failed to handle data collection payload"
71            );
72            return Err(anyhow::anyhow!(err));
73        }
74        Err(err) => {
75            // todo: debug and trace response (error)
76            error!(
77                step = "request",
78                err = err.to_string(),
79                "failed to handle data collection payload"
80            );
81            return Err(anyhow::anyhow!(err));
82        }
83    };
84
85    let mut headers = HeaderMap::new();
86    for (key, value) in request.headers.iter() {
87        headers.insert(HeaderName::from_str(key)?, HeaderValue::from_str(value)?);
88    }
89
90    if request.forward_client_headers {
91        let _ = insert_expected_headers(&mut headers, event, client_headers);
92    }
93
94    let method = match request.method {
95        DC::HttpMethod::Get => "GET",
96        DC::HttpMethod::Put => "PUT",
97        DC::HttpMethod::Post => "POST",
98        DC::HttpMethod::Delete => "DELETE",
99    }
100    .to_string();
101
102    Ok((headers, method, request.url, request.body))
103}
104
105pub async fn get_auth_request(
106    component_ctx: &ComponentsContext,
107    cfg: &DataCollectionComponents,
108    store: &mut Store<HostState>,
109) -> Result<Option<(HeaderMap, String, String, String, AuthMetadata)>, anyhow::Error> {
110    let instance = match component_ctx
111        .get_data_collection_1_0_1_instance(&cfg.id, store)
112        .await
113    {
114        Ok(instance) => instance,
115        Err(err) => {
116            error!("Failed to get data collection instance. Error: {}", err);
117            return Err(err);
118        }
119    };
120    let component = instance.edgee_components1_0_1_data_collection();
121
122    let auth_request = match component
123        .call_authenticate(
124            store,
125            &cfg.settings
126                .additional_settings
127                .iter()
128                .map(|(k, v)| (k.clone(), v.clone()))
129                .collect::<Vec<_>>(),
130        )
131        .await
132    {
133        Ok(Ok(Some(req))) => req,
134        Ok(Ok(None)) => {
135            return Ok(None);
136        }
137        Ok(Err(err)) => {
138            error!("auth error: {err}");
139            return Err(anyhow::anyhow!(err));
140        }
141        Err(err) => {
142            error!("auth error: {err}");
143            return Err(anyhow::anyhow!(err));
144        }
145    };
146
147    let mut headers = HeaderMap::new();
148    for (key, value) in auth_request.headers.iter() {
149        headers.insert(HeaderName::from_str(key)?, HeaderValue::from_str(value)?);
150    }
151
152    let method = match auth_request.method {
153        DC::HttpMethod::Get => "GET",
154        DC::HttpMethod::Put => "PUT",
155        DC::HttpMethod::Post => "POST",
156        DC::HttpMethod::Delete => "DELETE",
157    }
158    .to_string();
159
160    Ok(Some((
161        headers,
162        method,
163        auth_request.url,
164        auth_request.body,
165        AuthMetadata {
166            token_duration: auth_request.token_duration,
167            response_token_property_name: auth_request.response_token_property_name,
168            component_token_setting_name: auth_request.component_token_setting_name,
169        },
170    )))
171}