Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add option to run the server on http & https #818

Merged
merged 5 commits into from
Sep 26, 2022
Merged
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
13 changes: 13 additions & 0 deletions examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,19 @@ public static void Run()
var s = WireMockServer.Start();
s.Stop();

var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
{
HostingScheme = HostingScheme.HttpAndHttps,
Port = 12399
});
httpAndHttpsWithPort.Stop();

var httpAndHttpsFree = WireMockServer.Start(new WireMockServerSettings
{
HostingScheme = HostingScheme.HttpAndHttps
});
httpAndHttpsFree.Stop();

string url1 = "http://localhost:9091/";
string url2 = "http://localhost:9092/";
string url3 = "https://localhost:9443/";
Expand Down
Original file line number Diff line number Diff line change
@@ -1,8 +1,16 @@
{
"profiles": {
"WireMock.Net.StandAlone.NETCoreApp": {
"commandName": "Project",
"commandLineArgs": "--Urls http://localhost:9091 --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
"profiles": {
"WireMock.Net.StandAlone.NETCoreApp": {
"commandName": "Project",
"commandLineArgs": "--Urls http://localhost:9091 --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
},
"WireMock.Net.StandAlone.NETCoreAppNoPort": {
"commandName": "Project",
"commandLineArgs": "--CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
},
"WireMock.Net.StandAlone.NETCoreAppWithHostingProtocol": {
"commandName": "Project",
"commandLineArgs": "--HostingProtocol HttpAndHttps --CorsPolicyOptions AllowAll --WireMockLogger WireMockConsoleLogger"
}
}
}
}
15 changes: 15 additions & 0 deletions src/WireMock.Net.Abstractions/Types/HostingScheme.cs
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
using System;

namespace WireMock.Types;

[Flags]
public enum HostingScheme
{
None = 0x0,

Http = 0x1,

Https = 0x2,

HttpAndHttps = Http | Https
}
5 changes: 4 additions & 1 deletion src/WireMock.Net/Owin/HostUrlDetails.cs
Original file line number Diff line number Diff line change
@@ -1,12 +1,15 @@
namespace WireMock.Owin;

/// <summary>
/// https://en.wikipedia.org/wiki/Uniform_Resource_Identifier
/// </summary>
internal struct HostUrlDetails
{
public bool IsHttps { get; set; }

public string Url { get; set; }

public string Protocol { get; set; }
public string Scheme { get; set; }

public string Host { get; set; }

Expand Down
31 changes: 23 additions & 8 deletions src/WireMock.Net/Owin/HostUrlOptions.cs
Original file line number Diff line number Diff line change
@@ -1,34 +1,49 @@
using System.Collections.Generic;
using WireMock.Types;
using WireMock.Util;

namespace WireMock.Owin;

internal class HostUrlOptions
{
private const string LOCALHOST = "localhost";
private const string Localhost = "localhost";

public ICollection<string>? Urls { get; set; }

public int? Port { get; set; }

public bool UseSSL { get; set; }
public int? HttpsPort { get; set; }

public ICollection<HostUrlDetails> GetDetails()
public HostingScheme HostingScheme { get; set; }

public IReadOnlyList<HostUrlDetails> GetDetails()
{
var list = new List<HostUrlDetails>();
if (Urls == null)
{
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
string protocol = UseSSL ? "https" : "http";
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
if (HostingScheme is HostingScheme.Http or HostingScheme.Https)
{
var port = Port > 0 ? Port.Value : FindFreeTcpPort();
var scheme = HostingScheme == HostingScheme.Https ? "https" : "http";
list.Add(new HostUrlDetails { IsHttps = HostingScheme == HostingScheme.Https, Url = $"{scheme}://{Localhost}:{port}", Scheme = scheme, Host = Localhost, Port = port });
}

if (HostingScheme == HostingScheme.HttpAndHttps)
{
var httpPort = Port > 0 ? Port.Value : FindFreeTcpPort();
list.Add(new HostUrlDetails { IsHttps = false, Url = $"http://{Localhost}:{httpPort}", Scheme = "http", Host = Localhost, Port = httpPort });

var httpsPort = FindFreeTcpPort(); // In this scenario, always get a free port for https.
list.Add(new HostUrlDetails { IsHttps = true, Url = $"https://{Localhost}:{httpsPort}", Scheme = "https", Host = Localhost, Port = httpsPort });
}
}
else
{
foreach (string url in Urls)
{
if (PortUtils.TryExtract(url, out bool isHttps, out var protocol, out var host, out int port))
if (PortUtils.TryExtract(url, out var isHttps, out var protocol, out var host, out var port))
{
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Scheme = protocol, Host = host, Port = port });
}
}
}
Expand Down
22 changes: 17 additions & 5 deletions src/WireMock.Net/Server/WireMockServer.cs
Original file line number Diff line number Diff line change
Expand Up @@ -21,6 +21,7 @@
using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
using WireMock.Types;

namespace WireMock.Server;

Expand Down Expand Up @@ -48,7 +49,7 @@ public partial class WireMockServer : IWireMockServer

/// <inheritdoc />
[PublicAPI]
public int Port => Ports?.FirstOrDefault() ?? default(int);
public int Port => Ports?.FirstOrDefault() ?? default;

/// <inheritdoc />
[PublicAPI]
Expand Down Expand Up @@ -269,11 +270,22 @@ protected WireMockServer(WireMockServerSettings settings)
}
else
{
urlOptions = new HostUrlOptions
if (settings.HostingScheme is not null)
{
UseSSL = settings.UseSSL == true,
Port = settings.Port
};
urlOptions = new HostUrlOptions
{
HostingScheme = settings.HostingScheme.Value,
Port = settings.Port
};
}
else
{
urlOptions = new HostUrlOptions
{
HostingScheme = settings.UseSSL == true ? HostingScheme.Https : HostingScheme.Http,
Port = settings.Port
};
}
}

