From bc5e9803269b64e9719aaa5b502a0fc5a44e39fc Mon Sep 17 00:00:00 2001 From: sladro Date: Fri, 27 Mar 2026 11:00:35 +0800 Subject: [PATCH] fix: address windows agent host review feedback --- .../Configuration/AgentOptions.cs | 2 +- ...AgentOptionsServiceCollectionExtensions.cs | 36 ++++++++++ .../Configuration/AgentOptionsValidator.cs | 4 +- .../src/TermRemoteCtl.Agent/Program.cs | 16 +---- .../src/TermRemoteCtl.Agent/appsettings.json | 2 +- .../AgentOptionsPipelineTests.cs | 68 +++++++++++++++++++ .../AgentOptionsValidatorTests.cs | 2 +- .../TermRemoteCtl.Agent.Tests/UnitTest1.cs | 10 --- 8 files changed, 112 insertions(+), 28 deletions(-) create mode 100644 apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsServiceCollectionExtensions.cs create mode 100644 apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsPipelineTests.cs delete mode 100644 apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/UnitTest1.cs diff --git a/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptions.cs b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptions.cs index 530892b..c75a8bb 100644 --- a/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptions.cs +++ b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptions.cs @@ -8,7 +8,7 @@ public sealed class AgentOptions public string BindAddress { get; set; } = "0.0.0.0"; - public int HttpsPort { get; set; } + public int Port { get; set; } public int WebSocketFrameFlushMilliseconds { get; set; } diff --git a/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsServiceCollectionExtensions.cs b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsServiceCollectionExtensions.cs new file mode 100644 index 0000000..e4b7604 --- /dev/null +++ b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsServiceCollectionExtensions.cs @@ -0,0 +1,36 @@ +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; + +namespace TermRemoteCtl.Agent.Configuration; + +public static class AgentOptionsServiceCollectionExtensions +{ + public static AgentOptions AddAgentOptions(this IServiceCollection services, IConfiguration configuration) + { + var effectiveOptions = BuildEffectiveOptions(configuration); + + services.AddSingleton, AgentOptionsValidator>(); + services + .AddOptions() + .Configure(options => + { + options.DataRoot = effectiveOptions.DataRoot; + options.BindAddress = effectiveOptions.BindAddress; + options.Port = effectiveOptions.Port; + options.WebSocketFrameFlushMilliseconds = effectiveOptions.WebSocketFrameFlushMilliseconds; + options.RingBufferLineLimit = effectiveOptions.RingBufferLineLimit; + }) + .ValidateOnStart(); + + return effectiveOptions; + } + + private static AgentOptions BuildEffectiveOptions(IConfiguration configuration) + { + var options = new AgentOptions(); + configuration.GetSection(AgentOptions.SectionName).Bind(options); + options.DataRoot = AppPaths.ResolveDataRoot(configuration); + return options; + } +} diff --git a/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsValidator.cs b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsValidator.cs index f3ff91e..5037b34 100644 --- a/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsValidator.cs +++ b/apps/windows_agent/src/TermRemoteCtl.Agent/Configuration/AgentOptionsValidator.cs @@ -13,9 +13,9 @@ public sealed class AgentOptionsValidator : IValidateOptions failures.Add("Agent:DataRoot must be configured."); } - if (options.HttpsPort is < 1 or > 65535) + if (options.Port is < 1 or > 65535) { - failures.Add("Agent:HttpsPort must be between 1 and 65535."); + failures.Add("Agent:Port must be between 1 and 65535."); } if (options.WebSocketFrameFlushMilliseconds <= 0) diff --git a/apps/windows_agent/src/TermRemoteCtl.Agent/Program.cs b/apps/windows_agent/src/TermRemoteCtl.Agent/Program.cs index 9b4611c..394c926 100644 --- a/apps/windows_agent/src/TermRemoteCtl.Agent/Program.cs +++ b/apps/windows_agent/src/TermRemoteCtl.Agent/Program.cs @@ -1,23 +1,13 @@ using Microsoft.Extensions.Options; -using TermRemoteCtl.Agent; using TermRemoteCtl.Agent.Configuration; var builder = WebApplication.CreateBuilder(args); -var agentSection = builder.Configuration.GetSection(AgentOptions.SectionName); -var bindAddress = agentSection[nameof(AgentOptions.BindAddress)] ?? "0.0.0.0"; -var httpsPort = agentSection.GetValue(nameof(AgentOptions.HttpsPort)) ?? 9443; - -builder.WebHost.UseUrls($"http://{bindAddress}:{httpsPort}"); -builder.Services.AddSingleton, AgentOptionsValidator>(); -builder.Services - .AddOptions() - .Bind(agentSection) - .PostConfigure(options => options.DataRoot = AppPaths.ResolveDataRoot(builder.Configuration)) - .ValidateOnStart(); +var agentOptions = builder.Services.AddAgentOptions(builder.Configuration); +builder.WebHost.UseUrls($"http://{agentOptions.BindAddress}:{agentOptions.Port}"); var app = builder.Build(); -var agentOptions = app.Services.GetRequiredService>().Value; +agentOptions = app.Services.GetRequiredService>().Value; Directory.CreateDirectory(agentOptions.DataRoot); diff --git a/apps/windows_agent/src/TermRemoteCtl.Agent/appsettings.json b/apps/windows_agent/src/TermRemoteCtl.Agent/appsettings.json index aa50ffe..2f0f67e 100644 --- a/apps/windows_agent/src/TermRemoteCtl.Agent/appsettings.json +++ b/apps/windows_agent/src/TermRemoteCtl.Agent/appsettings.json @@ -2,7 +2,7 @@ "Agent": { "DataRoot": "C:\\ProgramData\\TermRemoteCtl", "BindAddress": "0.0.0.0", - "HttpsPort": 9443, + "Port": 9443, "WebSocketFrameFlushMilliseconds": 33, "RingBufferLineLimit": 4000 } diff --git a/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsPipelineTests.cs b/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsPipelineTests.cs new file mode 100644 index 0000000..ff891b2 --- /dev/null +++ b/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsPipelineTests.cs @@ -0,0 +1,68 @@ +using System.IO; +using Microsoft.Extensions.Configuration; +using Microsoft.Extensions.DependencyInjection; +using Microsoft.Extensions.Options; +using TermRemoteCtl.Agent.Configuration; + +namespace TermRemoteCtl.Agent.Tests.Configuration; + +public class AgentOptionsPipelineTests +{ + [Fact] + public void ResolveOptions_Uses_DataRoot_Fallback_When_Config_Omits_DataRoot() + { + var configuration = BuildConfiguration(new Dictionary + { + ["Agent:BindAddress"] = "127.0.0.1", + ["Agent:Port"] = "9443", + ["Agent:WebSocketFrameFlushMilliseconds"] = "33", + ["Agent:RingBufferLineLimit"] = "4000" + }); + + var services = new ServiceCollection(); + services.AddAgentOptions(configuration); + + using var provider = services.BuildServiceProvider(); + var options = provider.GetRequiredService>().Value; + + var expectedDataRoot = Path.Combine( + Environment.GetFolderPath(Environment.SpecialFolder.CommonApplicationData), + "TermRemoteCtl"); + + Assert.Equal(expectedDataRoot, options.DataRoot); + } + + [Theory] + [InlineData("0", "33", "Port")] + [InlineData("9443", "0", "WebSocketFrameFlushMilliseconds")] + public void ResolveOptions_Fails_When_Config_Is_Invalid( + string port, + string flushMilliseconds, + string expectedFailure) + { + var configuration = BuildConfiguration(new Dictionary + { + ["Agent:BindAddress"] = "127.0.0.1", + ["Agent:Port"] = port, + ["Agent:WebSocketFrameFlushMilliseconds"] = flushMilliseconds, + ["Agent:RingBufferLineLimit"] = "4000" + }); + + var services = new ServiceCollection(); + services.AddAgentOptions(configuration); + + using var provider = services.BuildServiceProvider(); + + var exception = Assert.Throws( + () => provider.GetRequiredService>().Value); + + Assert.Contains(exception.Failures, failure => failure.Contains(expectedFailure)); + } + + private static IConfiguration BuildConfiguration(IReadOnlyDictionary values) + { + return new ConfigurationBuilder() + .AddInMemoryCollection(values) + .Build(); + } +} diff --git a/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsValidatorTests.cs b/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsValidatorTests.cs index 533015a..1820931 100644 --- a/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsValidatorTests.cs +++ b/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/Configuration/AgentOptionsValidatorTests.cs @@ -11,7 +11,7 @@ public class AgentOptionsValidatorTests { DataRoot = "", BindAddress = "0.0.0.0", - HttpsPort = 9443 + Port = 9443 }; var validator = new AgentOptionsValidator(); diff --git a/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/UnitTest1.cs b/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/UnitTest1.cs deleted file mode 100644 index b87f866..0000000 --- a/apps/windows_agent/tests/TermRemoteCtl.Agent.Tests/UnitTest1.cs +++ /dev/null @@ -1,10 +0,0 @@ -namespace TermRemoteCtl.Agent.Tests; - -public class UnitTest1 -{ - [Fact] - public void Test1() - { - - } -} \ No newline at end of file