Configurable bind addresses + display host in Server Settings

ServerConfig grows two fields:
- BindAddresses: list of IPs Kestrel binds to (empty = all interfaces,
  current behavior). Listening only on a subset is useful when the host
  has multiple NICs and the webhook should not be reachable on all of
  them.
- DisplayHost: the hostname/IP the GUI splices into the URL column and
  Copy URL button. Cosmetic; doesn't affect what the server accepts.

Server Settings dialog gains a "Network" section: a checkbox for "all
interfaces" plus per-NIC checkboxes auto-detected via NetworkInterface.
GetAllNetworkInterfaces, and an editable ComboBox for the display host
pre-populated with detected IPs and the machine name.

Listener restart fires on BindAddresses change but not on DisplayHost
change (cosmetic).

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-05-08 09:27:18 -04:00
parent 4ef8d20578
commit 28479272d5
10 changed files with 162 additions and 4 deletions
@@ -102,6 +102,7 @@ public sealed class ServiceState
private static bool HasListenerSettingsChanged(ServerConfig oldCfg, ServerConfig newCfg)
{
if (oldCfg.HttpPort != newCfg.HttpPort) return true;
if (!oldCfg.BindAddresses.SequenceEqual(newCfg.BindAddresses, StringComparer.OrdinalIgnoreCase)) return true;
var a = oldCfg.HttpsBinding;
var b = newCfg.HttpsBinding;
if ((a is null) != (b is null)) return true;
@@ -110,6 +111,7 @@ public sealed class ServiceState
if (a.Kind != b.Kind || a.Port != b.Port || a.PfxPath != b.PfxPath || a.Thumbprint != b.Thumbprint)
return true;
}
// DisplayHost is cosmetic; don't restart for it.
return false;
}
}