v0.27.0-hotfix
This commit is contained in:
1 parent
762eb9e28b
commit
39238fdf53
17 files changed
+74
-67
No files matched your search
+10
-6
@@ -2424,31 +2424,35 @@
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"default": null,
|
||||
"description": "Per-published-vhost dynamic compression override. null inherits the enclosing/global policy; true/false enables or disables the scope."
|
||||
"description": "Single per-Docker-vhost dynamic compression switch. null inherits the global policy; true/false enables or disables compression for this publication. Codec availability and priority come from global Response settings."
|
||||
},
|
||||
"compression_zstd": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"default": null,
|
||||
"description": "Optional per-Docker-vhost Zstandard override. null inherits; globally disabled codecs remain unavailable."
|
||||
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; Zstandard availability is controlled by global Response settings.",
|
||||
"deprecated": true
|
||||
},
|
||||
"compression_br": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"default": null,
|
||||
"description": "Optional per-Docker-vhost Brotli override. null inherits; globally disabled codecs remain unavailable."
|
||||
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; Brotli availability is controlled by global Response settings.",
|
||||
"deprecated": true
|
||||
},
|
||||
"compression_gzip": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"default": null,
|
||||
"description": "Optional per-Docker-vhost gzip override. null inherits; globally disabled codecs remain unavailable."
|
||||
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; gzip availability is controlled by global Response settings.",
|
||||
"deprecated": true
|
||||
},
|
||||
"compression_deflate": {
|
||||
"type": "boolean",
|
||||
"nullable": true,
|
||||
"default": null,
|
||||
"description": "Optional per-Docker-vhost deflate override. null inherits; globally disabled codecs remain unavailable."
|
||||
"description": "Legacy compatibility field accepted when loading older 0.27.0 pre-release configuration. Ignored for Docker vhosts; deflate availability is controlled by global Response settings.",
|
||||
"deprecated": true
|
||||
}
|
||||
},
|
||||
"required": [
|
||||
@@ -5524,7 +5528,7 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
"description": "Sets an HttpOnly SameSite=Strict session cookie. Browser sessions use the configured 7–30 day absolute lifetime. Use the panel sign-in page. No bearer token or URL token is accepted.",
|
||||
"description": "Sets an HttpOnly SameSite=Strict session cookie. Browser sessions use the configured 7\u201330 day absolute lifetime. Use the panel sign-in page. No bearer token or URL token is accepted.",
|
||||
"security": [],
|
||||
"parameters": [
|
||||
{
|
||||
|
||||
+6
-10
@@ -251,8 +251,9 @@
|
||||
const inline = row.querySelector(".docker-acl-inline")?.checked;
|
||||
return {
|
||||
service_key: row.dataset.key, hostname: row.querySelector(".docker-hostname").value.trim().toLowerCase(), aliases: row._readAliases?.() || [], target_ip: row.querySelector(".docker-target-ip").value || null,
|
||||
enabled: true, scheme: row.querySelector(".docker-scheme").value, preserve_host: row.querySelector(".docker-preserve-host").checked, force_ssl: row.querySelector(".docker-force-ssl").checked, websockets: row.querySelector(".docker-websockets").checked, cache_enabled: row.querySelector(".docker-cache-enabled").checked, transform_enabled: row.querySelector(".docker-transform-enabled").checked, compression_enabled: (() => { const value = row.querySelector(".docker-compression-enabled").value; return value === "" ? null : value === "on"; })(),
|
||||
compression_zstd: (() => { const value = row.querySelector(".docker-compression-zstd").value; return value === "" ? null : value === "on"; })(), compression_br: (() => { const value = row.querySelector(".docker-compression-br").value; return value === "" ? null : value === "on"; })(), compression_gzip: (() => { const value = row.querySelector(".docker-compression-gzip").value; return value === "" ? null : value === "on"; })(), compression_deflate: (() => { const value = row.querySelector(".docker-compression-deflate").value; return value === "" ? null : value === "on"; })(),
|
||||
enabled: true, scheme: row.querySelector(".docker-scheme").value, preserve_host: row.querySelector(".docker-preserve-host").checked, force_ssl: row.querySelector(".docker-force-ssl").checked, websockets: row.querySelector(".docker-websockets").checked, cache_enabled: row.querySelector(".docker-cache-enabled").checked, transform_enabled: row.querySelector(".docker-transform-enabled").checked, compression_enabled: row.querySelector(".docker-compression-enabled").checked,
|
||||
// Docker publications intentionally expose one compression switch only. Codec selection stays global.
|
||||
compression_zstd: null, compression_br: null, compression_gzip: null, compression_deflate: null,
|
||||
acl_profile_id: row.querySelector(".docker-acl-profile")?.value || null, acl: inline ? { default: row.querySelector(".docker-acl-default").value, rules: parseRules(row.querySelector(".docker-acl-rules").value) } : null,
|
||||
proxy_timeouts: { connect_timeout_seconds: Number(row.querySelector(".docker-proxy-connect").value), response_header_timeout_seconds: Number(row.querySelector(".docker-proxy-header").value), read_timeout_seconds: Number(row.querySelector(".docker-proxy-read").value), send_timeout_seconds: Number(row.querySelector(".docker-proxy-send").value) },
|
||||
health_check: collectHealth(row), passive_health: collectPassiveHealth(row)
|
||||
@@ -289,14 +290,9 @@
|
||||
const websockets = input("", "checkbox", "docker-websockets"); websockets.checked = assignment?.websockets !== false; const websocketField = checkboxField("dockerWebsockets", websockets);
|
||||
const cacheEnabled = input("", "checkbox", "docker-cache-enabled"); cacheEnabled.checked = assignment?.cache_enabled === true; const cacheField = checkboxField("dockerCache", cacheEnabled);
|
||||
const transformEnabled = input("", "checkbox", "docker-transform-enabled"); transformEnabled.checked = assignment?.transform_enabled === true; const transformField = checkboxField("dockerTransform", transformEnabled);
|
||||
const compressionSelect = (className, current) => { const select = el("select", undefined, className); for (const [value, keyName] of [["", "inherit"], ["on", "enabled"], ["off", "notEnabled"]]) { const option = el("option", t(keyName)); option.value = value; select.append(option); } select.value = current === true ? "on" : current === false ? "off" : ""; return select; };
|
||||
const compressionEnabled = compressionSelect("docker-compression-enabled", assignment?.compression_enabled);
|
||||
const compressionZstd = compressionSelect("docker-compression-zstd", assignment?.compression_zstd), compressionBr = compressionSelect("docker-compression-br", assignment?.compression_br), compressionGzip = compressionSelect("docker-compression-gzip", assignment?.compression_gzip), compressionDeflate = compressionSelect("docker-compression-deflate", assignment?.compression_deflate);
|
||||
const compressionFields = [[labeled("compressionZstd", compressionZstd), compressionZstd], [labeled("compressionBr", compressionBr), compressionBr], [labeled("compressionGzip", compressionGzip), compressionGzip], [labeled("compressionDeflate", compressionDeflate), compressionDeflate]];
|
||||
const syncCompressionVisibility = () => { const disabled = compressionEnabled.value === "off"; for (const [field, control] of compressionFields) { field.hidden = disabled; control.disabled = disabled; } };
|
||||
compressionEnabled.addEventListener("change", syncCompressionVisibility); syncCompressionVisibility();
|
||||
const switches = el("div", undefined, "docker-switch-row"); switches.append(preserveLabel, forceSslField, websocketField, cacheField, transformField);
|
||||
route.append(labeled("dockerHostname", host, t("dockerHostnameHelp").replace("{domain}", agent.base_domain)), aliases.node, labeled("dockerBackendIp", target), labeled("dockerBackendScheme", scheme), labeled("dockerCompression", compressionEnabled, t("dockerCompressionHelp")), ...compressionFields.map(([field]) => field), switches);
|
||||
const compressionEnabled = input("", "checkbox", "docker-compression-enabled"); compressionEnabled.checked = assignment?.compression_enabled !== false; const compressionField = checkboxField("dockerCompression", compressionEnabled); compressionField.title = t("dockerCompressionHelp");
|
||||
const switches = el("div", undefined, "docker-switch-row"); switches.append(preserveLabel, forceSslField, websocketField, cacheField, compressionField, transformField);
|
||||
route.append(labeled("dockerHostname", host, t("dockerHostnameHelp").replace("{domain}", agent.base_domain)), aliases.node, labeled("dockerBackendIp", target), labeled("dockerBackendScheme", scheme), switches);
|
||||
editor.append(route, aclEditor(assignment, agent), timeoutEditor(assignment), healthEditor(assignment), passiveHealthEditor(assignment));
|
||||
const actions = el("div", undefined, "docker-service-actions"), apply = el("button", t("dockerApplyService"), "outline docker-apply"); apply.type = "button"; apply.disabled = !publish.checked; apply.addEventListener("click", async () => { apply.disabled = true; try { await saveAssignment(agent.id, row, true); } catch (error) { toast(error.message, true); } finally { if (row.isConnected) apply.disabled = !publish.checked; } }); actions.append(apply); editor.append(actions); row.append(editor);
|
||||
function updateHint() { const targetLabel = target.selectedOptions?.[0]?.textContent || t("dockerBackendIpAuto"), aliasCount = aliases.count(); editorHint.textContent = `${host.value.trim() || technical} → ${scheme.value.toUpperCase()} · ${targetLabel}${aliasCount ? ` · +${aliasCount} ${t("dockerAliasesShort")}` : ""}`; } updateHint();
|
||||
|
||||
@@ -110,7 +110,10 @@ pub struct Assignment {
|
||||
/// the per-app redirect switch existed. New UI assignments persist true.
|
||||
pub force_ssl: Option<bool>,
|
||||
pub websockets: bool,
|
||||
/// Single Docker-vhost dynamic-compression switch. None inherits the global policy.
|
||||
pub compression_enabled: Option<bool>,
|
||||
/// Legacy pre-release 0.27.0 fields kept for saved-config compatibility. Docker
|
||||
/// reconciliation ignores per-codec overrides; codecs are selected globally.
|
||||
pub compression_gzip: Option<bool>,
|
||||
pub compression_br: Option<bool>,
|
||||
pub compression_zstd: Option<bool>,
|
||||
|
||||
@@ -118,13 +118,9 @@ pub fn effective_config(
|
||||
"force_ssl": assignment.force_ssl.unwrap_or(false),
|
||||
"websockets": assignment.websockets,
|
||||
"backends": backends,
|
||||
"compression": {
|
||||
"enabled": assignment.compression_enabled,
|
||||
"gzip": assignment.compression_gzip,
|
||||
"br": assignment.compression_br,
|
||||
"zstd": assignment.compression_zstd,
|
||||
"deflate": assignment.compression_deflate
|
||||
},
|
||||
// Docker publications intentionally use one compression switch. The enabled
|
||||
// codec set is inherited from global Response settings.
|
||||
"compression": {"enabled": assignment.compression_enabled},
|
||||
"cache": {"enabled": assignment.cache_enabled},
|
||||
"transform": {"enabled": assignment.transform_enabled},
|
||||
"acl_profile_id": assignment.acl_profile_id.clone().or_else(|| agent.acl_profile_id.clone()),
|
||||
|
||||
+4
-3
@@ -233,7 +233,7 @@ mod tests {
|
||||
assert!(effective.vhosts[0].backends.is_empty());
|
||||
assert!(effective.vhosts[0].transient_unavailable);
|
||||
assert_eq!(effective.vhosts[0].compression.enabled, Some(false));
|
||||
assert_eq!(effective.vhosts[0].compression.zstd, Some(false));
|
||||
assert_eq!(effective.vhosts[0].compression.zstd, None);
|
||||
|
||||
let policy = crate::config::ValidationPolicy {
|
||||
proxy_addr: "127.0.0.1:8080".parse().unwrap(),
|
||||
@@ -271,6 +271,7 @@ mod tests {
|
||||
service_key: "container:app:8080/tcp".into(),
|
||||
hostname: "app".into(),
|
||||
compression_enabled: Some(true),
|
||||
// Legacy per-codec values must not affect Docker vhosts.
|
||||
compression_gzip: Some(false),
|
||||
compression_br: Some(true),
|
||||
..Default::default()
|
||||
@@ -294,8 +295,8 @@ mod tests {
|
||||
assert_eq!(effective.vhosts[0].backends.len(), 1);
|
||||
assert!(!effective.vhosts[0].transient_unavailable);
|
||||
assert_eq!(effective.vhosts[0].compression.enabled, Some(true));
|
||||
assert_eq!(effective.vhosts[0].compression.gzip, Some(false));
|
||||
assert_eq!(effective.vhosts[0].compression.br, Some(true));
|
||||
assert_eq!(effective.vhosts[0].compression.gzip, None);
|
||||
assert_eq!(effective.vhosts[0].compression.br, None);
|
||||
}
|
||||
|
||||
#[test]
|
||||
|
||||
Reference in new issue
Block a user