_options.FileSystemHandler = _settings.FileSystemHandler;
Expand Down
20 changes: 20 additions & 0 deletions src/WireMock.Net/Settings/SimpleCommandLineParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -94,6 +94,26 @@ public bool GetBoolSwitchValue(string name)
}, defaultValue);
}

public TEnum? GetEnumValue<TEnum>(string name)
where TEnum : struct
{
return GetValue(name, values =>
{
var value = values.FirstOrDefault();
return Enum.TryParse<TEnum>(value, true, out var enumValue) ? enumValue : (TEnum?)null;
});
}

public TEnum GetEnumValue<TEnum>(string name, TEnum defaultValue)
where TEnum : struct
{
return GetValue(name, values =>
{
var value = values.FirstOrDefault();
return Enum.TryParse<TEnum>(value, true, out var enumValue) ? enumValue : defaultValue;
}, defaultValue);
}

public string GetStringValue(string name, string defaultValue)
{
return GetValue(name, values => values.FirstOrDefault() ?? defaultValue, defaultValue);
Expand Down
9 changes: 8 additions & 1 deletion src/WireMock.Net/Settings/WireMockServerSettings.cs
Original file line number Diff line number Diff line change
Expand Up @@ -9,6 +9,7 @@
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.RegularExpressions;
using WireMock.Types;
#if USE_ASPNETCORE
using Microsoft.Extensions.DependencyInjection;
using WireMock.Types;
Expand All @@ -22,7 +23,7 @@ namespace WireMock.Settings
public class WireMockServerSettings
{
/// <summary>
/// Gets or sets the port.
/// Gets or sets the http port.
/// </summary>
[PublicAPI]
public int? Port { get; set; }
Expand All @@ -34,6 +35,12 @@ public class WireMockServerSettings
[PublicAPI]
public bool? UseSSL { get; set; }

/// <summary>
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
/// </summary>
[PublicAPI]
public HostingScheme? HostingScheme { get; set; }

/// <summary>
/// Gets or sets whether to start admin interface.
/// </summary>
Expand Down
13 changes: 5 additions & 8 deletions src/WireMock.Net/Settings/WireMockServerSettingsParser.cs
Original file line number Diff line number Diff line change
Expand Up @@ -54,14 +54,11 @@ public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out Wire
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme))
};

#if USE_ASPNETCORE
settings.CorsPolicyOptions = parser.GetValue(nameof(WireMockServerSettings.CorsPolicyOptions), values =>
{
var value = string.Join(string.Empty, values);
return Enum.TryParse<CorsPolicyOptions>(value, true, out var corsPolicyOptions) ? corsPolicyOptions : CorsPolicyOptions.None;
});
settings.CorsPolicyOptions = parser.GetEnumValue(nameof(WireMockServerSettings.CorsPolicyOptions), CorsPolicyOptions.None);
#endif

if (logger != null)
Expand All @@ -77,7 +74,7 @@ public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out Wire
{
settings.Port = parser.GetIntValue(nameof(WireMockServerSettings.Port));
}
else
else if (settings.HostingScheme is null)
{
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
}
Expand All @@ -95,15 +92,15 @@ public static bool TryParseArguments(string[] args, [NotNullWhen(true)] out Wire
SaveMapping = parser.GetBoolValue("SaveMapping"),
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
Url = proxyUrl
Url = proxyUrl!
};

string? proxyAddress = parser.GetStringValue("WebProxyAddress");
if (!string.IsNullOrEmpty(proxyAddress))
{
settings.ProxyAndRecordSettings.WebProxySettings = new WebProxySettings
{
Address = proxyAddress,
Address = proxyAddress!,
UserName = parser.GetStringValue("WebProxyUserName"),
Password = parser.GetStringValue("WebProxyPassword")
};
Expand Down