Refactor YAML parsing logic and settings handling across Client and Server projects, improve request building in the client.

This commit is contained in:
2025-08-24 09:34:54 +03:30
parent 3a9d48a3b6
commit a6d9ae87aa
7 changed files with 57 additions and 29 deletions

View File

@@ -0,0 +1,9 @@
using YamlDotNet.Serialization;
namespace VirtualDDNSRouter.Client.Context;
[YamlStaticContext]
[YamlSerializable(typeof(Settings))]
public partial class YamlStaticContextClient : StaticContext
{
}

View File

@@ -1,3 +1,4 @@
using VirtualDDNSRouter.Client.Context;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NamingConventions;
using Settings = VirtualDDNSRouter.Client.Models.Settings; using Settings = VirtualDDNSRouter.Client.Models.Settings;
@@ -16,7 +17,7 @@ public class Helpers
var yamlContent = await File.ReadAllTextAsync(YamlFilePath).ConfigureAwait(false); var yamlContent = await File.ReadAllTextAsync(YamlFilePath).ConfigureAwait(false);
// Build the deserializer with explicit naming convention // Build the deserializer with explicit naming convention
var deserializer = new StaticDeserializerBuilder(new YamlStaticContext()) var deserializer = new StaticDeserializerBuilder(new YamlStaticContextClient())
.WithNamingConvention(UnderscoredNamingConvention.Instance) .WithNamingConvention(UnderscoredNamingConvention.Instance)
.IgnoreUnmatchedProperties() .IgnoreUnmatchedProperties()
.Build(); .Build();
@@ -24,16 +25,10 @@ public class Helpers
// Deserialize into Settings // Deserialize into Settings
var settings = deserializer.Deserialize<Settings>(yamlContent); var settings = deserializer.Deserialize<Settings>(yamlContent);
if (settings is null || string.IsNullOrWhiteSpace(settings.Host) || string.IsNullOrWhiteSpace(settings.Path) || if (settings is null || string.IsNullOrWhiteSpace(settings.host) || string.IsNullOrWhiteSpace(settings.path) ||
string.IsNullOrWhiteSpace(settings.ApiKey)) string.IsNullOrWhiteSpace(settings.apiKey))
throw new Exception("Invalid settings file"); throw new Exception("Invalid settings file");
return settings; return settings;
} }
[YamlStaticContext]
[YamlSerializable(typeof(Settings))]
private partial class YamlStaticContext : StaticContext
{
}
} }

View File

@@ -1,10 +1,17 @@
using YamlDotNet.Serialization;
namespace VirtualDDNSRouter.Client.Models; namespace VirtualDDNSRouter.Client.Models;
public class Settings [YamlSerializable]
public record Settings
{ {
public string Host { get; set; } = string.Empty; public string host { get; set; } = string.Empty;
public string Path { get; set; } = string.Empty; public string path { get; set; } = string.Empty;
public ushort DestinationPort { get; set; } = 80; public ushort destinationPort { get; set; } = 80;
public string ApiKey { get; set; } = string.Empty; public string apiKey { get; set; } = string.Empty;
public ushort RefreshIntervalMinutes { get; set; } = 5; public ushort refreshIntervalMinutes { get; set; } = 5;
public Settings()
{
}
} }

View File

@@ -10,17 +10,34 @@ Console.CancelKeyPress += (s, e) =>
cts.Cancel(); cts.Cancel();
}; };
var timer = new PeriodicTimer(TimeSpan.FromMinutes(settings.RefreshIntervalMinutes)); var timer = new PeriodicTimer(TimeSpan.FromMinutes(settings.refreshIntervalMinutes));
var client = new HttpClient { Timeout = TimeSpan.FromSeconds(10) }; var client = new HttpClient { Timeout = TimeSpan.FromSeconds(10) };
var request = new HttpRequestMessage(HttpMethod.Get, var builder = new UriBuilder
new Uri($"{settings.Host}/setip/{settings.Path}/{settings.DestinationPort}/{settings.ApiKey}"));
while (await timer.WaitForNextTickAsync())
{ {
if (cts.IsCancellationRequested) break; Scheme = "http",
var response = await client.SendAsync(request, cts.Token); Host = settings.host,
if (response.IsSuccessStatusCode) Path = $"setip/{settings.path}/{settings.destinationPort}/{settings.apiKey}"
Console.WriteLine("[INFO] IP address updated at " + DateTime.Now.ToString("HH:mm:ss")); };
else
Console.WriteLine("[ERROR] IP address update failed at " + DateTime.Now.ToString("HH:mm:ss")); var request = new HttpRequestMessage(HttpMethod.Get, builder.Uri);
Console.WriteLine("[INFO] App started. Scheduling IP address update every " + settings.refreshIntervalMinutes +
" minutes.");
try
{
while (await timer.WaitForNextTickAsync(cts.Token))
{
if (cts.IsCancellationRequested) break;
var response = await client.SendAsync(request, cts.Token);
if (response.IsSuccessStatusCode)
Console.WriteLine("[INFO] IP address updated at " + DateTime.Now.ToString("HH:mm:ss"));
else
Console.WriteLine("[ERROR] IP address update failed at " + DateTime.Now.ToString("HH:mm:ss"));
}
}
catch (OperationCanceledException)
{
Console.WriteLine("[INFO] Shutdown complete.");
} }

View File

@@ -18,6 +18,7 @@
<ItemGroup> <ItemGroup>
<PackageReference Include="YamlDotNet" Version="16.3.0"/> <PackageReference Include="YamlDotNet" Version="16.3.0"/>
<PackageReference Include="Vecc.YamlDotNet.Analyzers.StaticGenerator" Version="16.3.0"/>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -5,6 +5,6 @@ namespace VirtualDDNSRouter.Server.Context;
[YamlStaticContext] [YamlStaticContext]
[YamlSerializable(typeof(Rule))] [YamlSerializable(typeof(Rule))]
public partial class YamlStaticContext : StaticContext public partial class YamlStaticContextServer : StaticContext
{ {
} }

View File

@@ -1,4 +1,3 @@
using System.Diagnostics.CodeAnalysis;
using VirtualDDNSRouter.Server.Context; using VirtualDDNSRouter.Server.Context;
using VirtualDDNSRouter.Server.Interfaces; using VirtualDDNSRouter.Server.Interfaces;
using VirtualDDNSRouter.Server.Models; using VirtualDDNSRouter.Server.Models;
@@ -19,7 +18,7 @@ public class YamlParser : IYamlParser
var yamlContent = await File.ReadAllTextAsync(_yamlFilePath).ConfigureAwait(false); var yamlContent = await File.ReadAllTextAsync(_yamlFilePath).ConfigureAwait(false);
// Build the deserializer with explicit naming convention // Build the deserializer with explicit naming convention
var deserializer = new StaticDeserializerBuilder(new YamlStaticContext()) var deserializer = new StaticDeserializerBuilder(new YamlStaticContextServer())
.WithNamingConvention(UnderscoredNamingConvention.Instance) // maps api_key -> apiKey .WithNamingConvention(UnderscoredNamingConvention.Instance) // maps api_key -> apiKey
.IgnoreUnmatchedProperties() .IgnoreUnmatchedProperties()
.Build(); .Build();
@@ -27,6 +26,6 @@ public class YamlParser : IYamlParser
// Deserialize into a list of Rule // Deserialize into a list of Rule
var rules = deserializer.Deserialize<List<Rule>>(yamlContent); var rules = deserializer.Deserialize<List<Rule>>(yamlContent);
return rules ?? new List<Rule>(); return rules;
} }
} }