This commit is contained in:
Mateusz Gruszczyński committed 2026-10-10 00:18:06 +02:00
1 parent ad95bfb050
commit 1431dd47f0
62 files changed
+1360 -198

No files matched your search

+12 -2
View File
@@ -188,6 +188,9 @@ impl Settings {
value.parse::<HeaderValue>().expect("validated cache Via header"),
);
}
if self.expose_only_hits && outcome != "HIT" {
return;
}
if self.expose_status {
headers.insert("x-cache", HeaderValue::from_static(outcome));
}
@@ -222,7 +225,10 @@ impl Settings {
}
}
pub fn annotate_transformed(&self, headers: &mut HeaderMap, transformed: bool) {
if !self.enabled || !self.expose_cache_status || !transformed {
if !self.enabled || !self.expose_cache_status || !transformed
|| (self.expose_only_hits && !headers.get("cache-status")
.and_then(|value| value.to_str().ok())
.is_some_and(|value| value.starts_with("RustProxy; hit"))) {
return;
}
let base = headers
@@ -249,7 +255,7 @@ impl Settings {
reason: &'static str,
) {
self.annotate(headers, outcome, hits, ttl);
if !self.enabled {
if !self.enabled || (self.expose_only_hits && outcome != "HIT") {
return;
}
if self.expose_status {
@@ -333,6 +339,7 @@ pub struct Overrides {
pub expose_hits: Option<bool>,
pub expose_cache_status: Option<bool>,
pub expose_resident_age: Option<bool>,
pub expose_only_hits: Option<bool>,
/// Deliberately unavailable in the global cache configuration.
pub unsafe_force: UnsafeForce,
}
@@ -380,6 +387,9 @@ impl Overrides {
if let Some(value) = self.expose_resident_age {
result.expose_resident_age = value;
}
if let Some(value) = self.expose_only_hits {
result.expose_only_hits = value;
}
result.validate()?;
Ok(result)
}
+3
View File
@@ -173,6 +173,8 @@ pub struct Settings {
pub expose_hits: bool,
pub expose_cache_status: bool,
pub expose_resident_age: bool,
/// Emit cache diagnostics only for actual HIT responses, not MISS or BYPASS.
pub expose_only_hits: bool,
/// Optional response Via field value added by RustProxy cache handling.
/// `None` disables the header; the default is `Via: RustProxy`.
pub via_header: Option<String>,
@@ -243,6 +245,7 @@ impl Default for Settings {
expose_hits: false,
expose_cache_status: false,
expose_resident_age: false,
expose_only_hits: false,
via_header: Some("RustProxy".into()),
}
}
+33
View File
@@ -127,6 +127,39 @@ mod dashboard_tests {
);
}
#[test]
fn hit_only_cache_diagnostics_hides_miss_bypass_and_preserves_hits() {
let global = Settings {
expose_status: true,
expose_hits: true,
expose_cache_status: true,
expose_resident_age: true,
expose_only_hits: true,
..Settings::default()
};
let mut headers = HeaderMap::new();
headers.insert("x-cache", HeaderValue::from_static("untrusted-upstream"));
headers.insert("cache-status", HeaderValue::from_static("untrusted-upstream"));
global.annotate_reason(&mut headers, "MISS", 0, 0, "response_headers_policy");
global.annotate_transformed(&mut headers, true);
for name in ["x-cache", "x-cache-hits", "cache-status", "x-cache-reason", "x-cache-resident-age"] {
assert!(!headers.contains_key(name), "{name} leaked on MISS");
}
assert_eq!(headers["via"], "RustProxy"); // independent proxy policy
global.annotate_reason(&mut headers, "BYPASS", 0, 0, "request_cookie");
assert!(!headers.contains_key("cache-status"));
global.annotate_reason(&mut headers, "HIT", 4, 60, "cache_hit");
global.annotate_resident_age(&mut headers, 10);
assert_eq!(headers["x-cache"], "HIT");
assert_eq!(headers["x-cache-hits"], "4");
assert!(headers["cache-status"].to_str().unwrap().contains("; hit;"));
assert_eq!(headers["x-cache-resident-age"], "10");
let mut override_on = Overrides { expose_only_hits: Some(false), ..Default::default() };
let normal = override_on.resolve(&global).unwrap();
assert!(!normal.expose_only_hits);
override_on.expose_only_hits = Some(true);
assert!(override_on.resolve(&Settings::default()).unwrap().expose_only_hits);
}
#[test]
fn via_header_is_configurable_and_preserves_upstream_chain() {
let settings = Settings::default();
let mut headers = HeaderMap::new();