diff --git a/WireMock.Net Solution.sln b/WireMock.Net Solution.sln
index 0d20008cb..5e5ab3859 100644
--- a/WireMock.Net Solution.sln
+++ b/WireMock.Net Solution.sln
@@ -78,7 +78,9 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-WireMock", "src\dotn
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET5", "examples\WireMock.Net.Console.NET5\WireMock.Net.Console.NET5.csproj", "{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}"
EndProject
-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Matchers.CSharpCode", "src\WireMock.Net.Matchers.CSharpCode\WireMock.Net.Matchers.CSharpCode.csproj", "{6437CE56-8AB9-4D6D-90F1-70CC5BBE1572}"
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Matchers.CSharpCode", "src\WireMock.Net.Matchers.CSharpCode\WireMock.Net.Matchers.CSharpCode.csproj", "{B6269AAC-170A-4346-8B9A-444DED3D9A44}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net472.Classic", "examples\WireMock.Net.Console.Net472.Classic\WireMock.Net.Console.Net472.Classic.csproj", "{6580580B-1EFD-4922-B0EC-FF290DB279EE}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
@@ -194,10 +196,14 @@ Global
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Release|Any CPU.Build.0 = Release|Any CPU
- {6437CE56-8AB9-4D6D-90F1-70CC5BBE1572}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
- {6437CE56-8AB9-4D6D-90F1-70CC5BBE1572}.Debug|Any CPU.Build.0 = Debug|Any CPU
- {6437CE56-8AB9-4D6D-90F1-70CC5BBE1572}.Release|Any CPU.ActiveCfg = Release|Any CPU
- {6437CE56-8AB9-4D6D-90F1-70CC5BBE1572}.Release|Any CPU.Build.0 = Release|Any CPU
+ {B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {B6269AAC-170A-4346-8B9A-444DED3D9A44}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {B6269AAC-170A-4346-8B9A-444DED3D9A44}.Release|Any CPU.Build.0 = Release|Any CPU
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -230,7 +236,8 @@ Global
{925E421A-1B3F-4202-B48F-734743573A4B} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{40BF24B5-12E6-4610-9489-138798632E28} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
- {6437CE56-8AB9-4D6D-90F1-70CC5BBE1572} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
+ {B6269AAC-170A-4346-8B9A-444DED3D9A44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
diff --git a/examples/WireMock.Net.Console.NET5/WireMock.Net.Console.NET5.csproj b/examples/WireMock.Net.Console.NET5/WireMock.Net.Console.NET5.csproj
index 0e238f852..7c8899699 100644
--- a/examples/WireMock.Net.Console.NET5/WireMock.Net.Console.NET5.csproj
+++ b/examples/WireMock.Net.Console.NET5/WireMock.Net.Console.NET5.csproj
@@ -30,6 +30,7 @@
+
diff --git a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
index 9d8d3d2ee..8a9342ef3 100644
--- a/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
+++ b/examples/WireMock.Net.Console.Net452.Classic/MainApp.cs
@@ -280,7 +280,7 @@ public static void Run()
.WithBody("hi"));
server
- .Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
+ .Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b != null && b.Contains("e")))
.AtPriority(999)
.RespondWith(Response.Create()
.WithStatusCode(201)
diff --git a/examples/WireMock.Net.Console.Net472.Classic/App.config b/examples/WireMock.Net.Console.Net472.Classic/App.config
new file mode 100644
index 000000000..773045f8d
--- /dev/null
+++ b/examples/WireMock.Net.Console.Net472.Classic/App.config
@@ -0,0 +1,54 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/examples/WireMock.Net.Console.Net472.Classic/Properties/AssemblyInfo.cs b/examples/WireMock.Net.Console.Net472.Classic/Properties/AssemblyInfo.cs
new file mode 100644
index 000000000..a10ce6d38
--- /dev/null
+++ b/examples/WireMock.Net.Console.Net472.Classic/Properties/AssemblyInfo.cs
@@ -0,0 +1,36 @@
+using System.Reflection;
+using System.Runtime.CompilerServices;
+using System.Runtime.InteropServices;
+
+// General Information about an assembly is controlled through the following
+// set of attributes. Change these attribute values to modify the information
+// associated with an assembly.
+[assembly: AssemblyTitle("WireMock.Net.Console.Net461.Classic")]
+[assembly: AssemblyDescription("")]
+[assembly: AssemblyConfiguration("")]
+[assembly: AssemblyCompany("")]
+[assembly: AssemblyProduct("WireMock.Net.Console.Net461.Classic")]
+[assembly: AssemblyCopyright("Copyright © Stef Heyenrath 2018")]
+[assembly: AssemblyTrademark("")]
+[assembly: AssemblyCulture("")]
+
+// Setting ComVisible to false makes the types in this assembly not visible
+// to COM components. If you need to access a type in this assembly from
+// COM, set the ComVisible attribute to true on that type.
+[assembly: ComVisible(false)]
+
+// The following GUID is for the ID of the typelib if this project is exposed to COM
+[assembly: Guid("1261bb9b-a7d4-456c-8985-3ce560361b8e")]
+
+// Version information for an assembly consists of the following four values:
+//
+// Major Version
+// Minor Version
+// Build Number
+// Revision
+//
+// You can specify all the values or you can default the Build and Revision Numbers
+// by using the '*' as shown below:
+// [assembly: AssemblyVersion("1.0.*")]
+[assembly: AssemblyVersion("1.0.0.0")]
+[assembly: AssemblyFileVersion("1.0.0.0")]
diff --git a/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj
new file mode 100644
index 000000000..6b236af8a
--- /dev/null
+++ b/examples/WireMock.Net.Console.Net472.Classic/WireMock.Net.Console.Net472.Classic.csproj
@@ -0,0 +1,326 @@
+
+
+
+
+
+ Debug
+ AnyCPU
+ {6580580B-1EFD-4922-B0EC-FF290DB279EE}
+ Exe
+ WireMock.Net.Console.Net461.Classic
+ WireMock.Net.Console.Net461.Classic
+ v4.7.2
+ 512
+ true
+
+
+
+
+
+ AnyCPU
+ true
+ full
+ false
+ bin\Debug\
+ DEBUG;TRACE
+ prompt
+ 4
+
+
+ AnyCPU
+ pdbonly
+ true
+ bin\Release\
+ TRACE
+ prompt
+ 4
+
+
+ WireMock.Net.ConsoleApplication.Program
+
+
+
+ ..\..\packages\Fare.2.1.1\lib\net35\Fare.dll
+
+
+ ..\..\packages\Handlebars.Net.1.9.5\lib\net452\Handlebars.dll
+
+
+ ..\..\packages\Handlebars.Net.Helpers.1.1.0\lib\net452\Handlebars.Net.Helpers.dll
+
+
+ ..\..\packages\JmesPath.Net.1.0.125\lib\net45\JmesPath.Net.dll
+
+
+ ..\..\packages\log4net.2.0.12\lib\net45\log4net.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Authentication.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Authentication.Core.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Authentication.Core.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Connections.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Connections.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Diagnostics.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Diagnostics.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Diagnostics.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.HostFiltering.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HostFiltering.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Hosting.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Hosting.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Hosting.Server.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Hosting.Server.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Http.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Http.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Http.Extensions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Extensions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Http.Features.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Http.Features.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.HttpOverrides.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.HttpOverrides.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Routing.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Routing.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Routing.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.IIS.2.2.6\lib\netstandard2.0\Microsoft.AspNetCore.Server.IIS.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.IISIntegration.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.IISIntegration.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.Kestrel.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.Kestrel.Core.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Core.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.Kestrel.Https.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Https.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets.dll
+
+
+ ..\..\packages\Microsoft.AspNetCore.WebUtilities.2.2.0\lib\netstandard2.0\Microsoft.AspNetCore.WebUtilities.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.5.0.0\lib\net461\Microsoft.Extensions.Configuration.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.Abstractions.5.0.0\lib\net461\Microsoft.Extensions.Configuration.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.Binder.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Binder.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.CommandLine.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.CommandLine.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.EnvironmentVariables.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.EnvironmentVariables.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.FileExtensions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.FileExtensions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.Json.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.Json.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Configuration.UserSecrets.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Configuration.UserSecrets.dll
+
+
+ ..\..\packages\Microsoft.Extensions.DependencyInjection.2.2.0\lib\net461\Microsoft.Extensions.DependencyInjection.dll
+
+
+ ..\..\packages\Microsoft.Extensions.DependencyInjection.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.DependencyInjection.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.FileProviders.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.FileProviders.Physical.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileProviders.Physical.dll
+
+
+ ..\..\packages\Microsoft.Extensions.FileSystemGlobbing.2.2.0\lib\netstandard2.0\Microsoft.Extensions.FileSystemGlobbing.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Hosting.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Hosting.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.Abstractions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Abstractions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.Configuration.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Configuration.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.Console.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Console.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.Debug.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.Debug.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Logging.EventSource.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Logging.EventSource.dll
+
+
+ ..\..\packages\Microsoft.Extensions.ObjectPool.2.2.0\lib\netstandard2.0\Microsoft.Extensions.ObjectPool.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Options.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Options.ConfigurationExtensions.2.2.0\lib\netstandard2.0\Microsoft.Extensions.Options.ConfigurationExtensions.dll
+
+
+ ..\..\packages\Microsoft.Extensions.Primitives.5.0.0\lib\net461\Microsoft.Extensions.Primitives.dll
+
+
+ ..\..\packages\Microsoft.Net.Http.Headers.2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll
+
+
+ ..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll
+
+
+ ..\..\packages\RandomDataGenerator.Net.1.0.12\lib\net45\RandomDataGenerator.dll
+
+
+ ..\..\packages\Scriban.Signed.2.1.4\lib\net45\Scriban.Signed.dll
+
+
+ ..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll
+
+
+
+ ..\..\packages\System.Buffers.4.5.1\lib\net461\System.Buffers.dll
+
+
+ ..\..\packages\System.Collections.Immutable.1.5.0\lib\netstandard2.0\System.Collections.Immutable.dll
+
+
+ ..\..\packages\System.ComponentModel.Annotations.4.5.0\lib\net461\System.ComponentModel.Annotations.dll
+
+
+
+
+
+ ..\..\packages\System.Diagnostics.DiagnosticSource.4.5.0\lib\net46\System.Diagnostics.DiagnosticSource.dll
+
+
+ ..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll
+
+
+ ..\..\packages\System.Linq.Dynamic.Core.1.0.12\lib\net46\System.Linq.Dynamic.Core.dll
+
+
+ ..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll
+
+
+
+
+ ..\..\packages\System.Numerics.Vectors.4.5.0\lib\net46\System.Numerics.Vectors.dll
+
+
+ ..\..\packages\System.Reflection.Metadata.1.6.0\lib\netstandard2.0\System.Reflection.Metadata.dll
+
+
+ ..\..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll
+
+
+ ..\..\packages\System.Security.Cryptography.Cng.4.5.0\lib\net47\System.Security.Cryptography.Cng.dll
+
+
+ ..\..\packages\System.Security.Principal.Windows.4.5.0\lib\net461\System.Security.Principal.Windows.dll
+
+
+ ..\..\packages\System.Text.Encodings.Web.4.5.0\lib\netstandard2.0\System.Text.Encodings.Web.dll
+
+
+ ..\..\packages\System.Threading.Tasks.Extensions.4.5.1\lib\netstandard2.0\System.Threading.Tasks.Extensions.dll
+
+
+ ..\..\packages\System.ValueTuple.4.5.0\lib\net47\System.ValueTuple.dll
+
+
+
+
+
+
+
+
+
+ ..\..\packages\XPath2.1.1.0\lib\net40\XPath2.dll
+
+
+ ..\..\packages\XPath2.Extensions.1.1.0\lib\net40\XPath2.Extensions.dll
+
+
+
+
+ CustomFileSystemFileHandler.cs
+
+
+ MainApp.cs
+
+
+ Program.cs
+
+
+
+
+
+ log4net.config
+
+
+
+
+
+
+ {b6269aac-170a-4346-8b9a-579ded3d9a94}
+ WireMock.Net.Abstractions
+
+
+ {d3804228-91f4-4502-9595-39584e5a01ad}
+ WireMock.Net
+
+
+
+
+
+ This project references NuGet package(s) that are missing on this computer. Use NuGet Package Restore to download them. For more information, see http://go.microsoft.com/fwlink/?LinkID=322105. The missing file is {0}.
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/examples/WireMock.Net.Console.Net472.Classic/packages.config b/examples/WireMock.Net.Console.Net472.Classic/packages.config
new file mode 100644
index 000000000..c57d5f8b4
--- /dev/null
+++ b/examples/WireMock.Net.Console.Net472.Classic/packages.config
@@ -0,0 +1,82 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/src/WireMock.Net/Http/HttpKnownHeaderNames.cs b/src/WireMock.Net/Http/HttpKnownHeaderNames.cs
index 857e1e7eb..07c2975bb 100644
--- a/src/WireMock.Net/Http/HttpKnownHeaderNames.cs
+++ b/src/WireMock.Net/Http/HttpKnownHeaderNames.cs
@@ -19,7 +19,7 @@ internal static class HttpKnownHeaderNames
Connection,
ContentLength,
ContentType,
- Date,
+ Date, // RFC1123Pattern
Expect,
Host,
IfModifiedSince,
diff --git a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
index a70cd51ee..168647019 100644
--- a/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
+++ b/src/WireMock.Net/Owin/Mappers/OwinResponseMapper.cs
@@ -1,177 +1,188 @@
-using System;
-using System.Collections.Generic;
-using System.Linq;
-using System.Net;
+using System;
+using System.Collections.Generic;
+using System.Globalization;
+using System.Linq;
+using System.Net;
using System.Reflection;
-using System.Text;
-using System.Threading.Tasks;
-using Newtonsoft.Json;
-using RandomDataGenerator.FieldOptions;
-using RandomDataGenerator.Randomizers;
-using WireMock.Http;
-using WireMock.ResponseBuilders;
-using WireMock.Types;
-using WireMock.Validation;
-#if !USE_ASPNETCORE
-using IResponse = Microsoft.Owin.IOwinResponse;
-#else
-using Microsoft.AspNetCore.Http;
-using IResponse = Microsoft.AspNetCore.Http.HttpResponse;
-#endif
-
-namespace WireMock.Owin.Mappers
-{
- ///
- /// OwinResponseMapper
- ///
- internal class OwinResponseMapper : IOwinResponseMapper
- {
- private readonly IRandomizerNumber _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
- private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 });
- private readonly IWireMockMiddlewareOptions _options;
- private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
-
- // https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
-#if !USE_ASPNETCORE
- private static readonly IDictionary>> ResponseHeadersToFix = new Dictionary>>(StringComparer.OrdinalIgnoreCase) {
-#else
- private static readonly IDictionary>> ResponseHeadersToFix = new Dictionary>>(StringComparer.OrdinalIgnoreCase) {
-#endif
- { HttpKnownHeaderNames.ContentType, (r, v) => r.ContentType = v.FirstOrDefault() }
- };
-
- ///
- /// Constructor
- ///
- /// The IWireMockMiddlewareOptions.
- public OwinResponseMapper(IWireMockMiddlewareOptions options)
- {
- Check.NotNull(options, nameof(options));
-
- _options = options;
- }
-
- ///
- public async Task MapAsync(ResponseMessage responseMessage, IResponse response)
- {
- if (responseMessage == null)
- {
- return;
- }
-
- byte[] bytes;
- switch (responseMessage.FaultType)
- {
- case FaultType.EMPTY_RESPONSE:
- bytes = IsFault(responseMessage) ? new byte[0] : GetNormalBody(responseMessage);
- break;
-
- case FaultType.MALFORMED_RESPONSE_CHUNK:
- bytes = GetNormalBody(responseMessage) ?? new byte[0];
- if (IsFault(responseMessage))
- {
- bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
- }
-
- break;
-
- default:
- bytes = GetNormalBody(responseMessage);
- break;
- }
-
- var statusCodeType = responseMessage.StatusCode?.GetType();
-
- switch (statusCodeType)
- {
- case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
- response.StatusCode = MapStatusCode((int)responseMessage.StatusCode);
+using System.Text;
+using System.Threading.Tasks;
+using Newtonsoft.Json;
+using RandomDataGenerator.FieldOptions;
+using RandomDataGenerator.Randomizers;
+using WireMock.Http;
+using WireMock.ResponseBuilders;
+using WireMock.Types;
+using WireMock.Validation;
+#if !USE_ASPNETCORE
+using IResponse = Microsoft.Owin.IOwinResponse;
+#else
+using Microsoft.AspNetCore.Http;
+using IResponse = Microsoft.AspNetCore.Http.HttpResponse;
+#endif
+
+namespace WireMock.Owin.Mappers
+{
+ ///
+ /// OwinResponseMapper
+ ///
+ internal class OwinResponseMapper : IOwinResponseMapper
+ {
+ private readonly IRandomizerNumber _randomizerDouble = RandomizerFactory.GetRandomizer(new FieldOptionsDouble { Min = 0, Max = 1 });
+ private readonly IRandomizerBytes _randomizerBytes = RandomizerFactory.GetRandomizer(new FieldOptionsBytes { Min = 100, Max = 200 });
+ private readonly IWireMockMiddlewareOptions _options;
+ private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
+
+ // https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
+#if !USE_ASPNETCORE
+ private static readonly IDictionary>> ResponseHeadersToFix = new Dictionary>>(StringComparer.OrdinalIgnoreCase) {
+#else
+ private static readonly IDictionary>> ResponseHeadersToFix = new Dictionary>>(StringComparer.OrdinalIgnoreCase) {
+#endif
+ { HttpKnownHeaderNames.ContentType, (r, v) => r.ContentType = v.FirstOrDefault() }
+ };
+
+ ///
+ /// Constructor
+ ///
+ /// The IWireMockMiddlewareOptions.
+ public OwinResponseMapper(IWireMockMiddlewareOptions options)
+ {
+ Check.NotNull(options, nameof(options));
+
+ _options = options;
+ }
+
+ ///
+ public async Task MapAsync(ResponseMessage responseMessage, IResponse response)
+ {
+ if (responseMessage == null)
+ {
+ return;
+ }
+
+ byte[] bytes;
+ switch (responseMessage.FaultType)
+ {
+ case FaultType.EMPTY_RESPONSE:
+ bytes = IsFault(responseMessage) ? new byte[0] : GetNormalBody(responseMessage);
+ break;
+
+ case FaultType.MALFORMED_RESPONSE_CHUNK:
+ bytes = GetNormalBody(responseMessage) ?? new byte[0];
+ if (IsFault(responseMessage))
+ {
+ bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
+ }
+
+ break;
+
+ default:
+ bytes = GetNormalBody(responseMessage);
+ break;
+ }
+
+ var statusCodeType = responseMessage.StatusCode?.GetType();
+
+ switch (statusCodeType)
+ {
+ case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
+ response.StatusCode = MapStatusCode((int)responseMessage.StatusCode);
+ break;
+
+ case Type typeAsString when typeAsString == typeof(string):
+ // Note: this case will also match on null
+ int.TryParse(responseMessage.StatusCode as string, out int result);
+ response.StatusCode = MapStatusCode(result);
+ break;
+
+ default:
break;
+ }
+
+ SetResponseHeaders(responseMessage, response);
+
+ if (bytes != null)
+ {
+ await response.Body.WriteAsync(bytes, 0, bytes.Length);
+ }
+ }
+
+ private int MapStatusCode(int code)
+ {
+ if (_options.AllowOnlyDefinedHttpStatusCodeInResponse == true && !Enum.IsDefined(typeof(HttpStatusCode), code))
+ {
+ return (int)HttpStatusCode.OK;
+ }
+
+ return code;
+ }
+
+ private bool IsFault(ResponseMessage responseMessage)
+ {
+ return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
+ }
+
+ private byte[] GetNormalBody(ResponseMessage responseMessage)
+ {
+ byte[] bytes = null;
+ switch (responseMessage.BodyData?.DetectedBodyType)
+ {
+ case BodyType.String:
+ bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString);
+ break;
+
+ case BodyType.Json:
+ Formatting formatting = responseMessage.BodyData.BodyAsJsonIndented == true
+ ? Formatting.Indented
+ : Formatting.None;
+ string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
+ bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
+ break;
+
+ case BodyType.Bytes:
+ bytes = responseMessage.BodyData.BodyAsBytes;
+ break;
+
+ case BodyType.File:
+ bytes = _options.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
+ break;
+ }
+
+ return bytes;
+ }
+
+ private static void SetResponseHeaders(ResponseMessage responseMessage, IResponse response)
+ {
+ // Force setting the Date header (#577)
+ AppendResponseHeader(response, HttpKnownHeaderNames.Date, new[] { string.Format(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, DateTime.Now) });
+
+ // Set other headers
+ foreach (var item in responseMessage.Headers)
+ {
+ var headerName = item.Key;
+ var value = item.Value;
+ if (ResponseHeadersToFix.ContainsKey(headerName))
+ {
+ ResponseHeadersToFix[headerName]?.Invoke(response, value);
+ }
+ else
+ {
+ // Check if this response header can be added (#148 and #227)
+ if (!HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName))
+ {
+ AppendResponseHeader(response, headerName, value.ToArray());
+ }
+ }
+ }
+ }
- case Type typeAsString when typeAsString == typeof(string):
- // Note: this case will also match on null
- int.TryParse(responseMessage.StatusCode as string, out int result);
- response.StatusCode = MapStatusCode(result);
- break;
-
- default:
- break;
- }
-
- SetResponseHeaders(responseMessage, response);
-
- if (bytes != null)
- {
- await response.Body.WriteAsync(bytes, 0, bytes.Length);
- }
- }
-
- private int MapStatusCode(int code)
- {
- if (_options.AllowOnlyDefinedHttpStatusCodeInResponse == true && !Enum.IsDefined(typeof(HttpStatusCode), code))
- {
- return (int)HttpStatusCode.OK;
- }
-
- return code;
- }
-
- private bool IsFault(ResponseMessage responseMessage)
- {
- return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
- }
-
- private byte[] GetNormalBody(ResponseMessage responseMessage)
- {
- byte[] bytes = null;
- switch (responseMessage.BodyData?.DetectedBodyType)
- {
- case BodyType.String:
- bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString);
- break;
-
- case BodyType.Json:
- Formatting formatting = responseMessage.BodyData.BodyAsJsonIndented == true
- ? Formatting.Indented
- : Formatting.None;
- string jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
- bytes = (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
- break;
-
- case BodyType.Bytes:
- bytes = responseMessage.BodyData.BodyAsBytes;
- break;
-
- case BodyType.File:
- bytes = _options.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
- break;
- }
-
- return bytes;
- }
-
- private void SetResponseHeaders(ResponseMessage responseMessage, IResponse response)
- {
- // Set headers
- foreach (var pair in responseMessage.Headers)
- {
- if (ResponseHeadersToFix.ContainsKey(pair.Key))
- {
- ResponseHeadersToFix[pair.Key]?.Invoke(response, pair.Value);
- }
- else
- {
- // Check if this response header can be added (#148 and #227)
- if (!HttpKnownHeaderNames.IsRestrictedResponseHeader(pair.Key))
- {
-#if !USE_ASPNETCORE
- response.Headers.AppendValues(pair.Key, pair.Value.ToArray());
-#else
- response.Headers.Append(pair.Key, pair.Value.ToArray());
-#endif
- }
- }
- }
- }
- }
+ private static void AppendResponseHeader(IResponse response, string headerName, string[] values)
+ {
+#if !USE_ASPNETCORE
+ response.Headers.AppendValues(headerName, values);
+#else
+ response.Headers.Append(headerName, values);
+#endif
+ }
+ }
}
\ No newline at end of file
diff --git a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs
index caf662c96..b0c4b187a 100644
--- a/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs
+++ b/test/WireMock.Net.Tests/Owin/Mappers/OwinResponseMapperTests.cs
@@ -108,23 +108,6 @@ public async Task OwinResponseMapper_MapAsync_Invalid_StatusCode_When_AllowOnlyD
_responseMock.VerifySet(r => r.StatusCode = expected, Times.Once);
}
- [Fact]
- public async Task OwinResponseMapper_MapAsync_Null_StatusCode_When_AllowOnlyDefinedHttpStatusCodeInResponseSet_Is_True()
- {
- // Arrange
- _optionsMock.SetupGet(o => o.AllowOnlyDefinedHttpStatusCodeInResponse).Returns(true);
- var responseMessage = new ResponseMessage
- {
- StatusCode = null
- };
-
- // Act
- await _sut.MapAsync(responseMessage, _responseMock.Object);
-
- // Assert
- _responseMock.VerifyNoOtherCalls();
- }
-
[Fact]
public async Task OwinResponseMapper_MapAsync_StatusCode_Is_Null()
{
@@ -138,7 +121,7 @@ public async Task OwinResponseMapper_MapAsync_StatusCode_Is_Null()
await _sut.MapAsync(responseMessage, _responseMock.Object);
// Assert
- _responseMock.VerifyNoOtherCalls();
+ _responseMock.VerifySet(r => r.StatusCode = It.IsAny(), Times.Never);
}
[Theory]