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