This commit is contained in:
Mateusz Gruszczyński committed 2026-10-08 15:59:37 +02:00
1 parent 65e082b9d1
commit 76cb4acef0
72 files changed
+6134 -4709

No files matched your search

+42
View File
@@ -277,6 +277,45 @@ fn valid_relative_cache_path(value: &str) -> bool {
.all(|part| matches!(part, Component::Normal(_)))
}
/// Explicit, per-vhost-only request-side cache override. It never weakens the
/// response-side privacy guards (Set-Cookie/private/no-store/Vary rules).
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
#[serde(default, deny_unknown_fields)]
pub struct UnsafeForce {
pub enabled: bool,
pub targets: Vec<String>,
}
impl UnsafeForce {
pub fn validate(&self) -> Result<()> {
ensure!(self.targets.len() <= 32, "forced cache supports at most 32 target prefixes");
for target in &self.targets {
ensure!(
!target.is_empty()
&& target.len() <= 2048
&& target.starts_with('/')
&& !target.contains('#')
&& !target.chars().any(char::is_control),
"forced cache targets must be 1..2048 byte origin-form path/query prefixes"
);
let path = target.split('?').next().unwrap_or(target);
ensure!(crate::acl::routing_path(path)? == path, "forced cache target path must be normalized");
}
Ok(())
}
pub fn matches(&self, path: &str, target: &str) -> bool {
if !self.enabled {
return false;
}
self.targets.iter().any(|configured| {
if configured.contains('?') {
target.starts_with(configured)
} else {
crate::config::prefix_matches(configured, path)
}
})
}
}
/// Per-vhost behavior, not independent memory pools. None inherits the global
/// default; the global resident-byte/entry/object ceilings remain hard limits.
#[derive(Debug, Clone, Default, Serialize, Deserialize)]
@@ -294,9 +333,12 @@ pub struct Overrides {
pub expose_hits: Option<bool>,
pub expose_cache_status: Option<bool>,
pub expose_resident_age: Option<bool>,
/// Deliberately unavailable in the global cache configuration.
pub unsafe_force: UnsafeForce,
}
impl Overrides {
pub fn resolve(&self, global: &Settings) -> Result<Settings> {
self.unsafe_force.validate()?;
let mut result = global.clone();
// A vhost may narrow the global policy, but can never re-enable a cache
// that the administrator disabled globally.