Skip to content

Commit be67f73

Browse files
authored
Merge pull request #2744 from lann/factors-fix-http-trigger
factors: Reorganize some http trigger code
2 parents be24451 + 6651646 commit be67f73

File tree

3 files changed

+210
-220
lines changed

3 files changed

+210
-220
lines changed

crates/trigger-http2/src/headers.rs

Lines changed: 173 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -139,6 +139,8 @@ fn prepare_header_key(key: &str) -> String {
139139
#[cfg(test)]
140140
mod tests {
141141
use super::*;
142+
use anyhow::Result;
143+
use spin_http::routes::Router;
142144

143145
#[test]
144146
fn test_spin_header_keys() {
@@ -155,4 +157,175 @@ mod tests {
155157
"spin-raw-component-route".to_string()
156158
);
157159
}
160+
161+
#[test]
162+
fn test_default_headers() -> Result<()> {
163+
let scheme = "https";
164+
let host = "fermyon.dev";
165+
let trigger_route = "/foo/...";
166+
let component_path = "/foo";
167+
let path_info = "/bar";
168+
let client_addr: SocketAddr = "127.0.0.1:8777".parse().unwrap();
169+
170+
let req_uri = format!(
171+
"{}://{}{}{}?key1=value1&key2=value2",
172+
scheme, host, component_path, path_info
173+
);
174+
175+
let req = http::Request::builder()
176+
.method("POST")
177+
.uri(req_uri)
178+
.body("")?;
179+
180+
let (router, _) = Router::build("/", [("DUMMY", &trigger_route.into())])?;
181+
let route_match = router.route("/foo/bar")?;
182+
183+
let default_headers = compute_default_headers(req.uri(), host, &route_match, client_addr)?;
184+
185+
assert_eq!(
186+
search(&FULL_URL, &default_headers).unwrap(),
187+
"https://fermyon.dev/foo/bar?key1=value1&key2=value2".to_string()
188+
);
189+
assert_eq!(
190+
search(&PATH_INFO, &default_headers).unwrap(),
191+
"/bar".to_string()
192+
);
193+
assert_eq!(
194+
search(&MATCHED_ROUTE, &default_headers).unwrap(),
195+
"/foo/...".to_string()
196+
);
197+
assert_eq!(
198+
search(&BASE_PATH, &default_headers).unwrap(),
199+
"/".to_string()
200+
);
201+
assert_eq!(
202+
search(&RAW_COMPONENT_ROUTE, &default_headers).unwrap(),
203+
"/foo/...".to_string()
204+
);
205+
assert_eq!(
206+
search(&COMPONENT_ROUTE, &default_headers).unwrap(),
207+
"/foo".to_string()
208+
);
209+
assert_eq!(
210+
search(&CLIENT_ADDR, &default_headers).unwrap(),
211+
"127.0.0.1:8777".to_string()
212+
);
213+
214+
Ok(())
215+
}
216+
217+
#[test]
218+
fn test_default_headers_with_named_wildcards() -> Result<()> {
219+
let scheme = "https";
220+
let host = "fermyon.dev";
221+
let trigger_route = "/foo/:userid/...";
222+
let component_path = "/foo";
223+
let path_info = "/bar";
224+
let client_addr: SocketAddr = "127.0.0.1:8777".parse().unwrap();
225+
226+
let req_uri = format!(
227+
"{}://{}{}/42{}?key1=value1&key2=value2",
228+
scheme, host, component_path, path_info
229+
);
230+
231+
let req = http::Request::builder()
232+
.method("POST")
233+
.uri(req_uri)
234+
.body("")?;
235+
236+
let (router, _) = Router::build("/", [("DUMMY", &trigger_route.into())])?;
237+
let route_match = router.route("/foo/42/bar")?;
238+
239+
let default_headers = compute_default_headers(req.uri(), host, &route_match, client_addr)?;
240+
241+
assert_eq!(
242+
search(&FULL_URL, &default_headers).unwrap(),
243+
"https://fermyon.dev/foo/42/bar?key1=value1&key2=value2".to_string()
244+
);
245+
assert_eq!(
246+
search(&PATH_INFO, &default_headers).unwrap(),
247+
"/bar".to_string()
248+
);
249+
assert_eq!(
250+
search(&MATCHED_ROUTE, &default_headers).unwrap(),
251+
"/foo/:userid/...".to_string()
252+
);
253+
assert_eq!(
254+
search(&BASE_PATH, &default_headers).unwrap(),
255+
"/".to_string()
256+
);
257+
assert_eq!(
258+
search(&RAW_COMPONENT_ROUTE, &default_headers).unwrap(),
259+
"/foo/:userid/...".to_string()
260+
);
261+
assert_eq!(
262+
search(&COMPONENT_ROUTE, &default_headers).unwrap(),
263+
"/foo/:userid".to_string()
264+
);
265+
assert_eq!(
266+
search(&CLIENT_ADDR, &default_headers).unwrap(),
267+
"127.0.0.1:8777".to_string()
268+
);
269+
270+
assert_eq!(
271+
search(
272+
&["SPIN_PATH_MATCH_USERID", "X_PATH_MATCH_USERID"],
273+
&default_headers
274+
)
275+
.unwrap(),
276+
"42".to_string()
277+
);
278+
279+
Ok(())
280+
}
281+
282+
#[test]
283+
fn forbidden_headers_are_removed() {
284+
let mut req = Request::get("http://test.spin.internal")
285+
.header("Host", "test.spin.internal")
286+
.header("accept", "text/plain")
287+
.body(Default::default())
288+
.unwrap();
289+
290+
strip_forbidden_headers(&mut req);
291+
292+
assert_eq!(1, req.headers().len());
293+
assert!(req.headers().get("Host").is_none());
294+
295+
let mut req = Request::get("http://test.spin.internal")
296+
.header("Host", "test.spin.internal:1234")
297+
.header("accept", "text/plain")
298+
.body(Default::default())
299+
.unwrap();
300+
301+
strip_forbidden_headers(&mut req);
302+
303+
assert_eq!(1, req.headers().len());
304+
assert!(req.headers().get("Host").is_none());
305+
}
306+
307+
#[test]
308+
fn non_forbidden_headers_are_not_removed() {
309+
let mut req = Request::get("http://test.example.com")
310+
.header("Host", "test.example.org")
311+
.header("accept", "text/plain")
312+
.body(Default::default())
313+
.unwrap();
314+
315+
strip_forbidden_headers(&mut req);
316+
317+
assert_eq!(2, req.headers().len());
318+
assert!(req.headers().get("Host").is_some());
319+
}
320+
321+
fn search(keys: &[&str; 2], headers: &[([String; 2], String)]) -> Option<String> {
322+
let mut res: Option<String> = None;
323+
for (k, v) in headers {
324+
if k[0] == keys[0] && k[1] == keys[1] {
325+
res = Some(v.clone());
326+
}
327+
}
328+
329+
res
330+
}
158331
}

0 commit comments

Comments
 (0)