This commit is contained in:
Mateusz Gruszczyński committed 2026-10-25 09:58:39 +01:00
1 parent 37c197c095
commit 5ac3617947
48 files changed
+1049 -255

No files matched your search

+87 -74
View File
@@ -171,16 +171,41 @@ impl Settings {
.any(|item| item.eq_ignore_ascii_case(extension))
}
pub fn annotate(&self, headers: &mut HeaderMap, outcome: &'static str, hits: u64, ttl: u64) {
for name in [
"x-cache",
"x-cache-hits",
"x-cache-status",
"cache-status",
"x-cache-reason",
"x-cache-resident-age",
] {
headers.remove(name);
}
self.annotate_internal(headers, outcome, hits, ttl, None, false);
}
pub fn annotate_reason(
&self,
headers: &mut HeaderMap,
outcome: &'static str,
hits: u64,
ttl: u64,
reason: &'static str,
) {
self.annotate_internal(headers, outcome, hits, ttl, Some(reason), false);
}
pub fn annotate_reason_transformed(
&self,
headers: &mut HeaderMap,
outcome: &'static str,
hits: u64,
ttl: u64,
reason: &'static str,
transformed: bool,
) {
self.annotate_internal(headers, outcome, hits, ttl, Some(reason), transformed);
}
fn annotate_internal(
&self,
headers: &mut HeaderMap,
outcome: &'static str,
hits: u64,
ttl: u64,
reason: Option<&'static str>,
transformed: bool,
) {
if !self.enabled {
return;
}
@@ -196,89 +221,77 @@ impl Settings {
return;
}
if self.expose_status {
headers.insert("x-cache", HeaderValue::from_static(outcome));
insert_cache_diagnostic(
headers,
"x-cache",
"x-upstream-cache",
HeaderValue::from_static(outcome),
);
if let Some(reason) = reason {
insert_cache_diagnostic(
headers,
"x-cache-reason",
"x-upstream-cache-reason",
HeaderValue::from_static(reason),
);
}
}
if self.expose_hits {
headers.insert(
insert_cache_diagnostic(
headers,
"x-cache-hits",
"x-upstream-cache-hits",
HeaderValue::from_str(&hits.to_string()).expect("integer header"),
);
}
if self.expose_cache_status {
let value = match outcome {
"HIT" => format!("RustProxy; hit; ttl={ttl}"),
"MISS" => "RustProxy; fwd=uri-miss".into(),
_ => "RustProxy; fwd=bypass".into(),
let mut value = if matches!(
reason,
Some("cache_revalidated" | "cache_revalidated_uncached")
) {
"RustProxy; fwd=stale; fwd-status=304".to_owned()
} else {
match outcome {
"MISS" => "RustProxy; fwd=miss".to_owned(),
_ => "RustProxy; fwd=bypass".to_owned(),
}
};
headers.insert(
if let Some(reason) = reason {
value.push_str(&format!("; detail=\"{reason}\""));
}
if transformed {
value.push_str("; transformed");
}
headers.append(
"cache-status",
HeaderValue::from_str(&value).expect("generated cache status"),
HeaderValue::from_str(&value).expect("generated Cache-Status member"),
);
}
}
pub fn annotate_resident_age(&self, headers: &mut HeaderMap, resident_age: u64) {
headers.remove("x-cache-resident-age");
if !self.enabled {
return;
}
if self.expose_resident_age {
headers.insert(
if self.enabled && self.expose_resident_age {
insert_cache_diagnostic(
headers,
"x-cache-resident-age",
"x-upstream-cache-resident-age",
HeaderValue::from_str(&resident_age.to_string()).expect("integer header"),
);
}
}
pub fn annotate_transformed(&self, headers: &mut HeaderMap, transformed: bool) {
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
.get("cache-status")
.and_then(|value| value.to_str().ok())
.unwrap_or("RustProxy");
if base
.split(';')
.any(|part| part.trim().eq_ignore_ascii_case("transformed"))
{
return;
}
if let Ok(value) = format!("{base}; transformed").parse() {
headers.insert("cache-status", value);
}
}
pub fn annotate_reason(
&self,
headers: &mut HeaderMap,
outcome: &'static str,
hits: u64,
ttl: u64,
reason: &'static str,
) {
self.annotate(headers, outcome, hits, ttl);
if !self.enabled || (self.expose_only_hits && outcome != "HIT") {
return;
}
if self.expose_status {
headers.insert("x-cache-reason", HeaderValue::from_static(reason));
}
if self.expose_cache_status {
let base = headers
.get("cache-status")
.and_then(|v| v.to_str().ok())
.unwrap_or("RustProxy");
if let Ok(value) = format!("{base}; detail=\"{reason}\"").parse() {
headers.insert("cache-status", value);
}
}
}
fn insert_cache_diagnostic(
headers: &mut HeaderMap,
name: &'static str,
upstream_name: &'static str,
value: HeaderValue,
) {
let upstream_values: Vec<HeaderValue> = headers.get_all(name).iter().cloned().collect();
for upstream_value in upstream_values {
headers.append(upstream_name, upstream_value);
}
headers.insert(name, value);
}
fn valid_relative_cache_path(value: &str) -> bool {
if value.is_empty() || value.len() > 256 {