Allow numeric routing ports

This commit is contained in:
wwmmzz 2026-05-24 13:30:54 +08:00
parent 807f0aba06
commit 3ec78dd38a
3 changed files with 94 additions and 0 deletions

View file

@ -0,0 +1,48 @@
using AwesomeAssertions;
using ServiceLib.Models.Entities;
using Xunit;
namespace ServiceLib.Tests.Fmt;
public class RoutingRulePortConverterTests
{
[Fact]
public void DeserializeRoutingRules_PortNumber_ShouldBeAccepted()
{
var json = """
[
{
"type": "field",
"outboundTag": "direct",
"port": 53
}
]
""";
var rules = JsonUtils.Deserialize<List<RulesItem>>(json);
rules.Should().NotBeNull();
rules!.Should().HaveCount(1);
rules[0].Port.Should().Be("53");
}
[Fact]
public void DeserializeRoutingRules_PortStringRange_ShouldStillWork()
{
var json = """
[
{
"type": "field",
"outboundTag": "proxy",
"port": "0-65535"
}
]
""";
var rules = JsonUtils.Deserialize<List<RulesItem>>(json);
rules.Should().NotBeNull();
rules!.Should().HaveCount(1);
rules[0].Port.Should().Be("0-65535");
}
}

View file

@ -0,0 +1,45 @@
namespace ServiceLib.Common;
/// <summary>
/// Accepts either a JSON string or number and stores the value as a string.
/// This keeps existing routing rule storage intact while allowing numeric clipboard input.
/// </summary>
public sealed class JsonStringOrNumberConverter : JsonConverter<string?>
{
public override string? Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
{
return reader.TokenType switch
{
JsonTokenType.String => reader.GetString(),
JsonTokenType.Number => ReadNumber(reader),
JsonTokenType.Null => null,
_ => throw new JsonException($"Unexpected token {reader.TokenType} for string-or-number value.")
};
}
public override void Write(Utf8JsonWriter writer, string? value, JsonSerializerOptions options)
{
if (value == null)
{
writer.WriteNullValue();
return;
}
writer.WriteStringValue(value);
}
private static string ReadNumber(Utf8JsonReader reader)
{
if (reader.TryGetInt64(out var longValue))
{
return longValue.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
if (reader.TryGetDouble(out var doubleValue))
{
return doubleValue.ToString(System.Globalization.CultureInfo.InvariantCulture);
}
return reader.GetDecimal().ToString(System.Globalization.CultureInfo.InvariantCulture);
}
}

View file

@ -5,6 +5,7 @@ public class RulesItem
{
public string Id { get; set; }
public string? Type { get; set; }
[JsonConverter(typeof(JsonStringOrNumberConverter))]
public string? Port { get; set; }
public string? Network { get; set; }
public List<string>? InboundTag { get; set; }