Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
46 changes: 36 additions & 10 deletions src/WireMock.Net.Minimal/Util/PortUtils.cs
Original file line number Diff line number Diff line change
@@ -1,7 +1,6 @@
// Copyright © WireMock.Net

using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net;
using System.Net.Sockets;
using System.Text.RegularExpressions;
Expand All @@ -14,7 +13,7 @@ namespace WireMock.Util;
/// </summary>
internal static class PortUtils
{
private static readonly Regex UrlDetailsRegex = new(@"^((?<scheme>\w+)://)(?<host>[^/]+?):(?<port>\d+)\/?$", RegexOptions.Compiled, RegexConstants.DefaultTimeout);
private static readonly Regex UrlDetailsRegex = new(@"^((?<scheme>\w+)://)(?<host>[^/]+?)(:(?<port>\d+))?\/?$", RegexOptions.Compiled, RegexConstants.DefaultTimeout);

/// <summary>
/// Finds a random, free port to be listened on.
Expand Down Expand Up @@ -90,17 +89,44 @@ public static bool TryExtract(string url, out bool isHttps, out bool isHttp2, [N
host = null;
port = 0;

var match = UrlDetailsRegex.Match(url);
if (match.Success)
var urlDetails = ExtractUrlDetails(url);

if (urlDetails is null || urlDetails.Value.Port < 0)
{
scheme = match.Groups["scheme"].Value;
isHttps = scheme.StartsWith("https", StringComparison.OrdinalIgnoreCase) || scheme.StartsWith("grpcs", StringComparison.OrdinalIgnoreCase) || scheme.StartsWith("wss", StringComparison.OrdinalIgnoreCase);
isHttp2 = scheme.StartsWith("grpc", StringComparison.OrdinalIgnoreCase);
host = match.Groups["host"].Value;
return false;
}

scheme = urlDetails.Value.Scheme;
isHttps = scheme.StartsWith("https", StringComparison.OrdinalIgnoreCase) || scheme.StartsWith("grpcs", StringComparison.OrdinalIgnoreCase) || scheme.StartsWith("wss", StringComparison.OrdinalIgnoreCase);
isHttp2 = scheme.StartsWith("grpc", StringComparison.OrdinalIgnoreCase);
host = urlDetails.Value.Host;
port = urlDetails.Value.Port;

return int.TryParse(match.Groups["port"].Value, out port);
return true;
}

private static (string Scheme, string Host, int Port)? ExtractUrlDetails(string url)
{
var match = UrlDetailsRegex.Match(url);

if (!match.Success)
{
return null;
}

return false;
var scheme = match.Groups["scheme"].Value;
var host = match.Groups["host"].Value;
var port = match.Groups["port"].Success && int.TryParse(match.Groups["port"].Value, out var parsedPort)
? parsedPort
: MapPortFromScheme(scheme);

return (scheme, host, port);
}

private static int MapPortFromScheme(string scheme) => scheme switch
{
"http" => 80,
"https" => 443,
_ => -1,
};
}
44 changes: 40 additions & 4 deletions test/WireMock.Net.Tests/Util/PortUtilsTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,14 +21,14 @@ public void PortUtils_TryExtract_InvalidUrl_Returns_False()
isGrpc.Should().BeFalse();
scheme.Should().BeNull();
host.Should().BeNull();
port.Should().Be(default(int));
port.Should().Be(default);
}

[Fact]
public void PortUtils_TryExtract_UrlIsMissingPort_Returns_False()
public void PortUtils_TryExtract_DefaultPort_UnknownScheme_Returns_False()
{
// Assign
var url = "http://0.0.0.0";
var url = "grpc://0.0.0.0";

// Act
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);
Expand All @@ -39,7 +39,43 @@ public void PortUtils_TryExtract_UrlIsMissingPort_Returns_False()
isGrpc.Should().BeFalse();
scheme.Should().BeNull();
host.Should().BeNull();
port.Should().Be(default(int));
port.Should().Be(default);
}

[Fact]
public void PortUtils_TryExtract_DefaultPort_Http_Returns_True()
{
// Assign
var url = "http://0.0.0.0";

// Act
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);

// Assert
result.Should().BeTrue();
isHttps.Should().BeFalse();
isGrpc.Should().BeFalse();
scheme.Should().Be("http");
host.Should().Be("0.0.0.0");
port.Should().Be(80);
}

[Fact]
public void PortUtils_TryExtract_DefaultPort_Https_Returns_True()
{
// Assign
var url = "https://0.0.0.0";

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you check if you can also add a "real" unit test which starts wiremock at https;//0.0.0.0 or https://localhost with that port?

Like this:
https://github.com/wiremock/WireMock.Net/blob/master/test/WireMock.Net.Tests/WireMockServerTests.cs#L199

(it could be that that test runs locally correct, and maybe in CI-CD fails, maybe, we have to see)


// Act
var result = PortUtils.TryExtract(url, out var isHttps, out var isGrpc, out var scheme, out var host, out var port);

// Assert
result.Should().BeTrue();
isHttps.Should().BeTrue();
isGrpc.Should().BeFalse();
scheme.Should().Be("https");
host.Should().Be("0.0.0.0");
port.Should().Be(443);
}

[Fact]
Expand Down
Loading