hive_router_plan_executor/headers/
request.rs1use hive_router_internal::expressions::ExecutableProgram;
2use http::HeaderMap;
3
4use crate::{
5 execution::client_request_details::ClientRequestDetails,
6 headers::{
7 errors::HeaderRuleRuntimeError,
8 expression::vrl_value_to_header_value,
9 plan::{
10 HeaderRulesPlan, RequestHeaderRule, RequestInsertExpression, RequestInsertStatic,
11 RequestPropagateNamed, RequestPropagateRegex, RequestRemoveNamed, RequestRemoveRegex,
12 },
13 sanitizer::{is_denied_header, is_never_join_header},
14 },
15};
16
17pub fn modify_subgraph_request_headers(
18 header_rule_plan: &HeaderRulesPlan,
19 subgraph_name: &str,
20 client_request: &ClientRequestDetails,
21 output_headers: &mut HeaderMap,
22) -> Result<(), HeaderRuleRuntimeError> {
23 let global_actions = &header_rule_plan.request.global;
24 let subgraph_actions = header_rule_plan.request.by_subgraph.get(subgraph_name);
25
26 let ctx = RequestExpressionContext {
27 subgraph_name,
28 client_request,
29 };
30
31 for action in global_actions
32 .iter()
33 .chain(subgraph_actions.into_iter().flatten())
34 {
35 action.apply_request_headers(&ctx, output_headers)?;
36 }
37
38 Ok(())
39}
40
41pub struct RequestExpressionContext<'a> {
42 pub subgraph_name: &'a str,
43 pub client_request: &'a ClientRequestDetails<'a>,
44}
45
46trait ApplyRequestHeader {
47 fn apply_request_headers(
48 &self,
49 ctx: &RequestExpressionContext,
50 output_headers: &mut HeaderMap,
51 ) -> Result<(), HeaderRuleRuntimeError>;
52}
53
54impl ApplyRequestHeader for RequestHeaderRule {
55 fn apply_request_headers(
56 &self,
57 ctx: &RequestExpressionContext,
58 output_headers: &mut HeaderMap,
59 ) -> Result<(), HeaderRuleRuntimeError> {
60 match self {
61 Self::PropagateNamed(data) => data.apply_request_headers(ctx, output_headers),
62 Self::PropagateRegex(data) => data.apply_request_headers(ctx, output_headers),
63 Self::InsertStatic(data) => data.apply_request_headers(ctx, output_headers),
64 Self::InsertExpression(data) => data.apply_request_headers(ctx, output_headers),
65 Self::RemoveNamed(data) => data.apply_request_headers(ctx, output_headers),
66 Self::RemoveRegex(data) => data.apply_request_headers(ctx, output_headers),
67 }
68 }
69}
70
71impl ApplyRequestHeader for RequestPropagateNamed {
72 fn apply_request_headers(
73 &self,
74 ctx: &RequestExpressionContext,
75 output_headers: &mut HeaderMap,
76 ) -> Result<(), HeaderRuleRuntimeError> {
77 let mut matched = false;
78
79 for header_name in &self.names {
80 if is_denied_header(header_name) {
81 continue;
82 }
83 if let Some(header_value) = ctx.client_request.headers.get(header_name) {
84 let destination_name = self.rename.as_ref().unwrap_or(header_name);
85 output_headers.append(destination_name, header_value.into());
86 matched = true;
87 }
88 }
89
90 if !matched {
91 if let (Some(default_value), Some(first_name)) = (&self.default, self.names.first()) {
93 let destination_name = self.rename.as_ref().unwrap_or(first_name);
94
95 if is_denied_header(destination_name) {
96 return Ok(());
97 }
98
99 output_headers.append(destination_name, default_value.clone());
100 }
101 }
102
103 Ok(())
104 }
105}
106
107impl ApplyRequestHeader for RequestPropagateRegex {
108 fn apply_request_headers(
109 &self,
110 ctx: &RequestExpressionContext,
111 output_headers: &mut HeaderMap,
112 ) -> Result<(), HeaderRuleRuntimeError> {
113 for (header_name, header_value) in ctx.client_request.headers {
114 if is_denied_header(header_name) {
115 continue;
116 }
117
118 let header_bytes = header_name.as_str().as_bytes();
119
120 let Some(include_regex) = &self.include else {
121 continue;
122 };
123
124 if !include_regex.is_match(header_bytes) {
125 continue;
126 }
127
128 if self
129 .exclude
130 .as_ref()
131 .is_some_and(|regex| regex.is_match(header_bytes))
132 {
133 continue;
134 }
135
136 output_headers.append(header_name, header_value.into());
137 }
138
139 Ok(())
140 }
141}
142
143impl ApplyRequestHeader for RequestInsertStatic {
144 fn apply_request_headers(
145 &self,
146 _ctx: &RequestExpressionContext,
147 output_headers: &mut HeaderMap,
148 ) -> Result<(), HeaderRuleRuntimeError> {
149 if !is_denied_header(&self.name) {
150 if is_never_join_header(&self.name) {
151 output_headers.append(self.name.clone(), self.value.clone());
152 } else {
153 output_headers.insert(self.name.clone(), self.value.clone());
154 }
155 }
156
157 Ok(())
158 }
159}
160
161impl ApplyRequestHeader for RequestInsertExpression {
162 fn apply_request_headers(
163 &self,
164 ctx: &RequestExpressionContext,
165 output_headers: &mut HeaderMap,
166 ) -> Result<(), HeaderRuleRuntimeError> {
167 if is_denied_header(&self.name) {
168 return Ok(());
169 }
170 let value = self.expression.execute(ctx.into()).map_err(|err| {
171 HeaderRuleRuntimeError::ExpressionEvaluation(self.name.to_string(), Box::new(err.0))
172 })?;
173
174 if let Some(header_value) = vrl_value_to_header_value(value) {
175 if is_never_join_header(&self.name) {
176 output_headers.append(self.name.clone(), header_value);
177 } else {
178 output_headers.insert(self.name.clone(), header_value);
179 }
180 }
181
182 Ok(())
183 }
184}
185
186impl ApplyRequestHeader for RequestRemoveNamed {
187 fn apply_request_headers(
188 &self,
189 _ctx: &RequestExpressionContext,
190 output_headers: &mut HeaderMap,
191 ) -> Result<(), HeaderRuleRuntimeError> {
192 for header_name in &self.names {
193 if is_denied_header(header_name) {
194 continue;
195 }
196 output_headers.remove(header_name);
197 }
198
199 Ok(())
200 }
201}
202
203impl ApplyRequestHeader for RequestRemoveRegex {
204 fn apply_request_headers(
205 &self,
206 _ctx: &RequestExpressionContext,
207 output_headers: &mut HeaderMap,
208 ) -> Result<(), HeaderRuleRuntimeError> {
209 let mut headers_to_remove = Vec::new();
210 for header_name in output_headers.keys() {
211 if is_denied_header(header_name) {
212 continue;
213 }
214
215 if self.regex.is_match(header_name.as_str().as_bytes()) {
216 headers_to_remove.push(header_name.clone());
217 }
218 }
219
220 for header_name in headers_to_remove.iter() {
221 output_headers.remove(header_name);
222 }
223
224 Ok(())
225 }
226}