Files
RustProxy/src/headers/tests.rs
T
2026-10-17 11:57:16 +02:00

110 lines
4.0 KiB
Rust

mod tests {
use super::*;
#[test]
fn transformations_preserve_distinct_set_cookie_fields() {
let source = r#"{"request":[],"response":[{"op":"remove","name":"server"},{"op":"set","name":"x-test","value":"one"},{"op":"append","name":"x-test","value":"two"},{"op":"append","name":"set-cookie","value":"b=2"}]}"#;
let rules: HeaderRules = serde_json::from_str(source).unwrap();
let compiled = rules.compile().unwrap();
let mut headers = HeaderMap::new();
headers.insert("server", "upstream".parse().unwrap());
headers.append("set-cookie", "a=1".parse().unwrap());
apply(&mut headers, &compiled.response);
assert!(!headers.contains_key("server"));
assert_eq!(headers.get_all("x-test").iter().count(), 2);
assert_eq!(headers.get_all("set-cookie").iter().count(), 2);
}
#[test]
fn transport_identity_and_crlf_are_rejected() {
for name in [
"Host",
"Connection",
"Content-Length",
"x-forwarded-for",
"Upgrade",
"X-RustProxy-Backend",
"X-Rust-Proxy-Backend",
"X-RustProxy-Backend-Time",
"X-Rust-Proxy-Backend-Time",
] {
let rules = HeaderRules {
request: vec![Rule {
op: Operation::Set,
name: name.into(),
value: Some("x".into()),
}],
response: vec![],
};
assert!(rules.compile().is_err(), "{name}");
let response_rules = HeaderRules { request: vec![], response: rules.request };
assert!(response_rules.compile().is_err(), "response {name}");
}
let rules = HeaderRules {
request: vec![Rule {
op: Operation::Set,
name: "x-test".into(),
value: Some("hello\r\ninjected: yes".into()),
}],
response: vec![],
};
assert!(rules.compile().is_err());
}
#[test]
fn response_age_is_allowed_but_applied_only_at_wire_stage() {
let request_age = HeaderRules {
request: vec![Rule {
op: Operation::Set,
name: "Age".into(),
value: Some("7".into()),
}],
response: vec![],
};
let request_compiled = request_age.compile().unwrap();
let mut request_headers = HeaderMap::new();
apply(&mut request_headers, &request_compiled.request);
assert_eq!(request_headers["age"], "7");
let response_age = HeaderRules {
request: vec![],
response: vec![Rule {
op: Operation::Remove,
name: "Age".into(),
value: None,
}],
};
let compiled = response_age.compile().unwrap();
let mut headers = HeaderMap::new();
headers.insert("age", HeaderValue::from_static("42"));
apply(&mut headers, &compiled.response);
assert_eq!(headers["age"], "42");
apply_wire_age(&mut headers, &compiled.response);
assert!(!headers.contains_key("age"));
}
#[test]
fn response_age_keeps_0266_rule_compatibility() {
let rules = HeaderRules {
request: vec![],
response: vec![
Rule {
op: Operation::Set,
name: "age".into(),
value: Some("custom".into()),
},
Rule {
op: Operation::Append,
name: "age".into(),
value: Some("7".into()),
},
],
};
let compiled = rules.compile().unwrap();
let mut headers = HeaderMap::new();
headers.insert("age", HeaderValue::from_static("42"));
apply(&mut headers, &compiled.response);
assert_eq!(headers["age"], "42");
apply_wire_age(&mut headers, &compiled.response);
assert_eq!(headers.get_all("age").iter().count(), 2);
}
}