v0.35.1: performance, AGPL licensing and documentation overhaul
- Web Server reads static files inline; proxy middleware chain flattened - About window with license summary and project links; AGPL-3.0-or-later - Rewritten documentation: feature list, screenshots, performance guide - Fix false spikes in per-Vhost request-rate charts
This commit is contained in:
1 parent
d3b492874b
commit
eba9f89283
135 files changed
+1425
-1064
No files matched your search
@@ -24,7 +24,6 @@ const group = (key, advanced = false) => {
|
||||
const body = el("div", undefined, "vh-grid"); box.append(body); container.append(box); return body;
|
||||
};
|
||||
const note = (parent, key) => { const node = text("p", key, "fine vh-wide"); parent.append(node); return node; };
|
||||
// Presentation-only subgroup: all existing inputs remain inside their original form.
|
||||
const subsection = (parent, key) => {
|
||||
const box = el("section", undefined, "vh-wide vh-setting-section");
|
||||
box.append(text("h3", key));
|
||||
@@ -215,8 +214,7 @@ function memberRow(parent, value = { id: `origin-${parent.children.length + 1}`,
|
||||
const connection = el("div", undefined, "vh-wide vh-backend-switches vh-backend-connection"); main.append(connection);
|
||||
controls["member-private"] = field(connection, "member-private", "vhPrivate", value.allow_private, "checkbox");
|
||||
const preserve = field(connection, "member-host", "vhPreserveHost", value.preserve_host === true, "checkbox");
|
||||
// Preserve Host is a request-authority choice, not an HTTP/1.1-only option.
|
||||
// The Rust forwarder keeps HTTP/2 :authority consistent with this value.
|
||||
// Preserve Host also applies to HTTP/2 :authority.
|
||||
|
||||
const advanced = el("details", undefined, "vh-wide vh-backend-advanced"), extra = el("div", undefined, "vh-grid"); advanced.append(text("summary", "advanced"), extra);
|
||||
field(extra, "member-allowlist", "vhAddressAllowlist", (value.address_allowlist || []).join("\n"), "textarea", { rows: 2, maxLength: 8192 });
|
||||
@@ -230,8 +228,7 @@ function memberRow(parent, value = { id: `origin-${parent.children.length + 1}`,
|
||||
field(extra, "member-max-concurrent", "vhMaxConcurrentRequests", value.max_concurrent_requests ?? 0, "number", { required: true, min: 0, max: 1000000 });
|
||||
field(extra, "member-queue-timeout", "vhBackendQueueTimeout", value.queue_timeout_ms ?? 0, "number", { required: true, min: 0, max: 60000 });
|
||||
note(extra, "vhBackendCapacityHelp");
|
||||
// The per-member settings live in the Health tab. Keep one persistent form
|
||||
// per backend, so switching the selection never discards unsaved edits.
|
||||
// One persistent form per backend keeps unsaved edits when switching.
|
||||
const healthPanel = el("section", undefined, "vh-grid vh-backend-health-panel");
|
||||
const customHealth = field(healthPanel, "member-health-custom", "backendHealthOverride", value.health_check != null, "checkbox");
|
||||
const health = value.health_check || {};
|
||||
@@ -305,9 +302,7 @@ function debugOriginIssues(members) {
|
||||
let parsed; try { parsed = new URL(member.url); } catch { return false; }
|
||||
const host = parsed.hostname.replace(/^\[|\]$/g, ""), ipHost = /^\d{1,3}(?:\.\d{1,3}){3}$/.test(host) || host.includes(":");
|
||||
if (parsed.protocol !== "https:" || !ipHost) return false;
|
||||
// The troubleshooting preset is OPTIONAL, not a protocol compatibility rule.
|
||||
// Warn only when IP-host TLS verification may need an explicit identity;
|
||||
// HTTP/1.1, Auto and H2 plus preserve_host are all valid configurations.
|
||||
// Warn only when TLS verification of an IP host needs an explicit server name.
|
||||
return member.tls_verify === true && !String(member.tls_server_name || "").trim();
|
||||
});
|
||||
}
|
||||
@@ -498,9 +493,7 @@ function locationsEditor(parent, values) {
|
||||
row.addEventListener("input", () => { syncUi(); sync(); }); row.addEventListener("change", () => { syncUi(); sync(); });
|
||||
rows.append(row); syncUi();
|
||||
}
|
||||
// The main vhost backend is an internal fallback, not a Custom location.
|
||||
// An empty location list must stay empty so the editor cannot accidentally
|
||||
// delete or recreate the main route as user configuration.
|
||||
// The main backend is an internal fallback, never an editable location.
|
||||
for (const value of values) add(value);
|
||||
const bottom = el("div", undefined, "vh-wide location-toolbar location-toolbar-bottom"); bottom.append(button("locationAdd", () => { add(); sync(); }, "primary")); parent.append(bottom);
|
||||
form.querySelector(".vh-members").addEventListener("input", () => { for (const select of rows.querySelectorAll('[name="location-backend"]')) memberOptions(select); });
|
||||
|
||||
Reference in new issue
Block a user