Skip to main content

hive_router_plan_executor/headers/
expression.rs

1use std::collections::BTreeMap;
2
3use bytes::Bytes;
4use hive_router_internal::expressions::vrl::core::Value;
5use http::{HeaderMap, HeaderValue};
6
7use crate::headers::{request::RequestExpressionContext, response::ResponseExpressionContext};
8use hive_router_internal::expressions::FromVrlValue;
9
10/// Convert a VRL value to a HeaderValue, returning an Option
11///
12/// This function is backward compatible with the old implementation but now
13/// uses the FromVrlValue trait internally to provide better error handling.
14/// For detailed error information, use `HeaderValue::from_vrl_value()` directly.
15pub fn vrl_value_to_header_value(value: Value) -> Option<HeaderValue> {
16    HeaderValue::from_vrl_value(value).ok()
17}
18
19fn header_map_to_vrl_value(headers: &HeaderMap) -> Value {
20    let mut obj = BTreeMap::new();
21    for (header_name, header_value) in headers.iter() {
22        if let Ok(value) = header_value.to_str() {
23            obj.insert(
24                header_name.as_str().into(),
25                Value::Bytes(Bytes::from(value.to_owned())),
26            );
27        }
28    }
29    Value::Object(obj)
30}
31
32impl From<&RequestExpressionContext<'_>> for Value {
33    /// NOTE: If performance becomes an issue, consider pre-computing parts of this context that do not change
34    fn from(ctx: &RequestExpressionContext) -> Self {
35        // .subgraph
36        let subgraph_value = {
37            let value = Self::Bytes(Bytes::from(ctx.subgraph_name.to_owned()));
38            Self::Object(BTreeMap::from([("name".into(), value)]))
39        };
40
41        // .request
42        let request_value: Self = ctx.client_request.into();
43
44        Self::Object(BTreeMap::from([
45            ("subgraph".into(), subgraph_value),
46            ("request".into(), request_value),
47        ]))
48    }
49}
50
51impl From<&ResponseExpressionContext<'_>> for Value {
52    /// NOTE: If performance becomes an issue, consider pre-computing parts of this context that do not change
53    fn from(ctx: &ResponseExpressionContext) -> Self {
54        // .subgraph
55        let subgraph_value = Self::Object(BTreeMap::from([(
56            "name".into(),
57            Self::Bytes(Bytes::from(ctx.subgraph_name.to_owned())),
58        )]));
59        // .response
60        let response_value = header_map_to_vrl_value(ctx.subgraph_headers);
61        // .request
62        let request_value: Self = ctx.client_request.into();
63
64        Self::Object(BTreeMap::from([
65            ("subgraph".into(), subgraph_value),
66            ("response".into(), response_value),
67            ("request".into(), request_value),
68        ]))
69    }
70}