v0.34.7
This commit is contained in:
1 parent
3ea00045bf
commit
1cd6b7ac99
22 files changed
+550
-149
No files matched your search
@@ -2062,10 +2062,17 @@
|
||||
},
|
||||
"default": []
|
||||
},
|
||||
"varnish_grace_seconds": {
|
||||
"type": "integer",
|
||||
"minimum": 0,
|
||||
"maximum": 604800,
|
||||
"default": 60,
|
||||
"description": "Implicit grace window in seconds for eligible positive-TTL objects in Varnish-compatible mode without an explicit origin stale-while-revalidate directive. Zero disables implicit grace. Explicit origin stale-while-revalidate, including =0, takes precedence."
|
||||
},
|
||||
"varnish_compatible": {
|
||||
"type": "boolean",
|
||||
"default": true,
|
||||
"description": "Default true: Varnish-style request cache policy (ignore client Cache-Control/Pragma directives including no-cache, max-age=0, only-if-cached); reject origin no-cache, Surrogate-Control no-store and nonpositive remaining TTL; 10-second stale-while-revalidate grace for eligible stored objects. Existing RustProxy privacy, cookies, Vary, explicit TTL and invalidation options remain in force. False restores strict client-cache directive handling; switching modes invalidates cache; not full VCL emulation."
|
||||
"description": "Default true: ignore only client hard-reload no-cache, max-age=0 and Pragma: no-cache on fresh cache lookups. Preserve client no-store, only-if-cached (504 on MISS), min-fresh/max-stale, origin ETag revalidation and zero-TTL stale-if-error storage. A positive default_ttl_seconds explicitly allows public origin no-cache responses to be reused for that fallback TTL, even without validators; zero keeps validator-only revalidation. Surrogate-Control: no-store and all private/no-store/Set-Cookie/Vary restrictions remain active. Eligible positive-TTL entries without an explicit stale-while-revalidate directive get configurable grace (varnish_grace_seconds, default 60s; explicit =0 is honored). False restores strict browser reload. Switching modes invalidates cache; not full Varnish VCL emulation."
|
||||
}
|
||||
},
|
||||
"additionalProperties": false
|
||||
|
||||
@@ -11,7 +11,7 @@ function renderSettings() {
|
||||
$("compress-min").value = compression.min_bytes ?? 1024; syncServerMode();
|
||||
}
|
||||
if (!settingsDirty.has("cache-form")) {
|
||||
const c = config.cache || {}; $("cache-enabled").checked = !!c.enabled; $("cache-varnish-compatible").checked = c.varnish_compatible !== false; $("cache-memory").value = (c.max_bytes ?? 268435456) / 1048576;
|
||||
const c = config.cache || {}; $("cache-enabled").checked = !!c.enabled; $("cache-varnish-compatible").checked = c.varnish_compatible !== false; $("cache-varnish-grace").value = c.varnish_grace_seconds ?? 60; $("cache-memory").value = (c.max_bytes ?? 268435456) / 1048576;
|
||||
$("cache-transient-memory").value = (c.transient_max_bytes ?? 67108864) / 1048576;
|
||||
$("cache-object").value = (c.max_object_bytes ?? 16777216) / 1024; $("cache-entries").value = c.max_entries ?? 4096;
|
||||
$("cache-eviction-limit").value = c.hot_eviction_max_objects ?? 64;
|
||||
@@ -286,7 +286,7 @@ bindSettingsForm("response-form", next => {
|
||||
next.compression = { min_bytes: Number($("compress-min").value) }; for (const name of ["gzip", "br", "zstd", "deflate"]) next.compression[name] = $(`compress-${name}`).checked;
|
||||
}, "response", next => ({ server_header: next.server_header, diagnostic_headers: next.diagnostic_headers, compression: next.compression }));
|
||||
bindSettingsForm("cache-form", next => {
|
||||
next.cache = { ...(next.cache || {}), enabled: $("cache-enabled").checked, varnish_compatible: $("cache-varnish-compatible").checked, memory_preset: selectedCacheMemoryPreset, max_bytes: Math.round(Number($("cache-memory").value) * 1048576), transient_max_bytes: Math.round(Number($("cache-transient-memory").value) * 1048576), max_object_bytes: Number($("cache-object").value) * 1024, max_entries: Number($("cache-entries").value), hot_eviction_max_objects: Number($("cache-eviction-limit").value), hot_auto_trim_enabled: $("cache-auto-trim-enabled").checked, hot_auto_trim_after_seconds: Number($("cache-auto-trim-after").value), hot_auto_trim_target_percent: Number($("cache-auto-trim-target").value), cold_enabled: $("cache-cold-enabled").checked, cold_preset: selectedCacheColdPreset, cold_path: $("cache-cold-path").value.trim(), cold_max_bytes: Math.round(Number($("cache-cold-bytes").value) * 1048576), cold_max_entries: Number($("cache-cold-entries").value), cold_queue_max_bytes: Math.round(Number($("cache-cold-queue-bytes").value) * 1048576), cold_gc_interval_seconds: Number($("cache-cold-gc-interval").value), cold_gc_max_delete: Number($("cache-cold-gc-max-delete").value), cold_after_seconds: Number($("cache-cold-after").value), cold_max_hot_seconds: Number($("cache-cold-max-hot").value), cold_on_idle: $("cache-cold-on-idle").checked, cold_on_age: $("cache-cold-on-age").checked, cold_on_lru: $("cache-cold-on-lru").checked, cold_on_shutdown: $("cache-cold-on-shutdown").checked, max_ttl_seconds: Number($("cache-ttl").value), default_ttl_seconds: Number($("cache-default-ttl").value), collapse_enabled: $("cache-collapse-enabled").checked, collapse_wait_timeout_ms: Number($("cache-collapse-timeout").value), collapse_timeout_fallback: $("cache-collapse-fallback").value, stale_if_error_timeout: $("cache-sie-timeout").checked, stale_if_error_connection: $("cache-sie-connection").checked, stale_if_error_dns: $("cache-sie-dns").checked, stale_if_error_tls: $("cache-sie-tls").checked, stale_if_error_statuses: $("cache-sie-statuses").value.split(/[\s,]+/).filter(Boolean).map(Number), proactive_refresh_enabled: $("cache-proactive-enabled").checked, proactive_refresh_before_expiry_seconds: Number($("cache-proactive-before").value), proactive_refresh_percent: Number($("cache-proactive-percent").value), proactive_refresh_max_inflight: Number($("cache-proactive-inflight").value), bypass_query: $("cache-query").checked, bypass_prefixes: $("cache-prefixes").value.split(/\r?\n/).map(v => v.trim()).filter(Boolean), http_invalidation_allowed_cidrs: $("cache-http-invalidation-cidrs").value.split(/[\n,]+/).map(v => v.trim()).filter(Boolean), static_ignore_cookies: $("cache-static-cookie").checked, static_extensions: $("cache-static-extensions").value.split(/[\n,]+/).map(v => v.trim().replace(/^\./, "").toLowerCase()).filter(Boolean), expose_status: $("cache-status-header").checked, expose_hits: $("cache-hits-header").checked, expose_cache_status: $("cache-rfc-header").checked, expose_resident_age: $("cache-resident-age-header").checked, expose_only_hits: $("cache-only-hits").checked, via_header: $("cache-via-enabled").checked ? $("cache-via-value").value.trim() : null };
|
||||
next.cache = { ...(next.cache || {}), enabled: $("cache-enabled").checked, varnish_compatible: $("cache-varnish-compatible").checked, varnish_grace_seconds: Number($("cache-varnish-grace").value), memory_preset: selectedCacheMemoryPreset, max_bytes: Math.round(Number($("cache-memory").value) * 1048576), transient_max_bytes: Math.round(Number($("cache-transient-memory").value) * 1048576), max_object_bytes: Number($("cache-object").value) * 1024, max_entries: Number($("cache-entries").value), hot_eviction_max_objects: Number($("cache-eviction-limit").value), hot_auto_trim_enabled: $("cache-auto-trim-enabled").checked, hot_auto_trim_after_seconds: Number($("cache-auto-trim-after").value), hot_auto_trim_target_percent: Number($("cache-auto-trim-target").value), cold_enabled: $("cache-cold-enabled").checked, cold_preset: selectedCacheColdPreset, cold_path: $("cache-cold-path").value.trim(), cold_max_bytes: Math.round(Number($("cache-cold-bytes").value) * 1048576), cold_max_entries: Number($("cache-cold-entries").value), cold_queue_max_bytes: Math.round(Number($("cache-cold-queue-bytes").value) * 1048576), cold_gc_interval_seconds: Number($("cache-cold-gc-interval").value), cold_gc_max_delete: Number($("cache-cold-gc-max-delete").value), cold_after_seconds: Number($("cache-cold-after").value), cold_max_hot_seconds: Number($("cache-cold-max-hot").value), cold_on_idle: $("cache-cold-on-idle").checked, cold_on_age: $("cache-cold-on-age").checked, cold_on_lru: $("cache-cold-on-lru").checked, cold_on_shutdown: $("cache-cold-on-shutdown").checked, max_ttl_seconds: Number($("cache-ttl").value), default_ttl_seconds: Number($("cache-default-ttl").value), collapse_enabled: $("cache-collapse-enabled").checked, collapse_wait_timeout_ms: Number($("cache-collapse-timeout").value), collapse_timeout_fallback: $("cache-collapse-fallback").value, stale_if_error_timeout: $("cache-sie-timeout").checked, stale_if_error_connection: $("cache-sie-connection").checked, stale_if_error_dns: $("cache-sie-dns").checked, stale_if_error_tls: $("cache-sie-tls").checked, stale_if_error_statuses: $("cache-sie-statuses").value.split(/[\s,]+/).filter(Boolean).map(Number), proactive_refresh_enabled: $("cache-proactive-enabled").checked, proactive_refresh_before_expiry_seconds: Number($("cache-proactive-before").value), proactive_refresh_percent: Number($("cache-proactive-percent").value), proactive_refresh_max_inflight: Number($("cache-proactive-inflight").value), bypass_query: $("cache-query").checked, bypass_prefixes: $("cache-prefixes").value.split(/\r?\n/).map(v => v.trim()).filter(Boolean), http_invalidation_allowed_cidrs: $("cache-http-invalidation-cidrs").value.split(/[\n,]+/).map(v => v.trim()).filter(Boolean), static_ignore_cookies: $("cache-static-cookie").checked, static_extensions: $("cache-static-extensions").value.split(/[\n,]+/).map(v => v.trim().replace(/^\./, "").toLowerCase()).filter(Boolean), expose_status: $("cache-status-header").checked, expose_hits: $("cache-hits-header").checked, expose_cache_status: $("cache-rfc-header").checked, expose_resident_age: $("cache-resident-age-header").checked, expose_only_hits: $("cache-only-hits").checked, via_header: $("cache-via-enabled").checked ? $("cache-via-value").value.trim() : null };
|
||||
}, "cache");
|
||||
bindSettingsForm("transform-form", next => {
|
||||
next.transform = {
|
||||
|
||||
@@ -2210,9 +2210,24 @@
|
||||
Authorization, cookies and private/no-store responses still bypass the cache.
|
||||
One byte range can be served from a complete cached object;
|
||||
multipart/unsupported ranges pass through.</p>
|
||||
<label class="check"><input id="cache-varnish-compatible" type="checkbox" /><span
|
||||
data-i18n="cacheVarnishCompatible">Varnish-compatible cache policy (recommended; enabled by default)</span></label>
|
||||
<p class="fine" data-i18n="cacheVarnishCompatibleHelp">When enabled, client Cache-Control and Pragma are ignored for cache lookup: Shift+F5/no-cache/max-age=0 does not replace a fresh HIT or reset its Age. Response private/no-store/no-cache and Surrogate-Control no-store stay uncacheable, responses with no remaining TTL stay out of cache, and eligible expired objects may use up to 10 seconds of background-refresh grace. Existing static-cookie exceptions, Authorization protection, Vary, explicit TTL limits, BAN/PURGE, HOT/COLD, transforms and unsafe-force rules remain independent. Off restores the previous strict client HTTP caching policy. Changing modes invalidates stored objects. This is not full Varnish VCL emulation.</p>
|
||||
<div class="cache-varnish-setting">
|
||||
<label class="check"><input id="cache-varnish-compatible" type="checkbox" /><span
|
||||
data-i18n="cacheVarnishCompatible">Varnish-compatible cache policy (recommended; enabled by default)</span></label>
|
||||
<details class="metric-info cache-varnish-info">
|
||||
<summary data-i18n-aria="cacheVarnishCompatibleInfoLabel"
|
||||
aria-label="Varnish-compatible cache behavior">i</summary>
|
||||
<div class="metric-info-popover" role="note">
|
||||
<p class="fine" data-i18n="cacheVarnishCompatibleHelp">A browser Shift+F5 (no-cache, max-age=0 or Pragma: no-cache) uses a fresh cache HIT without replacing it or resetting Age.</p>
|
||||
<p class="fine" data-i18n="cacheVarnishCompatibleSafeguards">Preserves client no-store, only-if-cached (504 on MISS; no origin contact or background refresh), min-fresh and max-stale (including max-stale=0 during grace); existing cookie rules, Authorization, Vary, PURGE/BAN, HOT/COLD and transformations stay active.</p>
|
||||
<p class="fine" data-i18n="cacheVarnishCompatibleBackendHelp">Origin no-cache with a validator remains revalidatable. If an explicit fallback TTL is set, public no-cache responses may instead be reused for that TTL, even without a validator. Private/no-store/Set-Cookie and Surrogate-Control: no-store remain blocked. Zero-TTL objects may be retained for stale-if-error or revalidation; explicit stale-while-revalidate=0 is respected.</p>
|
||||
<p class="fine" data-i18n="cacheVarnishCompatibleModeHelp">Implicit grace (60 seconds by default, configurable below) only applies to eligible fresh-at-storage responses without an explicit stale-while-revalidate directive. Off restores strict client reload semantics. Changing the mode invalidates existing cached objects. This is not full Varnish VCL emulation.</p>
|
||||
</div>
|
||||
</details>
|
||||
</div>
|
||||
<div class="cache-varnish-grace-field">
|
||||
<label for="cache-varnish-grace" data-i18n="cacheVarnishGrace">Default grace (seconds, 0 = off)</label>
|
||||
<input id="cache-varnish-grace" type="number" min="0" max="604800" step="1" required />
|
||||
</div>
|
||||
<div class="card soft-card cache-memory-sizing">
|
||||
<div class="card-heading">
|
||||
<h3 data-i18n="cacheMemorySizingTitle">Memory sizing</h3>
|
||||
|
||||
@@ -5580,6 +5580,13 @@ dialog .window-heading {
|
||||
white-space: normal
|
||||
}
|
||||
|
||||
/* Nested Settings tab bars must scroll with their content. The global sticky
|
||||
rule otherwise lets cache subtabs paint across checkboxes while scrolling. */
|
||||
#panel-settings .settings-tabs.sub-tabs {
|
||||
position: static;
|
||||
top: auto;
|
||||
}
|
||||
|
||||
#panel-settings .settings-pages {
|
||||
min-width: 0
|
||||
}
|
||||
@@ -9387,6 +9394,51 @@ html[data-chart-style] :is(#workspace, dialog) svg polyline {
|
||||
white-space: nowrap;
|
||||
}
|
||||
|
||||
.cache-varnish-setting {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
gap: 8px;
|
||||
margin-top: 14px;
|
||||
position: relative;
|
||||
}
|
||||
|
||||
.cache-varnish-setting .check {
|
||||
min-width: 0;
|
||||
flex: 0 1 auto;
|
||||
margin: 0 !important;
|
||||
}
|
||||
|
||||
.cache-varnish-info {
|
||||
position: static;
|
||||
flex-shrink: 0;
|
||||
}
|
||||
|
||||
.cache-varnish-grace-field {
|
||||
width: min(320px, 100%);
|
||||
min-width: 0;
|
||||
margin-top: 12px;
|
||||
}
|
||||
|
||||
.cache-varnish-grace-field label {
|
||||
display: block;
|
||||
}
|
||||
|
||||
.cache-varnish-grace-field input {
|
||||
display: block;
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
|
||||
.cache-varnish-info .metric-info-popover {
|
||||
width: calc(min(440px, 100vw - 56px));
|
||||
max-height: calc(min(65vh, 450px));
|
||||
overflow-y: auto;
|
||||
}
|
||||
|
||||
.cache-varnish-info .metric-info-popover .fine + .fine {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
.cache-maintenance-help {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
Reference in new issue
Block a user