hive_router_plan_executor/execution/
client_request_details.rs1use std::collections::BTreeMap;
2
3use bytes::Bytes;
4use http::Method;
5use ntex_http::HeaderMap as NtexHeaderMap;
6use vrl::core::Value;
7
8use crate::utils::vrl::sonic_value_to_vrl_value;
9
10pub struct OperationDetails<'exec> {
11 pub name: Option<&'exec str>,
12 pub query: &'exec str,
13 pub kind: &'static str,
14}
15
16pub struct ClientRequestDetails<'exec, 'req> {
17 pub method: &'req Method,
18 pub url: &'req http::Uri,
19 pub headers: &'req NtexHeaderMap,
20 pub operation: OperationDetails<'exec>,
21 pub jwt: &'exec JwtRequestDetails<'req>,
22}
23
24pub enum JwtRequestDetails<'exec> {
25 Authenticated {
26 token: &'exec str,
27 prefix: Option<&'exec str>,
28 claims: &'exec sonic_rs::Value,
29 scopes: Option<Vec<String>>,
30 },
31 Unauthenticated,
32}
33
34impl From<&ClientRequestDetails<'_, '_>> for Value {
35 fn from(details: &ClientRequestDetails) -> Self {
36 let headers_value = client_header_map_to_vrl_value(details.headers);
38
39 let url_value = Self::Object(BTreeMap::from([
41 (
42 "host".into(),
43 details.url.host().unwrap_or("unknown").into(),
44 ),
45 ("path".into(), details.url.path().into()),
46 (
47 "port".into(),
48 details
49 .url
50 .port_u16()
51 .unwrap_or_else(|| {
52 if details.url.scheme() == Some(&http::uri::Scheme::HTTPS) {
53 443
54 } else {
55 80
56 }
57 })
58 .into(),
59 ),
60 ]));
61
62 let operation_value = Self::Object(BTreeMap::from([
64 ("name".into(), details.operation.name.into()),
65 ("type".into(), details.operation.kind.into()),
66 ("query".into(), details.operation.query.into()),
67 ]));
68
69 let jwt_value = match details.jwt {
71 JwtRequestDetails::Authenticated {
72 token,
73 prefix,
74 claims,
75 scopes,
76 } => Self::Object(BTreeMap::from([
77 ("authenticated".into(), Value::Boolean(true)),
78 ("token".into(), token.to_string().into()),
79 (
80 "prefix".into(),
81 prefix.unwrap_or_default().to_string().into(),
82 ),
83 ("claims".into(), sonic_value_to_vrl_value(claims)),
84 (
85 "scopes".into(),
86 match scopes {
87 Some(scopes) => Value::Array(
88 scopes
89 .iter()
90 .map(|v| Value::Bytes(Bytes::from(v.clone())))
91 .collect(),
92 ),
93 None => Value::Array(vec![]),
94 },
95 ),
96 ])),
97 JwtRequestDetails::Unauthenticated => Self::Object(BTreeMap::from([
98 ("authenticated".into(), Value::Boolean(false)),
99 ("token".into(), Value::Null),
100 ("prefix".into(), Value::Null),
101 ("claims".into(), Value::Object(BTreeMap::new())),
102 ("scopes".into(), Value::Array(vec![])),
103 ])),
104 };
105
106 Self::Object(BTreeMap::from([
107 ("method".into(), details.method.as_str().into()),
108 ("headers".into(), headers_value),
109 ("url".into(), url_value),
110 ("operation".into(), operation_value),
111 ("jwt".into(), jwt_value),
112 ]))
113 }
114}
115
116fn client_header_map_to_vrl_value(headers: &ntex_http::HeaderMap) -> Value {
117 let mut obj = BTreeMap::new();
118 for (header_name, header_value) in headers.iter() {
119 if let Ok(value) = header_value.to_str() {
120 obj.insert(
121 header_name.as_str().into(),
122 Value::Bytes(Bytes::from(value.to_owned())),
123 );
124 }
125 }
126 Value::Object(obj)
127}