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:
@@ -104,6 +104,7 @@ internal sealed class AdminPipeServer : BackgroundService
|
||||
Running = true,
|
||||
HttpPort = snap.HttpPort,
|
||||
HttpsPort = snap.HttpsBinding?.Port,
|
||||
DisplayHost = snap.DisplayHost,
|
||||
StartedAt = _state.StartedAt,
|
||||
EndpointCount = snap.Endpoints.Count,
|
||||
});
|
||||
|
||||
@@ -36,7 +36,7 @@ try
|
||||
|
||||
builder.WebHost.ConfigureKestrel(opts =>
|
||||
{
|
||||
opts.ListenAnyIP(initialConfig.HttpPort);
|
||||
ConfigureHttp(opts, initialConfig);
|
||||
ConfigureHttps(opts, initialConfig.HttpsBinding);
|
||||
});
|
||||
|
||||
@@ -87,6 +87,24 @@ finally
|
||||
Log.CloseAndFlush();
|
||||
}
|
||||
|
||||
static void ConfigureHttp(Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions opts, ServerConfig cfg)
|
||||
{
|
||||
if (cfg.BindAddresses is { Count: > 0 } binds)
|
||||
{
|
||||
foreach (var entry in binds)
|
||||
{
|
||||
if (System.Net.IPAddress.TryParse(entry, out var ip))
|
||||
opts.Listen(ip, cfg.HttpPort);
|
||||
else
|
||||
Log.Warning("Skipping invalid bind address {Entry}", entry);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
opts.ListenAnyIP(cfg.HttpPort);
|
||||
}
|
||||
}
|
||||
|
||||
static void ConfigureHttps(Microsoft.AspNetCore.Server.Kestrel.Core.KestrelServerOptions opts, HttpsBinding? binding)
|
||||
{
|
||||
if (binding is null || binding.Kind == HttpsBindingKind.None) return;
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user