Merge pull request #6392 from Bond-009/tests9

ApiServiceCollectionExtensions.AddProxyAddresses: Add more tests
This commit is contained in:
Claus Vium 2021-08-15 19:56:08 +02:00 committed by GitHub
commit d3f291f159
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
2 changed files with 93 additions and 51 deletions

View File

@ -4,7 +4,6 @@ using System.Linq;
using System.Net; using System.Net;
using System.Net.Sockets; using System.Net.Sockets;
using System.Text.RegularExpressions; using System.Text.RegularExpressions;
using System.Threading.Tasks;
namespace MediaBrowser.Common.Net namespace MediaBrowser.Common.Net
{ {
@ -196,7 +195,7 @@ namespace MediaBrowser.Common.Net
return res; return res;
} }
throw new InvalidCastException("Host does not contain a valid value. {host}"); throw new InvalidCastException($"Host does not contain a valid value. {host}");
} }
/// <summary> /// <summary>
@ -221,7 +220,7 @@ namespace MediaBrowser.Common.Net
return res; return res;
} }
throw new InvalidCastException("Host does not contain a valid value. {host}"); throw new InvalidCastException($"Host does not contain a valid value. {host}");
} }
/// <summary> /// <summary>
@ -349,7 +348,7 @@ namespace MediaBrowser.Common.Net
} }
} }
output = output[0..^1]; output = output[..^1];
if (moreThanOne) if (moreThanOne)
{ {
@ -400,7 +399,7 @@ namespace MediaBrowser.Common.Net
if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout))) if ((_addresses.Length == 0 && !Resolved) || (DateTime.UtcNow > _lastResolved.Value.AddMinutes(Timeout)))
{ {
_lastResolved = DateTime.UtcNow; _lastResolved = DateTime.UtcNow;
ResolveHostInternal().GetAwaiter().GetResult(); ResolveHostInternal();
Resolved = true; Resolved = true;
} }
@ -410,30 +409,31 @@ namespace MediaBrowser.Common.Net
/// <summary> /// <summary>
/// Task that looks up a Host name and returns its IP addresses. /// Task that looks up a Host name and returns its IP addresses.
/// </summary> /// </summary>
/// <returns>A <see cref="Task"/> representing the asynchronous operation.</returns> private void ResolveHostInternal()
private async Task ResolveHostInternal()
{ {
if (!string.IsNullOrEmpty(HostName)) var hostName = HostName;
if (string.IsNullOrEmpty(hostName))
{ {
// Resolves the host name - so save a DNS lookup. return;
if (string.Equals(HostName, "localhost", StringComparison.OrdinalIgnoreCase)) }
{
_addresses = new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback };
return;
}
if (Uri.CheckHostName(HostName).Equals(UriHostNameType.Dns)) // Resolves the host name - so save a DNS lookup.
if (string.Equals(hostName, "localhost", StringComparison.OrdinalIgnoreCase))
{
_addresses = new IPAddress[] { IPAddress.Loopback, IPAddress.IPv6Loopback };
return;
}
if (Uri.CheckHostName(hostName) == UriHostNameType.Dns)
{
try
{ {
try _addresses = Dns.GetHostEntry(hostName).AddressList;
{ }
IPHostEntry ip = await Dns.GetHostEntryAsync(HostName).ConfigureAwait(false); catch (SocketException ex)
_addresses = ip.AddressList; {
} // Log and then ignore socket errors, as the result value will just be an empty array.
catch (SocketException ex) Debug.WriteLine("GetHostAddresses failed with {Message}.", ex.Message);
{
// Log and then ignore socket errors, as the result value will just be an empty array.
Debug.WriteLine("GetHostEntryAsync failed with {Message}.", ex.Message);
}
} }
} }
} }

View File

