diff --git a/src/Nacos.AspNetCore/UriTool.cs b/src/Nacos.AspNetCore/UriTool.cs index b23e8969..b132ad2f 100644 --- a/src/Nacos.AspNetCore/UriTool.cs +++ b/src/Nacos.AspNetCore/UriTool.cs @@ -1,62 +1,64 @@ -[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Nacos.AspNetCore.Tests")] - -namespace Nacos.AspNetCore -{ - using Microsoft.AspNetCore.Hosting.Server.Features; - using Microsoft.AspNetCore.Http.Features; - using System; - using System.Collections.Generic; - using System.Linq; - using System.Net; - using System.Net.NetworkInformation; - using System.Net.Sockets; - - internal static class UriTool - { - public static IEnumerable GetUri(IFeatureCollection features, string ip, int port, string preferredNetworks) - { - var splitChars = new char[] { ',', ';' }; - var appPort = port <= 0 ? 80 : port; - - // 1. config - if (!string.IsNullOrWhiteSpace(ip)) - { - // it seems that nacos don't return the scheme - // so here use http only. - return new List { new Uri($"http://{ip}:{appPort}") }; - } - - // 1.1. Ip is null && Port has value - if (string.IsNullOrWhiteSpace(ip) && appPort != 80) - { - return new List { new Uri($"http://{GetCurrentIp(preferredNetworks)}:{appPort}") }; - } - - var address = string.Empty; - - // 2. IServerAddressesFeature - if (features != null) - { - var addresses = features.Get(); - var addressCollection = addresses?.Addresses; - - if (addressCollection != null && addressCollection.Any()) - { - var uris = new List(); - foreach (var item in addressCollection) - { - var url = ReplaceAddress(item, preferredNetworks); - uris.Add(new Uri(url)); - } - - return uris; - } - } - - // 3. ASPNETCORE_URLS - address = Environment.GetEnvironmentVariable("ASPNETCORE_URLS"); - if (!string.IsNullOrWhiteSpace(address)) - { +using System.Text.RegularExpressions; + +[assembly: System.Runtime.CompilerServices.InternalsVisibleTo("Nacos.AspNetCore.Tests")] + +namespace Nacos.AspNetCore +{ + using Microsoft.AspNetCore.Hosting.Server.Features; + using Microsoft.AspNetCore.Http.Features; + using System; + using System.Collections.Generic; + using System.Linq; + using System.Net; + using System.Net.NetworkInformation; + using System.Net.Sockets; + + internal static class UriTool + { + public static IEnumerable GetUri(IFeatureCollection features, string ip, int port, string preferredNetworks) + { + var splitChars = new char[] { ',', ';' }; + var appPort = port <= 0 ? 80 : port; + + // 1. config + if (!string.IsNullOrWhiteSpace(ip)) + { + // it seems that nacos don't return the scheme + // so here use http only. + return new List { new Uri($"http://{ip}:{appPort}") }; + } + + // 1.1. Ip is null && Port has value + if (string.IsNullOrWhiteSpace(ip) && appPort != 80) + { + return new List { new Uri($"http://{GetCurrentIp(preferredNetworks)}:{appPort}") }; + } + + var address = string.Empty; + + // 2. IServerAddressesFeature + if (features != null) + { + var addresses = features.Get(); + var addressCollection = addresses?.Addresses; + + if (addressCollection != null && addressCollection.Any()) + { + var uris = new List(); + foreach (var item in addressCollection) + { + var url = ReplaceAddress(item, preferredNetworks); + uris.Add(new Uri(url)); + } + + return uris; + } + } + + // 3. ASPNETCORE_URLS + address = Environment.GetEnvironmentVariable("ASPNETCORE_URLS"); + if (!string.IsNullOrWhiteSpace(address)) + { var url = ReplaceAddress(address, preferredNetworks); var uris = url.Split(splitChars).Select(x => new Uri(x)); @@ -67,101 +69,105 @@ public static IEnumerable GetUri(IFeatureCollection features, string ip, in { throw new Nacos.V2.Exceptions.NacosException("Invalid ip address from ASPNETCORE_URLS"); } - } - - return uris; - } - - // 4. --urls - var cmdArgs = Environment.GetCommandLineArgs(); - if (cmdArgs != null && cmdArgs.Any()) - { - var cmd = cmdArgs.FirstOrDefault(x => x.StartsWith("--urls", StringComparison.OrdinalIgnoreCase)); - - if (!string.IsNullOrWhiteSpace(cmd)) - { - address = cmd.Split('=')[1]; - - var url = ReplaceAddress(address, preferredNetworks); - - var uris = url.Split(splitChars).Select(x => new Uri(x)); - + } + + return uris; + } + + // 4. --urls + var cmdArgs = Environment.GetCommandLineArgs(); + if (cmdArgs != null && cmdArgs.Any()) + { + var cmd = cmdArgs.FirstOrDefault(x => x.StartsWith("--urls", StringComparison.OrdinalIgnoreCase)); + + if (!string.IsNullOrWhiteSpace(cmd)) + { + address = cmd.Split('=')[1]; + + var url = ReplaceAddress(address, preferredNetworks); + + var uris = url.Split(splitChars).Select(x => new Uri(x)); + foreach (var item in uris) { if (!IPAddress.TryParse(item.Host, out _)) { throw new Nacos.V2.Exceptions.NacosException("Invalid ip address from --urls"); } - } - - return uris; - } - } - - // 5. current ip address third - address = $"http://{GetCurrentIp(preferredNetworks)}:{appPort}"; - - return new List { new Uri(address) }; - } - - private static string ReplaceAddress(string address, string preferredNetworks) - { - var ip = GetCurrentIp(preferredNetworks); - - if (address.Contains("*")) - { - address = address.Replace("*", ip); - } - else if (address.Contains("+")) - { - address = address.Replace("+", ip); - } - else if (address.Contains("localhost", StringComparison.OrdinalIgnoreCase)) - { - address = address.Replace("localhost", ip, StringComparison.OrdinalIgnoreCase); - } - else if (address.Contains("0.0.0.0", StringComparison.OrdinalIgnoreCase)) - { - address = address.Replace("0.0.0.0", ip, StringComparison.OrdinalIgnoreCase); - } - - return address; - } - - private static string GetCurrentIp(string preferredNetworks) - { - var instanceIp = "127.0.0.1"; - - try - { - // 获取可用网卡 - var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up); - - // 获取所有可用网卡IP信息 - var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses); - - foreach (var ipadd in ipCollection) - { - if (!IPAddress.IsLoopback(ipadd.Address) && ipadd.Address.AddressFamily == AddressFamily.InterNetwork) - { - if (string.IsNullOrEmpty(preferredNetworks)) - { - instanceIp = ipadd.Address.ToString(); - break; - } - - if (!ipadd.Address.ToString().StartsWith(preferredNetworks)) continue; - instanceIp = ipadd.Address.ToString(); - break; - } - } - } - catch - { - // ignored - } - - return instanceIp; - } - } -} + } + + return uris; + } + } + + // 5. current ip address third + address = $"http://{GetCurrentIp(preferredNetworks)}:{appPort}"; + + return new List { new Uri(address) }; + } + + private static string ReplaceAddress(string address, string preferredNetworks) + { + var ip = GetCurrentIp(preferredNetworks); + + if (address.Contains("*")) + { + address = address.Replace("*", ip); + } + else if (address.Contains("+")) + { + address = address.Replace("+", ip); + } + else if (address.Contains("localhost", StringComparison.OrdinalIgnoreCase)) + { + address = address.Replace("localhost", ip, StringComparison.OrdinalIgnoreCase); + } + else if (address.Contains("0.0.0.0", StringComparison.OrdinalIgnoreCase)) + { + address = address.Replace("0.0.0.0", ip, StringComparison.OrdinalIgnoreCase); + } + + return address; + } + + private static string GetCurrentIp(string preferredNetworks) + { + var instanceIp = "127.0.0.1"; + + try + { + // 获取可用网卡 + var nics = NetworkInterface.GetAllNetworkInterfaces()?.Where(network => network.OperationalStatus == OperationalStatus.Up); + + // 获取所有可用网卡IP信息 + var ipCollection = nics?.Select(x => x.GetIPProperties())?.SelectMany(x => x.UnicastAddresses); + + var preferredNetworksArr = preferredNetworks.Split(","); + foreach (var ipadd in ipCollection) + { + if (!IPAddress.IsLoopback(ipadd.Address) && + ipadd.Address.AddressFamily == AddressFamily.InterNetwork) + { + if (string.IsNullOrEmpty(preferredNetworks)) + { + instanceIp = ipadd.Address.ToString(); + break; + } + + if (!preferredNetworksArr.Any(preferredNetwork => + ipadd.Address.ToString().StartsWith(preferredNetwork) + || Regex.IsMatch(ipadd.Address.ToString(), preferredNetwork))) continue; + instanceIp = ipadd.Address.ToString(); + break; + } + } + } + catch + { + // ignored + } + + return instanceIp; + } + } +} diff --git a/tests/Nacos.AspNetCore.Tests/UriToolTests.cs b/tests/Nacos.AspNetCore.Tests/UriToolTests.cs index fa13cac3..ed4d4642 100644 --- a/tests/Nacos.AspNetCore.Tests/UriToolTests.cs +++ b/tests/Nacos.AspNetCore.Tests/UriToolTests.cs @@ -1,61 +1,71 @@ -namespace Nacos.AspNetCore.Tests -{ - using Microsoft.AspNetCore.Hosting.Server.Features; - using Microsoft.AspNetCore.Http.Features; - using System.Linq; - using Xunit; - - [Trait("Category", "all")] - public class UriToolTests - { - [Fact] - public void GetUri_Should_Return_Single_Uri() - { - IFeatureCollection fc = new FeatureCollection(); - IServerAddressesFeature saf = new ServerAddressesFeature(); - saf.Addresses.Add("http://*:8080"); - fc.Set(saf); - - var uris = UriTool.GetUri(fc, "", 0, ""); - - Assert.Single(uris); - } - - [Fact] - public void GetUri_Should_Return_Multi_Uris() - { - IFeatureCollection fc = new FeatureCollection(); - IServerAddressesFeature saf = new ServerAddressesFeature(); - saf.Addresses.Add("http://*:8080"); - saf.Addresses.Add("http://*:8081"); - fc.Set(saf); - - var uris = UriTool.GetUri(fc, "", 0, ""); - - Assert.Equal(2, uris.Count()); - } - - [Theory] - [InlineData("http://+80")] - [InlineData("http://*80")] +namespace Nacos.AspNetCore.Tests +{ + using Microsoft.AspNetCore.Hosting.Server.Features; + using Microsoft.AspNetCore.Http.Features; + using System.Linq; + using Xunit; + + [Trait("Category", "all")] + public class UriToolTests + { + [Fact] + public void GetUri_Should_Return_Single_Uri() + { + IFeatureCollection fc = new FeatureCollection(); + IServerAddressesFeature saf = new ServerAddressesFeature(); + saf.Addresses.Add("http://*:8080"); + fc.Set(saf); + + var uris = UriTool.GetUri(fc, "", 0, ""); + + Assert.Single(uris); + } + + [Fact] + public void GetUri_Should_Return_Multi_Uris() + { + IFeatureCollection fc = new FeatureCollection(); + IServerAddressesFeature saf = new ServerAddressesFeature(); + saf.Addresses.Add("http://*:8080"); + saf.Addresses.Add("http://*:8081"); + fc.Set(saf); + + var uris = UriTool.GetUri(fc, "", 0, ""); + + Assert.Equal(2, uris.Count()); + } + + [Theory] + [InlineData("http://+80")] + [InlineData("http://*80")] public void GetUrl_With_ASPNETCORE_URLS_Should_ThrowExceptions(string url) - { - System.Environment.SetEnvironmentVariable("ASPNETCORE_URLS", url); - var ex = Assert.Throws(() => UriTool.GetUri(null, "", 0, "")); - Assert.Equal("Invalid ip address from ASPNETCORE_URLS", ex.ErrorMsg); - } - - [Theory] - [InlineData("http://+:80")] - [InlineData("http://*:80")] + { + System.Environment.SetEnvironmentVariable("ASPNETCORE_URLS", url); + var ex = Assert.Throws(() => UriTool.GetUri(null, "", 0, "")); + Assert.Equal("Invalid ip address from ASPNETCORE_URLS", ex.ErrorMsg); + } + + [Theory] + [InlineData("http://+:80")] + [InlineData("http://*:80")] public void GetUrl_With_ASPNETCORE_URLS_Should_Succeed(string url) - { - System.Environment.SetEnvironmentVariable("ASPNETCORE_URLS", url); - var uris = UriTool.GetUri(null, "", 0, ""); - Assert.Single(uris); - var uri = uris.First(); - Assert.True(System.Net.IPAddress.TryParse(uri.Host, out _)); - Assert.Equal(80, uri.Port); - } - } -} + { + System.Environment.SetEnvironmentVariable("ASPNETCORE_URLS", url); + var uris = UriTool.GetUri(null, "", 0, ""); + Assert.Single(uris); + var uri = uris.First(); + Assert.True(System.Net.IPAddress.TryParse(uri.Host, out _)); + Assert.Equal(80, uri.Port); + } + + [Fact] + public void GetUri_With_Multiple_And_Regex_PreferredNetworks_Should_Succeed() + { + var preferredNetworks = @"192.168.,10.0.,172\.\d+\.\d+\.\d+"; + var uris = UriTool.GetUri(null, "", 0, preferredNetworks); + Assert.Single(uris); + var uri = uris.First(); + Assert.Matches(@"(192\.168\.\d+\.\d+|10\.0\.\d+\.\d+|172\.\d+\.\d+|127.0.0.1)", uri.Host); + } + } +}