Files
RustProxy/src/proxy/cache_plan/tests.rs
T
2026-10-27 12:18:20 +01:00

180 lines
6.2 KiB
Rust

use super::*;
use crate::cache::RangeSelection;
use http::HeaderValue;
fn settings() -> Settings {
Settings {
enabled: true,
static_ignore_cookies: true,
static_extensions: vec!["css".into()],
..Default::default()
}
}
#[test]
fn disabled_cache_retains_reason_without_matching_force_rules_or_reparsing_headers() {
let settings = settings();
let mut headers = HeaderMap::new();
headers.insert("authorization", HeaderValue::from_static("private"));
headers.insert(
"cache-control",
HeaderValue::from_static("max-age=not-a-number"),
);
for reason in [
"cache_disabled",
"route_disabled",
"admin_control_plane",
"basic_auth",
"tinyauth",
"authelia",
"authentik",
"sticky_cookie",
"request_upgrade",
] {
let plan = CachePlan::new(Some(reason), &settings, "/style.css", || {
panic!("disabled cache must not match force-cache rules")
});
assert!(!plan.force_cache());
assert!(!plan.ignore_cookie());
let policy =
plan.request_policy(&Method::GET, &headers, true, "/style.css", false, &settings);
assert_eq!(policy, RequestPolicy::Bypass(reason));
assert_eq!(
combine_policy(policy, || panic!(
"disabled cache must not parse post-rule policy"
)),
policy
);
}
}
#[test]
fn cache_on_keeps_all_existing_request_policy_outcomes() {
let settings = settings();
for forced in [false, true] {
let plan = CachePlan::new(None, &settings, "/style.css", || forced);
for (name, value) in [
("x-irrelevant", "yes"),
("cache-control", "no-store"),
("cache-control", "no-cache"),
("cache-control", "max-age=0"),
("cache-control", "min-fresh=broken"),
("authorization", "private"),
("cookie", "session=private"),
("range", "bytes=0-2"),
("range", "bytes=0-2,4-5"),
("if-range", "\"etag\""),
("if-match", "\"etag\""),
("upgrade", "websocket"),
] {
let mut headers = HeaderMap::new();
headers.insert(
http::HeaderName::from_bytes(name.as_bytes()).unwrap(),
value.parse().unwrap(),
);
for method in [Method::GET, Method::HEAD, Method::POST] {
for body_empty in [false, true] {
let expected = if forced {
crate::cache::forced_request_policy(&method, &headers, body_empty)
} else {
crate::cache::request_policy(
&method,
&headers,
body_empty,
"/style.css",
false,
&settings,
)
};
assert_eq!(
plan.request_policy(
&method,
&headers,
body_empty,
"/style.css",
false,
&settings
),
expected
);
}
}
}
}
}
#[test]
fn request_header_rules_cannot_relax_bypass_or_revalidation() {
let cases = [
RequestPolicy::Use,
RequestPolicy::Revalidate("request_no_cache"),
RequestPolicy::Revalidate("request_max_age"),
RequestPolicy::Bypass("request_authorization"),
RequestPolicy::Bypass("request_no_store"),
];
for original in cases {
for rewritten in cases {
let expected = match (original, rewritten) {
(RequestPolicy::Bypass(reason), _) | (_, RequestPolicy::Bypass(reason)) => {
RequestPolicy::Bypass(reason)
}
(RequestPolicy::Revalidate(reason), _) | (_, RequestPolicy::Revalidate(reason)) => {
RequestPolicy::Revalidate(reason)
}
_ => RequestPolicy::Use,
};
assert_eq!(combine_policy(original, || rewritten), expected);
}
}
}
#[test]
fn cache_off_still_blocks_range_transformation_and_preserves_origin_headers() {
for method in [Method::GET, Method::HEAD, Method::POST] {
for range in [
None,
Some("bytes=0-2"),
Some("bytes=0-2,4-5"),
Some("broken"),
Some("bytes=99-"),
] {
let mut headers = HeaderMap::new();
if let Some(range) = range {
headers.insert("range", range.parse().unwrap());
}
headers.insert("if-range", HeaderValue::from_static("\"same-validator\""));
headers.insert(
"if-none-match",
HeaderValue::from_static("\"client-validator\""),
);
let original = headers.clone();
let baseline = crate::cache::request_range(&method, &headers);
assert_eq!(range_selection(true, &method, &headers), baseline);
assert_eq!(
matches!(
range_selection(false, &method, &headers),
RangeSelection::None
),
matches!(baseline, RangeSelection::None)
);
assert_eq!(
headers, original,
"origin must receive the original Range/conditional fields"
);
}
}
}
#[test]
fn force_cache_keeps_cookie_variants_and_disabled_cookie_matching_has_no_effect() {
let settings = settings();
let ordinary = CachePlan::new(None, &settings, "/style.css", || false);
assert!(ordinary.ignore_cookie());
let forced = CachePlan::new(None, &settings, "/style.css", || true);
assert!(forced.force_cache());
assert!(!forced.ignore_cookie());
let disabled = CachePlan::new(Some("route_disabled"), &settings, "/style.css", || true);
assert!(!disabled.force_cache());
assert!(!disabled.ignore_cookie());
}