@ -1,10 +1,15 @@
using System;
using System.Collections.Generic;
using System.Globalization; using System.Globalization;
using System.Linq;
using System.Net;
using System.Text; using System.Text;
using Jellyfin.Networking.Configuration; using Jellyfin.Networking.Configuration;
using Jellyfin.Networking.Manager; using Jellyfin.Networking.Manager;
using Jellyfin.Server.Extensions; using Jellyfin.Server.Extensions;
using MediaBrowser.Common.Configuration; using MediaBrowser.Common.Configuration;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.HttpOverrides;
using Microsoft.Extensions.Logging.Abstractions; using Microsoft.Extensions.Logging.Abstractions;
using Moq; using Moq;
using Xunit; using Xunit;
@ -13,20 +18,63 @@ namespace Jellyfin.Server.Tests
{ {
public class ParseNetworkTests public class ParseNetworkTests
{ {
/// <summary> public static TheoryData<bool, bool, string[], IPAddress[], IPNetwork[]> TestNetworks_TestData()
/// Order of the result has always got to be hosts, then networks. {
/// </summary> var data = new TheoryData<bool, bool, string[], IPAddress[], IPNetwork[]>();
/// <param name="ip4">IP4 enabled.</param> data.Add(
/// <param name="ip6">IP6 enabled.</param> true,
/// <param name="hostList">List to parse.</param> true,
/// <param name="match">What it should match.</param> new string[] { "192.168.t", "127.0.0.1", "1234.1232.12.1234" },
new IPAddress[] { IPAddress.Loopback.MapToIPv6() },
Array.Empty<IPNetwork>());
data.Add(
true,
false,
new string[] { "192.168.x", "127.0.0.1", "1234.1232.12.1234" },
new IPAddress[] { IPAddress.Loopback },
Array.Empty<IPNetwork>());
data.Add(
true,
true,
new string[] { "::1" },
Array.Empty<IPAddress>(),
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
data.Add(
false,
false,
new string[] { "localhost" },
Array.Empty<IPAddress>(),
Array.Empty<IPNetwork>());
data.Add(
true,
false,
new string[] { "localhost" },
new IPAddress[] { IPAddress.Loopback },
Array.Empty<IPNetwork>());
data.Add(
false,
true,
new string[] { "localhost" },
Array.Empty<IPAddress>(),
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
data.Add(
true,
true,
new string[] { "localhost" },
new IPAddress[] { IPAddress.Loopback.MapToIPv6() },
new IPNetwork[] { new IPNetwork(IPAddress.IPv6Loopback, 128) });
return data;
}
[Theory] [Theory]
// [InlineData(true, true, "192.168.0.0/16,www.yahoo.co.uk", "::ffff:212.82.100.150,::ffff:192.168.0.0/16")] <- fails on Max. www.yahoo.co.uk resolves to a different ip address. [MemberData(nameof(TestNetworks_TestData))]
// [InlineData(true, false, "192.168.0.0/16,www.yahoo.co.uk", "212.82.100.150,192.168.0.0/16")] public void TestNetworks(bool ip4, bool ip6, string[] hostList, IPAddress[] knownProxies, IPNetwork[] knownNetworks)
[InlineData(true, true, "192.168.t,127.0.0.1,1234.1232.12.1234", "::ffff:127.0.0.1")]
[InlineData(true, false, "192.168.x,127.0.0.1,1234.1232.12.1234", "127.0.0.1")]
[InlineData(true, true, "::1", "::1/128")]
public void TestNetworks(bool ip4, bool ip6, string hostList, string match)
{ {
using var nm = CreateNetworkManager(); using var nm = CreateNetworkManager();
@ -36,31 +84,25 @@ namespace Jellyfin.Server.Tests
EnableIPV6 = ip6 EnableIPV6 = ip6
}; };
var result = match + ",";
ForwardedHeadersOptions options = new ForwardedHeadersOptions(); ForwardedHeadersOptions options = new ForwardedHeadersOptions();
// Need this here as ::1 and 127.0.0.1 are in them by default. // Need this here as ::1 and 127.0.0.1 are in them by default.
options.KnownProxies.Clear(); options.KnownProxies.Clear();
options.KnownNetworks.Clear(); options.KnownNetworks.Clear();
ApiServiceCollectionExtensions.AddProxyAddresses(settings, hostList.Split(','), options); ApiServiceCollectionExtensions.AddProxyAddresses(settings, hostList, options);
var sb = new StringBuilder(); Assert.Equal(knownProxies.Length, options.KnownProxies.Count);
foreach (var item in options.KnownProxies) foreach (var item in knownProxies)
{ {
sb.Append(item) Assert.True(options.KnownProxies.Contains(item));
.Append(',');
} }
foreach (var item in options.KnownNetworks) Assert.Equal(knownNetworks.Length, options.KnownNetworks.Count);
foreach (var item in knownNetworks)
{ {
sb.Append(item.Prefix) Assert.NotNull(options.KnownNetworks.FirstOrDefault(x => x.Prefix.Equals(item.Prefix) && x.PrefixLength == item.PrefixLength));
.Append('/')
.Append(item.PrefixLength.ToString(CultureInfo.InvariantCulture))
.Append(',');
} }
Assert.Equal(sb.ToString(), result);
} }
private static IConfigurationManager GetMockConfig(NetworkConfiguration conf) private static IConfigurationManager GetMockConfig(NetworkConfiguration conf)