diff --git a/src/WireMock.Net.Abstractions/IRequestMessage.cs b/src/WireMock.Net.Abstractions/IRequestMessage.cs
index ca80ec89e..d7a0d301d 100644
--- a/src/WireMock.Net.Abstractions/IRequestMessage.cs
+++ b/src/WireMock.Net.Abstractions/IRequestMessage.cs
@@ -63,12 +63,12 @@ public interface IRequestMessage
///
/// Gets the headers.
///
- IDictionary>? Headers { get; }
+ IDictionary> Headers { get; }
///
/// Gets the cookies.
///
- IDictionary? Cookies { get; }
+ IDictionary Cookies { get; }
///
/// Gets the query.
diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETCore.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETCore.cs
index 3c505e161..1a5c85e98 100644
--- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETCore.cs
+++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.NETCore.cs
@@ -3,45 +3,44 @@
using Microsoft.Extensions.DependencyInjection;
using WireMock.Types;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal partial class AspNetCoreSelfHost
{
- internal partial class AspNetCoreSelfHost
+ public void AddCors(IServiceCollection services)
{
- public void AddCors(IServiceCollection services)
+ if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
{
- if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
- {
- /* https://stackoverflow.com/questions/31942037/how-to-enable-cors-in-asp-net-core */
- /* Enable Cors */
- services.AddCors(corsOptions => corsOptions
- .AddPolicy(CorsPolicyName,
- corsPolicyBuilder =>
+ /* https://stackoverflow.com/questions/31942037/how-to-enable-cors-in-asp-net-core */
+ /* Enable Cors */
+ services.AddCors(corsOptions => corsOptions
+ .AddPolicy(CorsPolicyName,
+ corsPolicyBuilder =>
+ {
+ if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyHeader))
{
- if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyHeader))
- {
- corsPolicyBuilder.AllowAnyHeader();
- }
+ corsPolicyBuilder.AllowAnyHeader();
+ }
- if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyMethod))
- {
- corsPolicyBuilder.AllowAnyMethod();
- }
+ if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyMethod))
+ {
+ corsPolicyBuilder.AllowAnyMethod();
+ }
- if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyOrigin))
- {
- corsPolicyBuilder.AllowAnyOrigin();
- }
- }));
- }
+ if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyOrigin))
+ {
+ corsPolicyBuilder.AllowAnyOrigin();
+ }
+ }));
}
+ }
- public void UseCors(IApplicationBuilder appBuilder)
+ public void UseCors(IApplicationBuilder appBuilder)
+ {
+ if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
{
- if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
- {
- /* Use Cors */
- appBuilder.UseCors(CorsPolicyName);
- }
+ /* Use Cors */
+ appBuilder.UseCors(CorsPolicyName);
}
}
}
diff --git a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
index 097a21592..74d860888 100644
--- a/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
+++ b/src/WireMock.Net/Owin/AspNetCoreSelfHost.cs
@@ -36,10 +36,10 @@ internal partial class AspNetCoreSelfHost : IOwinSelfHost
public Exception RunningException => _runningException;
- public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions wireMockMiddlewareOptions, [NotNull] HostUrlOptions urlOptions)
+ public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
{
- Guard.NotNull(wireMockMiddlewareOptions, nameof(wireMockMiddlewareOptions));
- Guard.NotNull(urlOptions, nameof(urlOptions));
+ Guard.NotNull(wireMockMiddlewareOptions);
+ Guard.NotNull(urlOptions);
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
@@ -119,7 +119,7 @@ private Task RunHost(CancellationToken token)
{
Urls.Add(address.Replace("0.0.0.0", "localhost").Replace("[::]", "localhost"));
- PortUtils.TryExtract(address, out bool isHttps, out string protocol, out string host, out int port);
+ PortUtils.TryExtract(address, out _, out _, out _, out int port);
Ports.Add(port);
}
diff --git a/src/WireMock.Net/Owin/HostUrlDetails.cs b/src/WireMock.Net/Owin/HostUrlDetails.cs
index 6bd8826ca..e988ae433 100644
--- a/src/WireMock.Net/Owin/HostUrlDetails.cs
+++ b/src/WireMock.Net/Owin/HostUrlDetails.cs
@@ -1,15 +1,14 @@
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal struct HostUrlDetails
{
- internal class HostUrlDetails
- {
- public bool IsHttps { get; set; }
+ public bool IsHttps { get; set; }
- public string Url { get; set; }
+ public string Url { get; set; }
- public string Protocol { get; set; }
+ public string Protocol { get; set; }
- public string Host { get; set; }
+ public string Host { get; set; }
- public int Port { get; set; }
- }
+ public int Port { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/HostUrlOptions.cs b/src/WireMock.Net/Owin/HostUrlOptions.cs
index dd94ce331..77dcf1e0d 100644
--- a/src/WireMock.Net/Owin/HostUrlOptions.cs
+++ b/src/WireMock.Net/Owin/HostUrlOptions.cs
@@ -1,46 +1,47 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using WireMock.Util;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal class HostUrlOptions
{
- internal class HostUrlOptions
- {
- private const string LOCALHOST = "localhost";
+ private const string LOCALHOST = "localhost";
- public ICollection Urls { get; set; }
+ public ICollection? Urls { get; set; }
- public int? Port { get; set; }
+ public int? Port { get; set; }
- public bool UseSSL { get; set; }
+ public bool UseSSL { get; set; }
- public ICollection GetDetails()
+ public ICollection GetDetails()
+ {
+ var list = new List();
+ if (Urls == null)
{
- var list = new List();
- 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 });
- }
- else
+ 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 });
+ }
+ else
+ {
+ foreach (string url in Urls)
{
- foreach (string url in Urls)
+ if (PortUtils.TryExtract(url, out bool isHttps, out var protocol, out var host, out int port))
{
- PortUtils.TryExtract(url, out bool isHttps, out string protocol, out string host, out int port);
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
}
}
-
- return list;
}
- private int FindFreeTcpPort()
- {
+ return list;
+ }
+
+ private static int FindFreeTcpPort()
+ {
#if USE_ASPNETCORE || NETSTANDARD2_0 || NETSTANDARD2_1
- return 0;
+ return 0;
#else
- return PortUtils.FindFreeTcpPort();
+ return PortUtils.FindFreeTcpPort();
#endif
- }
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/IMappingMatcher.cs b/src/WireMock.Net/Owin/IMappingMatcher.cs
index a1e54e7b7..ffcecd749 100644
--- a/src/WireMock.Net/Owin/IMappingMatcher.cs
+++ b/src/WireMock.Net/Owin/IMappingMatcher.cs
@@ -1,7 +1,6 @@
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal interface IMappingMatcher
{
- internal interface IMappingMatcher
- {
- (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request);
- }
+ (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request);
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/IOwinSelfHost.cs b/src/WireMock.Net/Owin/IOwinSelfHost.cs
index 81828ef63..781445fcb 100644
--- a/src/WireMock.Net/Owin/IOwinSelfHost.cs
+++ b/src/WireMock.Net/Owin/IOwinSelfHost.cs
@@ -1,36 +1,35 @@
-using System.Collections.Generic;
+using System.Collections.Generic;
using System.Threading.Tasks;
using System;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+interface IOwinSelfHost
{
- interface IOwinSelfHost
- {
- ///
- /// Gets a value indicating whether this server is started.
- ///
- ///
- /// true if this server is started; otherwise, false.
- ///
- bool IsStarted { get; }
+ ///
+ /// Gets a value indicating whether this server is started.
+ ///
+ ///
+ /// true if this server is started; otherwise, false.
+ ///
+ bool IsStarted { get; }
- ///
- /// Gets the urls.
- ///
- List Urls { get; }
+ ///
+ /// Gets the urls.
+ ///
+ List Urls { get; }
- ///
- /// Gets the ports.
- ///
- List Ports { get; }
+ ///
+ /// Gets the ports.
+ ///
+ List Ports { get; }
- ///
- /// The exception occurred when the host is running
- ///
- Exception RunningException { get; }
+ ///
+ /// The exception occurred when the host is running.
+ ///
+ Exception? RunningException { get; }
- Task StartAsync();
+ Task StartAsync();
- Task StopAsync();
- }
+ Task StopAsync();
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs
index dbdcafde7..29afe592e 100644
--- a/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs
+++ b/src/WireMock.Net/Owin/Mappers/OwinRequestMapper.cs
@@ -27,7 +27,7 @@ public async Task MapAsync(IRequest request, IWireMockMiddleware
string method = request.Method;
- Dictionary? headers = null;
+ var headers = new Dictionary();
IEnumerable? contentEncodingHeader = null;
if (request.Headers.Any())
{
@@ -43,7 +43,7 @@ public async Task MapAsync(IRequest request, IWireMockMiddleware
}
}
- IDictionary? cookies = null;
+ var cookies = new Dictionary();
if (request.Cookies.Any())
{
cookies = new Dictionary();
@@ -75,13 +75,24 @@ private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest re
{
#if !USE_ASPNETCORE
var urlDetails = UrlUtils.Parse(request.Uri, request.PathBase);
- string clientIP = request.RemoteIpAddress;
+ var clientIP = request.RemoteIpAddress;
#else
var urlDetails = UrlUtils.Parse(new Uri(request.GetEncodedUrl()), request.PathBase);
+
var connection = request.HttpContext.Connection;
- string clientIP = connection.RemoteIpAddress.IsIPv4MappedToIPv6
- ? connection.RemoteIpAddress.MapToIPv4().ToString()
- : connection.RemoteIpAddress.ToString();
+ string clientIP;
+ if (connection.RemoteIpAddress is null)
+ {
+ clientIP = string.Empty;
+ }
+ else if (connection.RemoteIpAddress.IsIPv4MappedToIPv6)
+ {
+ clientIP = connection.RemoteIpAddress.MapToIPv4().ToString();
+ }
+ else
+ {
+ clientIP = connection.RemoteIpAddress.ToString();
+ }
#endif
return (urlDetails, clientIP);
}
diff --git a/src/WireMock.Net/Owin/MappingMatcher.cs b/src/WireMock.Net/Owin/MappingMatcher.cs
index de78afc63..704af303f 100644
--- a/src/WireMock.Net/Owin/MappingMatcher.cs
+++ b/src/WireMock.Net/Owin/MappingMatcher.cs
@@ -4,72 +4,71 @@
using WireMock.Extensions;
using Stef.Validation;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal class MappingMatcher : IMappingMatcher
{
- internal class MappingMatcher : IMappingMatcher
+ private readonly IWireMockMiddlewareOptions _options;
+
+ public MappingMatcher(IWireMockMiddlewareOptions options)
{
- private readonly IWireMockMiddlewareOptions _options;
+ Guard.NotNull(options, nameof(options));
- public MappingMatcher(IWireMockMiddlewareOptions options)
- {
- Guard.NotNull(options, nameof(options));
+ _options = options;
+ }
- _options = options;
- }
+ public (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request)
+ {
+ var possibleMappings = new List();
- public (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request)
+ foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
{
- var mappings = new List();
-
- foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
+ try
{
- try
- {
- var nextState = GetNextState(mapping);
+ var nextState = GetNextState(mapping);
- mappings.Add(new MappingMatcherResult
- {
- Mapping = mapping,
- RequestMatchResult = mapping.GetRequestMatchResult(request, nextState)
- });
- }
- catch (Exception ex)
+ possibleMappings.Add(new MappingMatcherResult
{
- _options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}");
- }
+ Mapping = mapping,
+ RequestMatchResult = mapping.GetRequestMatchResult(request, nextState)
+ });
}
-
- var partialMappings = mappings
- .Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
- .OrderBy(m => m.RequestMatchResult)
- .ThenBy(m => m.Mapping.Priority)
- .ToList();
- var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
-
- if (_options.AllowPartialMapping == true)
+ catch (Exception ex)
{
- return (partialMatch, partialMatch);
+ _options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}");
}
+ }
- var match = mappings
- .Where(m => m.RequestMatchResult.IsPerfectMatch)
- .OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult)
- .FirstOrDefault();
+ var partialMappings = possibleMappings
+ .Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
+ .OrderBy(m => m.RequestMatchResult)
+ .ThenBy(m => m.Mapping.Priority)
+ .ToList();
+ var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
- return (match, partialMatch);
+ if (_options.AllowPartialMapping == true)
+ {
+ return (partialMatch, partialMatch);
}
- private string? GetNextState(IMapping mapping)
- {
- // If the mapping does not have a scenario or _options.Scenarios does not contain this scenario from the mapping,
- // just return null to indicate that there is no next state.
- if (mapping.Scenario == null || !_options.Scenarios.ContainsKey(mapping.Scenario))
- {
- return null;
- }
+ var match = possibleMappings
+ .Where(m => m.RequestMatchResult.IsPerfectMatch)
+ .OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult)
+ .FirstOrDefault();
- // Else just return the next state
- return _options.Scenarios[mapping.Scenario].NextState;
+ return (match, partialMatch);
+ }
+
+ private string? GetNextState(IMapping mapping)
+ {
+ // If the mapping does not have a scenario or _options.Scenarios does not contain this scenario from the mapping,
+ // just return null to indicate that there is no next state.
+ if (mapping.Scenario == null || !_options.Scenarios.ContainsKey(mapping.Scenario))
+ {
+ return null;
}
+
+ // Else just return the next state
+ return _options.Scenarios[mapping.Scenario].NextState;
}
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/MappingMatcherResult.cs b/src/WireMock.Net/Owin/MappingMatcherResult.cs
index 509327d61..344483036 100644
--- a/src/WireMock.Net/Owin/MappingMatcherResult.cs
+++ b/src/WireMock.Net/Owin/MappingMatcherResult.cs
@@ -1,11 +1,10 @@
using WireMock.Matchers.Request;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal class MappingMatcherResult
{
- internal class MappingMatcherResult
- {
- public IMapping Mapping { get; set; }
+ public IMapping Mapping { get; set; }
- public IRequestMatchResult RequestMatchResult { get; set; }
- }
+ public IRequestMatchResult RequestMatchResult { get; set; }
}
\ No newline at end of file
diff --git a/src/WireMock.Net/Owin/OwinSelfHost.cs b/src/WireMock.Net/Owin/OwinSelfHost.cs
index d0740a9f3..58992ff16 100644
--- a/src/WireMock.Net/Owin/OwinSelfHost.cs
+++ b/src/WireMock.Net/Owin/OwinSelfHost.cs
@@ -1,110 +1,109 @@
#if !USE_ASPNETCORE
-using JetBrains.Annotations;
using Microsoft.Owin.Hosting;
using Owin;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
+using JetBrains.Annotations;
using WireMock.Logging;
using WireMock.Owin.Mappers;
using Stef.Validation;
-namespace WireMock.Owin
+namespace WireMock.Owin;
+
+internal class OwinSelfHost : IOwinSelfHost
{
- internal class OwinSelfHost : IOwinSelfHost
- {
- private readonly IWireMockMiddlewareOptions _options;
- private readonly CancellationTokenSource _cts = new CancellationTokenSource();
- private readonly IWireMockLogger _logger;
+ private readonly IWireMockMiddlewareOptions _options;
+ private readonly CancellationTokenSource _cts = new();
+ private readonly IWireMockLogger _logger;
- private Exception _runningException;
+ private Exception? _runningException;
- public OwinSelfHost([NotNull] IWireMockMiddlewareOptions options, [NotNull] HostUrlOptions urlOptions)
- {
- Guard.NotNull(options, nameof(options));
- Guard.NotNull(urlOptions, nameof(urlOptions));
+ public OwinSelfHost(IWireMockMiddlewareOptions options, HostUrlOptions urlOptions)
+ {
+ Guard.NotNull(options, nameof(options));
+ Guard.NotNull(urlOptions, nameof(urlOptions));
- _options = options;
- _logger = options.Logger ?? new WireMockConsoleLogger();
+ _options = options;
+ _logger = options.Logger ?? new WireMockConsoleLogger();
- foreach (var detail in urlOptions.GetDetails())
- {
- Urls.Add(detail.Url);
- Ports.Add(detail.Port);
- }
+ foreach (var detail in urlOptions.GetDetails())
+ {
+ Urls.Add(detail.Url);
+ Ports.Add(detail.Port);
}
+ }
- public bool IsStarted { get; private set; }
+ public bool IsStarted { get; private set; }
- public List Urls { get; } = new List();
+ public List Urls { get; } = new();
- public List Ports { get; } = new List();
+ public List Ports { get; } = new();
- public Exception RunningException => _runningException;
+ public Exception? RunningException => _runningException;
- [PublicAPI]
- public Task StartAsync()
- {
- return Task.Run(StartServers, _cts.Token);
- }
+ [PublicAPI]
+ public Task StartAsync()
+ {
+ return Task.Run(StartServers, _cts.Token);
+ }
- [PublicAPI]
- public Task StopAsync()
- {
- _cts.Cancel();
+ [PublicAPI]
+ public Task StopAsync()
+ {
+ _cts.Cancel();
- return Task.FromResult(true);
- }
+ return Task.FromResult(true);
+ }
- private void StartServers()
- {
+ private void StartServers()
+ {
#if NET46
- _logger.Info("Server using .net 4.6.1 or higher");
+ _logger.Info("Server using .net 4.6.1 or higher");
#else
- _logger.Info("Server using .net 4.5.x");
+ _logger.Info("Server using .net 4.5.x");
#endif
- var servers = new List();
+ var servers = new List();
- try
- {
- var requestMapper = new OwinRequestMapper();
- var responseMapper = new OwinResponseMapper(_options);
- var matcher = new MappingMatcher(_options);
-
- Action startup = app =>
- {
- app.Use(_options, responseMapper);
- _options.PreWireMockMiddlewareInit?.Invoke(app);
- app.Use(_options, requestMapper, responseMapper, matcher);
- _options.PostWireMockMiddlewareInit?.Invoke(app);
- };
-
- foreach (var url in Urls)
- {
- servers.Add(WebApp.Start(url, startup));
- }
-
- IsStarted = true;
-
- // WaitHandle is signaled when the token is cancelled,
- // which will be more efficient than Thread.Sleep in while loop
- _cts.Token.WaitHandle.WaitOne();
- }
- catch (Exception e)
+ try
+ {
+ var requestMapper = new OwinRequestMapper();
+ var responseMapper = new OwinResponseMapper(_options);
+ var matcher = new MappingMatcher(_options);
+
+ Action startup = app =>
{
- // Expose exception of starting host, otherwise it's hard to be troubleshooting if keeping quiet
- // For example, WebApp.Start will fail with System.MissingMemberException if Microsoft.Owin.Host.HttpListener.dll is being located
- // https://stackoverflow.com/questions/25090211/owin-httplistener-not-located/31369857
- _runningException = e;
- _logger.Error(e.ToString());
- }
- finally
+ app.Use(_options, responseMapper);
+ _options.PreWireMockMiddlewareInit?.Invoke(app);
+ app.Use(_options, requestMapper, responseMapper, matcher);
+ _options.PostWireMockMiddlewareInit?.Invoke(app);
+ };
+
+ foreach (var url in Urls)
{
- IsStarted = false;
- // Dispose all servers in finally block to make sure clean up allocated resource on error happening
- servers.ForEach(s => s.Dispose());
+ servers.Add(WebApp.Start(url, startup));
}
+
+ IsStarted = true;
+
+ // WaitHandle is signaled when the token is cancelled,
+ // which will be more efficient than Thread.Sleep in while loop
+ _cts.Token.WaitHandle.WaitOne();
+ }
+ catch (Exception e)
+ {
+ // Expose exception of starting host, otherwise it's hard to be troubleshooting if keeping quiet
+ // For example, WebApp.Start will fail with System.MissingMemberException if Microsoft.Owin.Host.HttpListener.dll is being located
+ // https://stackoverflow.com/questions/25090211/owin-httplistener-not-located/31369857
+ _runningException = e;
+ _logger.Error(e.ToString());
+ }
+ finally
+ {
+ IsStarted = false;
+ // Dispose all servers in finally block to make sure clean up allocated resource on error happening
+ servers.ForEach(s => s.Dispose());
}
}
}
diff --git a/src/WireMock.Net/Owin/WireMockMiddleware.cs b/src/WireMock.Net/Owin/WireMockMiddleware.cs
index 5c79eecf6..5bbb90976 100644
--- a/src/WireMock.Net/Owin/WireMockMiddleware.cs
+++ b/src/WireMock.Net/Owin/WireMockMiddleware.cs
@@ -1,6 +1,7 @@
using System;
using System.Threading.Tasks;
using System.Linq;
+using System.Net;
using Stef.Validation;
using WireMock.Logging;
using WireMock.Matchers;
@@ -74,10 +75,16 @@ private async Task InvokeInternalAsync(IContext ctx)
var logRequest = false;
IResponseMessage? response = null;
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
+
try
{
- foreach (var mapping in _options.Mappings.Values.Where(m => m?.Scenario != null))
+ foreach (var mapping in _options.Mappings.Values)
{
+ if (mapping.Scenario is null)
+ {
+ continue;
+ }
+
// Set scenario start
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
{
@@ -107,7 +114,7 @@ private async Task InvokeInternalAsync(IContext ctx)
if (!present || _options.AuthenticationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
{
_options.Logger.Error("HttpStatusCode set to 401");
- response = ResponseMessageBuilder.Create(null, 401);
+ response = ResponseMessageBuilder.Create(null, HttpStatusCode.Unauthorized);
return;
}
}
@@ -194,7 +201,7 @@ private async Task InvokeInternalAsync(IContext ctx)
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
{
- for (int index = 0; index < mapping.Webhooks.Length; index++)
+ for (int index = 0; index < mapping.Webhooks?.Length; index++)
{
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
var webhookSender = new WebhookSender(mapping.Settings);
@@ -212,7 +219,7 @@ private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request
private void UpdateScenarioState(IMapping mapping)
{
- var scenario = _options.Scenarios[mapping.Scenario];
+ var scenario = _options.Scenarios[mapping.Scenario!];
// Increase the number of times this state has been executed
scenario.Counter++;
diff --git a/src/WireMock.Net/RequestMessage.cs b/src/WireMock.Net/RequestMessage.cs
index 2470ee0f9..9c67444fe 100644
--- a/src/WireMock.Net/RequestMessage.cs
+++ b/src/WireMock.Net/RequestMessage.cs
@@ -47,10 +47,10 @@ public class RequestMessage : IRequestMessage
public string Method { get; }
///
- public IDictionary>? Headers { get; }
+ public IDictionary> Headers { get; }
///
- public IDictionary? Cookies { get; }
+ public IDictionary Cookies { get; }
///
public IDictionary>? Query { get; }
diff --git a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
index 5c9377d72..3ed1ba9b7 100644
--- a/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
+++ b/test/WireMock.Net.Tests/Owin/MappingMatcherTests.cs
@@ -1,4 +1,4 @@
-using System;
+using System;
using System.Collections.Concurrent;
using FluentAssertions;
using Moq;
@@ -9,183 +9,195 @@
using WireMock.Util;
using Xunit;
-namespace WireMock.Net.Tests.Owin
+namespace WireMock.Net.Tests.Owin;
+
+public class MappingMatcherTests
{
- public class MappingMatcherTests
+ private readonly Mock _optionsMock;
+ private readonly MappingMatcher _sut;
+
+ public MappingMatcherTests()
{
- private readonly Mock _optionsMock;
- private readonly MappingMatcher _sut;
+ _optionsMock = new Mock();
+ _optionsMock.SetupAllProperties();
+ _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary());
+ _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection());
+ _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary());
+
+ var loggerMock = new Mock();
+ loggerMock.SetupAllProperties();
+ loggerMock.Setup(l => l.Error(It.IsAny()));
+ _optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
+
+ _sut = new MappingMatcher(_optionsMock.Object);
+ }
- public MappingMatcherTests()
- {
- _optionsMock = new Mock();
- _optionsMock.SetupAllProperties();
- _optionsMock.Setup(o => o.Mappings).Returns(new ConcurrentDictionary());
- _optionsMock.Setup(o => o.LogEntries).Returns(new ConcurrentObservableCollection());
- _optionsMock.Setup(o => o.Scenarios).Returns(new ConcurrentDictionary());
-
- var loggerMock = new Mock();
- loggerMock.SetupAllProperties();
- loggerMock.Setup(l => l.Error(It.IsAny()));
- _optionsMock.Setup(o => o.Logger).Returns(loggerMock.Object);
-
- _sut = new MappingMatcher(_optionsMock.Object);
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenNoMappingsDefined_ShouldReturnNull()
+ {
+ // Assign
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenNoMappingsDefined_ShouldReturnNull()
- {
- // Assign
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+ // Act
+ var result = _sut.FindBestMatch(request);
- // Act
- var result = _sut.FindBestMatch(request);
+ // Assert
+ result.Match.Should().BeNull();
+ result.Partial.Should().BeNull();
+ }
- // Assert
- result.Match.Should().BeNull();
- result.Partial.Should().BeNull();
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenMappingThrowsException_ShouldReturnNull()
+ {
+ // Assign
+ var mappingMock = new Mock();
+ mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Throws();
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenMappingThrowsException_ShouldReturnNull()
- {
- // Assign
- var mappingMock = new Mock();
- mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Throws();
+ var mappings = new ConcurrentDictionary();
+ mappings.TryAdd(Guid.NewGuid(), mappingMock.Object);
- var mappings = new ConcurrentDictionary();
- mappings.TryAdd(Guid.NewGuid(), mappingMock.Object);
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+ // Act
+ var result = _sut.FindBestMatch(request);
- // Act
- var result = _sut.FindBestMatch(request);
+ // Assert
+ result.Match.Should().BeNull();
+ result.Partial.Should().BeNull();
+ }
- // Assert
- result.Match.Should().BeNull();
- result.Partial.Should().BeNull();
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_ShouldReturnExactMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings
+ (
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 1.0 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().NotBeNull();
+ result.Match!.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+
+ result.Partial.Should().NotBeNull();
+ result.Partial!.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ }
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_ShouldReturnExactMatch()
- {
- // Assign
- var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
- var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
- var mappings = InitMappings(
- (guid1, new[] { 0.1 }),
- (guid2, new[] { 1.0 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert
- result.Match.Mapping.Guid.Should().Be(guid2);
- result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
- result.Partial.Mapping.Guid.Should().Be(guid2);
- result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_AndNoExactMatch_ShouldReturnNullExactMatch_And_PartialMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings
+ (
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 0.9 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().BeNull();
+
+ result.Partial.Should().NotBeNull();
+ result.Partial!.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+ }
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_AndNoExactmatch_ShouldReturnNullExactMatch_And_PartialMatch()
- {
- // Assign
- var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
- var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
- var mappings = InitMappings(
- (guid1, new[] { 0.1 }),
- (guid2, new[] { 0.9 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert
- result.Match.Should().BeNull();
- result.Partial.Mapping.Guid.Should().Be(guid2);
- result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsTrue_ShouldReturnAnyMatch()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+
+ _optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
+ var mappings = InitMappings(
+ (guid1, new[] { 0.1 }),
+ (guid2, new[] { 0.9 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert
+ result.Match.Should().NotBeNull();
+ result.Match!.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+
+ result.Partial.Should().NotBeNull();
+ result.Partial!.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
+ }
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsTrue_ShouldReturnAnyMatch()
- {
- // Assign
- var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
- var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
-
- _optionsMock.SetupGet(o => o.AllowPartialMapping).Returns(true);
- var mappings = InitMappings(
- (guid1, new[] { 0.1 }),
- (guid2, new[] { 0.9 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert
- result.Match.Mapping.Guid.Should().Be(guid2);
- result.Match.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
- result.Partial.Mapping.Guid.Should().Be(guid2);
- result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(0.9);
- }
+ [Fact]
+ public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_WithSameAverageScoreButMoreMatchers_ReturnsMatchWithMoreMatchers()
+ {
+ // Assign
+ var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
+ var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
+ var mappings = InitMappings(
+ (guid1, new[] { 1.0 }),
+ (guid2, new[] { 1.0, 1.0 })
+ );
+ _optionsMock.Setup(o => o.Mappings).Returns(mappings);
+
+ var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
+
+ // Act
+ var result = _sut.FindBestMatch(request);
+
+ // Assert and Verify
+ result.Match.Should().NotBeNull();
+ result.Match!.Mapping.Guid.Should().Be(guid2);
+ result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+
+ result.Partial.Should().NotBeNull();
+ result.Partial!.Mapping.Guid.Should().Be(guid2);
+ result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
+ }
- [Fact]
- public void MappingMatcher_FindBestMatch_WhenAllowPartialMappingIsFalse_And_WithSameAverageScoreButMoreMatchers_ReturnsMatchWithMoreMatchers()
- {
- // Assign
- var guid1 = Guid.Parse("00000000-0000-0000-0000-000000000001");
- var guid2 = Guid.Parse("00000000-0000-0000-0000-000000000002");
- var mappings = InitMappings(
- (guid1, new[] { 1.0 }),
- (guid2, new[] { 1.0, 1.0 })
- );
- _optionsMock.Setup(o => o.Mappings).Returns(mappings);
-
- var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
-
- // Act
- var result = _sut.FindBestMatch(request);
-
- // Assert and Verify
- result.Match.Mapping.Guid.Should().Be(guid2);
- result.Match.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
- result.Partial.Mapping.Guid.Should().Be(guid2);
- result.Partial.RequestMatchResult.AverageTotalScore.Should().Be(1.0);
- }
+ private static ConcurrentDictionary InitMappings(params (Guid guid, double[] scores)[] matches)
+ {
+ var mappings = new ConcurrentDictionary();
- private ConcurrentDictionary InitMappings(params (Guid guid, double[] scores)[] matches)
+ foreach (var match in matches)
{
- var mappings = new ConcurrentDictionary();
+ var mappingMock = new Mock();
+ mappingMock.SetupGet(m => m.Guid).Returns(match.guid);
- foreach (var match in matches)
+ var requestMatchResult = new RequestMatchResult();
+ foreach (var score in match.scores)
{
- var mappingMock = new Mock();
- mappingMock.SetupGet(m => m.Guid).Returns(match.guid);
-
- var requestMatchResult = new RequestMatchResult();
- foreach (var score in match.scores)
- {
- requestMatchResult.AddScore(typeof(object), score);
- }
-
- mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Returns(requestMatchResult);
-
- mappings.TryAdd(match.guid, mappingMock.Object);
+ requestMatchResult.AddScore(typeof(object), score);
}
- return mappings;
+ mappingMock.Setup(m => m.GetRequestMatchResult(It.IsAny(), It.IsAny())).Returns(requestMatchResult);
+
+ mappings.TryAdd(match.guid, mappingMock.Object);
}
+
+ return mappings;
}
}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs
index 58b317c32..def80c602 100644
--- a/test/WireMock.Net.Tests/WireMockServer.Proxy.cs
+++ b/test/WireMock.Net.Tests/WireMockServer.Proxy.cs
@@ -63,7 +63,8 @@ public async Task WireMockServer_Proxy_AdminFalse_With_SaveMapping_Is_True_And_S
{
Url = "http://www.google.com",
SaveMapping = true,
- SaveMappingToFile = false
+ SaveMappingToFile = false,
+ ExcludedHeaders = new[] { "Connection" } // Needed for .NET 4.5.x and 4.6.x
}
};
var server = WireMockServer.Start(settings);
@@ -82,7 +83,7 @@ public async Task WireMockServer_Proxy_AdminFalse_With_SaveMapping_Is_True_And_S
}
// Assert
- server.Mappings.Should().HaveCountGreaterOrEqualTo(2); // For .NET 4.5.2 and 4.6.x this is 3?
+ server.Mappings.Should().HaveCount(2);
}
[Fact]
@@ -95,7 +96,8 @@ public async Task WireMockServer_Proxy_AdminTrue_With_SaveMapping_Is_True_And_Sa
{
Url = "http://www.google.com",
SaveMapping = true,
- SaveMappingToFile = false
+ SaveMappingToFile = false,
+ ExcludedHeaders = new[] { "Connection" } // Needed for .NET 4.5.x and 4.6.x
},
StartAdminInterface = true
};
@@ -114,7 +116,7 @@ public async Task WireMockServer_Proxy_AdminTrue_With_SaveMapping_Is_True_And_Sa
}
// Assert
- server.Mappings.Should().HaveCountGreaterOrEqualTo(28); // For .NET 4.5.2 and 4.6.x this is 29?
+ server.Mappings.Should().HaveCount(28);
}
[Fact]