Compare commits

...

3 Commits

Author SHA1 Message Date
Stef Heyenrath
b06b3c8e8b 1.4.41 2022-04-21 18:28:49 +02:00
Stef Heyenrath
2e5bfc41d5 Update the logic for ProxyAndRecord (#747)
* .

* set

* .

* .

* .

* .

* prio

* appsettings

* TinyMapperUtils

* set

* p

* nullable

* .

* ,

* fs

* .

* .

* --PreferProxyMapping
2022-04-21 17:58:44 +02:00
Stef Heyenrath
9d54994747 Allow Timeout.InfiniteTimeSpan for WithDelay (#746)
* Update WithDelay

* Allow Timeout.InfiniteTimeSpan for WithDelay
2022-04-18 20:55:23 +02:00
37 changed files with 1953 additions and 1550 deletions

View File

@@ -1,3 +1,8 @@
# 1.4.41 (21 April 2022)
- [#746](https://github.com/WireMock-Net/WireMock.Net/pull/746) - Allow Timeout.InfiniteTimeSpan for WithDelay [feature] contributed by [StefH](https://github.com/StefH)
- [#747](https://github.com/WireMock-Net/WireMock.Net/pull/747) - Update the logic for ProxyAndRecord contributed by [StefH](https://github.com/StefH)
- [#744](https://github.com/WireMock-Net/WireMock.Net/issues/744) - System.ArgumentOutOfRangeException when Timeout.InfiniteTimeSpan used as an argument for IResponseBuilder.WithDelay() [bug]
# 1.4.40 (26 March 2022)
- [#740](https://github.com/WireMock-Net/WireMock.Net/pull/740) - Add Port and Url property to WireMockServer + upgrade System.Linq.Dynamic.Core [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.4.40</VersionPrefix>
<VersionPrefix>1.4.41</VersionPrefix>
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
@@ -13,6 +13,8 @@
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
<LangVersion>Latest</LangVersion>
<Nullable>enable</Nullable>
</PropertyGroup>
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
@@ -24,6 +26,10 @@
<!--<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>-->
</ItemGroup>
<PropertyGroup Condition="'$(TargetFramework)' != 'net45'">
<!--<Nullable>enable</Nullable>-->
</PropertyGroup>
<Choose>
<!-- The environment variable `Prerelease` is set in the azure-pipelines.yml file. -->
<When Condition=" '$(Prerelease)' != '' ">

View File

@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=1.4.40
SET version=1.4.41
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%

View File

@@ -1,4 +1,6 @@
# 1.4.40 (26 March 2022)
- #740 Add Port and Url property to WireMockServer + upgrade System.Linq.Dynamic.Core [feature]
# 1.4.41 (21 April 2022)
- #746 Allow Timeout.InfiniteTimeSpan for WithDelay [feature]
- #747 Update the logic for ProxyAndRecord
- #744 System.ArgumentOutOfRangeException when Timeout.InfiniteTimeSpan used as an argument for IResponseBuilder.WithDelay() [bug]
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -40,8 +40,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Client", "exam
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NETCoreApp", "examples\WireMock.Net.Console.NETCoreApp\WireMock.Net.Console.NETCoreApp.csproj", "{FE281639-B014-4C8A-96FA-141164A74713}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.NETCoreApp", "examples\WireMock.Net.Console.Record.NETCoreApp\WireMock.Net.Console.Proxy.NETCoreApp.csproj", "{1995E414-F197-4AB4-90C2-68D806B5AF59}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.StandAlone.NETCoreApp", "examples\WireMock.Net.StandAlone.NETCoreApp\WireMock.Net.StandAlone.NETCoreApp.csproj", "{10E16614-61CA-48D8-8BDD-664C13913DED}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net452", "examples\WireMock.Net.StandAlone.Net452\WireMock.Net.StandAlone.Net452.csproj", "{668F689E-57B4-422E-8846-C0FF643CA999}"
@@ -101,6 +99,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET6",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NET6", "examples\WireMock.Net.WebApplication.NET6\WireMock.Net.WebApplication.NET6.csproj", "{3F7AA023-6833-4856-A08A-4B5717B592B8}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.NETCoreApp", "examples\WireMock.Net.Console.Proxy.NETCoreApp\WireMock.Net.Console.Proxy.NETCoreApp.csproj", "{670C7562-C154-442E-A249-7D26849BCD13}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -143,10 +143,6 @@ Global
{FE281639-B014-4C8A-96FA-141164A74713}.Debug|Any CPU.Build.0 = Debug|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.ActiveCfg = Release|Any CPU
{FE281639-B014-4C8A-96FA-141164A74713}.Release|Any CPU.Build.0 = Release|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1995E414-F197-4AB4-90C2-68D806B5AF59}.Release|Any CPU.Build.0 = Release|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Debug|Any CPU.Build.0 = Debug|Any CPU
{10E16614-61CA-48D8-8BDD-664C13913DED}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -239,6 +235,10 @@ Global
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.Build.0 = Release|Any CPU
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
{670C7562-C154-442E-A249-7D26849BCD13}.Release|Any CPU.ActiveCfg = Release|Any CPU
{670C7562-C154-442E-A249-7D26849BCD13}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -253,7 +253,6 @@ Global
{41C19451-E980-4ED4-A011-DA7A1C23FC05} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{FE281639-B014-4C8A-96FA-141164A74713} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{1995E414-F197-4AB4-90C2-68D806B5AF59} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{10E16614-61CA-48D8-8BDD-664C13913DED} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{668F689E-57B4-422E-8846-C0FF643CA999} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{26433A8F-BF01-4962-97EB-81BFFBB61096} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
@@ -279,6 +278,7 @@ Global
{3BA5109E-5F30-4CC2-B699-02EC82560AA6} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{2215055B-594E-4C2F-99B2-6DF337F02893} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{3F7AA023-6833-4856-A08A-4B5717B592B8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}

View File

@@ -0,0 +1,169 @@
{
"Guid": "501d5907-7f73-46dc-a1c6-1a48f39b103a",
"Title": "",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/post",
"IgnoreCase": false
}
]
},
"Methods": [
"POST"
],
"Headers": [
{
"Name": "Accept",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "*/*",
"IgnoreCase": true
}
]
},
{
"Name": "Connection",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "keep-alive",
"IgnoreCase": true
}
]
},
{
"Name": "Host",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "localhost:9091",
"IgnoreCase": true
}
]
},
{
"Name": "User-Agent",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "PostmanRuntime/7.29.0",
"IgnoreCase": true
}
]
},
{
"Name": "Accept-Encoding",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "gzip, deflate, br",
"IgnoreCase": true
}
]
},
{
"Name": "Authorization",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "BASIC 1234",
"IgnoreCase": true
}
]
},
{
"Name": "Content-Type",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "application/vnd.contoso+json",
"IgnoreCase": true
}
]
},
{
"Name": "Content-Length",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "16",
"IgnoreCase": true
}
]
},
{
"Name": "postmanecho",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "post",
"IgnoreCase": true
}
]
},
{
"Name": "Test123",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "application/vnd.contoso+json",
"IgnoreCase": true
}
]
}
],
"Body": {
"Matcher": {
"Name": "JsonMatcher",
"Pattern": {
"test": 42
},
"IgnoreCase": true
}
}
},
"Response": {
"StatusCode": 200,
"BodyAsJson": {
"args": {},
"data": {
"test": "Stef"
},
"files": {},
"form": {},
"headers": {
"x-forwarded-proto": "http",
"x-forwarded-port": "80",
"host": "postman-echo.com",
"x-amzn-trace-id": "Root=1-624a96e3-023cf5a15966164e7156c20d",
"content-length": "11",
"accept": "*/*",
"user-agent": "PostmanRuntime/7.29.0",
"accept-encoding": "gzip, deflate, br",
"authorization": "BASIC 1234",
"cookie": "sails.sid=s%3AMpD3hNdjm1Ilte_ml7vgmEopThEhwAbr.HDn7RFcO3qK7oVXIxK3Pxk23g1qHDrNZIN4NozK5oog",
"postmanecho": "post",
"test123": "application/vnd.contoso+json",
"postman-token": "050b1136-19ed-4fbe-ad2a-338a20237321",
"content-type": "application/vnd.contoso+json"
},
"json": {
"test": "Stef"
},
"url": "http://postman-echo.com/post"
},
"Headers": {
"Content-Type": "application/json; charset=utf-8",
"Content-Length": "663",
"Date": "Mon, 04 Apr 2022 06:57:39 GMT",
"Connection": "keep-alive",
"ETag": "W/\"297-FimzXopdNUy6DBi49iOW6Tm9q0o\"",
"Vary": "Accept-Encoding",
"Set-Cookie": "sails.sid=s%3AhtpOsTOJqbHuXmMAZT6cyHLR6FBx1XhV.0loKIsdu5GJKgjJeha16NVWYl%2B0BvPeEQYHcLBCLJ20; Path=/; HttpOnly"
}
}
}

View File

@@ -0,0 +1,53 @@
using Newtonsoft.Json;
using WireMock.Logging;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.Console.Proxy.NETCoreApp;
static class Program
{
static void Main(params string[] args)
{
var server = WireMockServer.Start(new WireMockServerSettings
{
Logger = new WireMockConsoleLogger(),
Urls = new[] { "http://localhost:9091/", "https://localhost:9443/" },
StartAdminInterface = true,
ReadStaticMappings = true,
WatchStaticMappings = true,
WatchStaticMappingsInSubdirectories = true,
ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = "http://postman-echo.com/post",
SaveMapping = true,
SaveMappingToFile = true,
ExcludedHeaders = new[] { "Postman-Token" },
ExcludedCookies = new[] { "sails.sid" }
}
});
//server
// .Given(Request.Create().UsingGet())
// .RespondWith(Response.Create()
// .WithProxy(new ProxyAndRecordSettings
// {
// Url = "http://postman-echo.com/post",
// SaveMapping = true,
// SaveMappingToFile = true
// }));
System.Console.WriteLine("Press any key to stop the server");
System.Console.ReadKey();
server.Stop();
System.Console.WriteLine("Displaying all requests");
var allRequests = server.LogEntries;
System.Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented));
System.Console.WriteLine("Press any key to quit");
System.Console.ReadKey();
}
}

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net5.0</TargetFramework>
<TargetFramework>net6.0</TargetFramework>
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup>

View File

@@ -1,50 +0,0 @@
using Newtonsoft.Json;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.Console.Proxy.NETCoreApp
{
static class Program
{
static void Main(params string[] args)
{
var server = WireMockServer.Start(new WireMockServerSettings
{
Urls = new[] { "http://localhost:9091/", "https://localhost:9443/" },
StartAdminInterface = true,
ReadStaticMappings = false,
//ProxyAndRecordSettings = new ProxyAndRecordSettings
//{
// Url = "https://www.google.com",
// //ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
// SaveMapping = true,
// SaveMappingToFile = false,
// ExcludedHeaders = new [] { "dnt", "Content-Length" }
//}
});
server
.Given(Request.Create().UsingGet())
.RespondWith(Response.Create()
.WithProxy(new ProxyAndRecordSettings
{
Url = "http://postman-echo.com/post",
SaveMapping = true,
SaveMappingToFile = true
}));
System.Console.WriteLine("Press any key to stop the server");
System.Console.ReadKey();
server.Stop();
System.Console.WriteLine("Displaying all requests");
var allRequests = server.LogEntries;
System.Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented));
System.Console.WriteLine("Press any key to quit");
System.Console.ReadKey();
}
}
}

View File

@@ -1,28 +1,27 @@
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Hosting;
using System.Threading;
using System.Threading.Tasks;
namespace WireMock.Net.WebApplication
namespace WireMock.Net.WebApplication;
public class App : IHostedService
{
public class App : IHostedService
{
private readonly IWireMockService _service;
private readonly IWireMockService _service;
public App(IWireMockService service)
{
_service = service;
}
public App(IWireMockService service)
{
_service = service;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_service.Start();
return Task.CompletedTask;
}
public Task StartAsync(CancellationToken cancellationToken)
{
_service.Start();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_service.Stop();
return Task.CompletedTask;
}
public Task StopAsync(CancellationToken cancellationToken)
{
_service.Stop();
return Task.CompletedTask;
}
}

View File

@@ -1,9 +1,8 @@
namespace WireMock.Net.WebApplication
{
public interface IWireMockService
{
void Start();
namespace WireMock.Net.WebApplication;
void Stop();
}
public interface IWireMockService
{
void Start();
void Stop();
}

View File

@@ -1,30 +1,29 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using WireMock.Settings;
namespace WireMock.Net.WebApplication
namespace WireMock.Net.WebApplication;
public class Program
{
public class Program
public static void Main(string[] args)
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
CreateHostBuilder(args).Build().Run();
}
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureServices((host, services) => ConfigureServices(services, host.Configuration));
private static IHostBuilder CreateHostBuilder(string[] args)
=> Host.CreateDefaultBuilder(args)
.ConfigureServices((host, services) => ConfigureServices(services, host.Configuration));
private static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddLogging(logging => logging.AddConsole().AddDebug());
private static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
{
services.AddLogging(logging => logging.AddConsole().AddDebug());
services.AddTransient<IWireMockService, WireMockService>();
services.Configure<WireMockServerSettings>(configuration.GetSection("WireMockServerSettings"));
services.AddTransient<IWireMockService, WireMockService>();
services.Configure<WireMockServerSettings>(configuration.GetSection("WireMockServerSettings"));
services.AddHostedService<App>();
}
services.AddHostedService<App>();
}
}

View File

@@ -1,83 +1,81 @@
using System;
using System;
using Microsoft.Extensions.Logging;
using Microsoft.Extensions.Options;
using Newtonsoft.Json;
using WireMock.Admin.Requests;
using WireMock.Logging;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.WebApplication
namespace WireMock.Net.WebApplication;
public class WireMockService : IWireMockService
{
public class WireMockService : IWireMockService
private WireMockServer? _server;
private readonly ILogger _logger;
private readonly WireMockServerSettings _settings;
private class Logger : IWireMockLogger
{
private WireMockServer _server;
private readonly ILogger _logger;
private readonly WireMockServerSettings _settings;
private class Logger : IWireMockLogger
{
private readonly ILogger _logger;
public Logger(ILogger logger)
{
_logger = logger;
}
public void Debug(string formatString, params object[] args)
{
_logger.LogDebug(formatString, args);
}
public void Info(string formatString, params object[] args)
{
_logger.LogInformation(formatString, args);
}
public void Warn(string formatString, params object[] args)
{
_logger.LogWarning(formatString, args);
}
public void Error(string formatString, params object[] args)
{
_logger.LogError(formatString, args);
}
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminrequest)
{
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
_logger.LogDebug("Admin[{0}] {1}", isAdminrequest, message);
}
public void Error(string formatString, Exception exception)
{
_logger.LogError(formatString, exception.Message);
}
}
public WireMockService(ILogger<WireMockService> logger, IOptions<WireMockServerSettings> settings)
public Logger(ILogger logger)
{
_logger = logger;
_settings = settings.Value;
_settings.Logger = new Logger(logger);
}
public void Start()
public void Debug(string formatString, params object[] args)
{
_logger.LogInformation("WireMock.Net server starting");
_server = WireMockServer.Start(_settings);
_logger.LogInformation($"WireMock.Net server settings {JsonConvert.SerializeObject(_settings)}");
_logger.LogDebug(formatString, args);
}
public void Stop()
public void Info(string formatString, params object[] args)
{
_logger.LogInformation("WireMock.Net server stopping");
_server?.Stop();
_logger.LogInformation(formatString, args);
}
public void Warn(string formatString, params object[] args)
{
_logger.LogWarning(formatString, args);
}
public void Error(string formatString, params object[] args)
{
_logger.LogError(formatString, args);
}
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminrequest)
{
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
_logger.LogDebug("Admin[{0}] {1}", isAdminrequest, message);
}
public void Error(string formatString, Exception exception)
{
_logger.LogError(formatString, exception.Message);
}
}
}
public WireMockService(ILogger<WireMockService> logger, IOptions<WireMockServerSettings> settings)
{
_logger = logger;
_settings = settings.Value;
_settings.Logger = new Logger(logger);
}
public void Start()
{
_logger.LogInformation("WireMock.Net server starting");
_server = WireMockServer.Start(_settings);
_logger.LogInformation($"WireMock.Net server settings {JsonConvert.SerializeObject(_settings)}");
}
public void Stop()
{
_logger.LogInformation("WireMock.Net server stopping");
_server?.Stop();
}
}

View File

@@ -1,29 +1,29 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Debug"
}
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"LogLevel": {
"Default": "Debug"
}
},
"Console": {
"LogLevel": {
"Default": "Debug"
}
}
},
"Console": {
"LogLevel": {
"Default": "Debug"
}
"WireMockServerSettings": {
"StartAdminInterface": true,
"Urls": [
"https://localhost:8081/"
],
"AllowPartialMapping": false,
"HandleRequestsSynchronously": true,
"ThrowExceptionWhenMatcherFails": true,
"ProxyAndRecordSettings": {
"Url": "http://postman-echo.com/post",
"SaveMapping": true,
"SaveMappingToFile": true
}
}
},
"WireMockServerSettings": {
"StartAdminInterface": true,
"Urls": [
"https://localhost:8081/"
],
"AllowPartialMapping": false,
"HandleRequestsSynchronously": true,
"ThrowExceptionWhenMatcherFails": true,
"ProxyAndRecordSettings": {
"Url": "https://support.smartbear.com/",
"SaveMapping": true,
"SaveMappingToFile": true
}
}
}

View File

@@ -2,13 +2,9 @@
"iisSettings": {
"windowsAuthentication": false,
"anonymousAuthentication": true,
"iis": {
"applicationUrl": "http://localhost//wiremock",
"sslPort": 0
},
"iisExpress": {
"applicationUrl": "http://localhost:56513/",
"sslPort": 0
"applicationUrl": "http://localhost:60097/",
"sslPort": 44321
}
},
"profiles": {

View File

@@ -1,8 +1,8 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>netcoreapp3.1</TargetFramework>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
<!--<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>-->
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
<RootNamespace>WireMock.Net.WebApplication</RootNamespace>

View File

@@ -25,7 +25,7 @@ namespace WireMock.Admin.Mappings
public string Title { get; set; }
/// <summary>
/// The priority.
/// The priority. (A low value means higher priority.)
/// </summary>
public int? Priority { get; set; }

View File

@@ -0,0 +1,59 @@
using JetBrains.Annotations;
namespace WireMock.Admin.Settings;
[FluentBuilder.AutoGenerateBuilder]
public class ProxyAndRecordSettingsModel
{
/// <summary>
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
public string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettingsModel WebProxySettings { get; set; }
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
/// <summary>
/// The URL to proxy.
/// </summary>
public string Url { get; set; }
/// <summary>
/// Save the mapping for each request/response to the internal Mappings.
/// </summary>
public bool SaveMapping { get; set; }
/// <summary>
/// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.)
/// </summary>
public bool SaveMappingToFile { get; set; }
/// <summary>
/// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.)
/// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported.
/// </summary>
public string SaveMappingForStatusCodePattern { get; set; } = "*";
/// <summary>
/// Defines a list from headers which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedHeaders { get; set; }
/// <summary>
/// Defines a list of cookies which will be excluded from the saved mappings.
/// </summary>
public string[] ExcludedCookies { get; set; }
/// <summary>
/// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to <c>true</c>).
/// </summary>
// public bool PreferProxyMapping { get; set; }
}

View File

@@ -1,6 +1,6 @@
using System.Text.RegularExpressions;
using JetBrains.Annotations;
using WireMock.Handlers;
using WireMock.Types;
namespace WireMock.Admin.Settings
{
@@ -55,9 +55,29 @@ namespace WireMock.Admin.Settings
/// </summary>
public bool? SaveUnmatchedRequests { get; set; }
/// <summary>
/// Gets or sets if the static mappings should be read at startup.
/// </summary>
public bool? ReadStaticMappings { get; set; }
/// <summary>
/// Watch the static mapping files + folder for changes when running.
/// </summary>
public bool? WatchStaticMappings { get; set; }
/// <summary>
/// A value indicating whether subdirectories within the static mappings path should be monitored.
/// </summary>
public bool? WatchStaticMappingsInSubdirectories { get; set; }
/// <summary>
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
/// </summary>
public string CorsPolicyOptions { get; set; }
/// <summary>
/// The proxy and record settings.
/// </summary>
public ProxyAndRecordSettingsModel ProxyAndRecordSettings { get; set; }
}
}

View File

@@ -0,0 +1,24 @@
namespace WireMock.Admin.Settings
{
/// <summary>
/// WebProxySettings
/// </summary>
[FluentBuilder.AutoGenerateBuilder]
public class WebProxySettingsModel
{
/// <summary>
/// A string instance that contains the address of the proxy server.
/// </summary>
public string Address { get; set; }
/// <summary>
/// The user name associated with the credentials.
/// </summary>
public string UserName { get; set; }
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
public string Password { get; set; }
}
}

View File

@@ -41,4 +41,11 @@
</PackageReference>
</ItemGroup>
<!--<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
<PackageReference Include="Nullable" Version="1.2.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>-->
</Project>

View File

@@ -0,0 +1,9 @@
namespace WireMock.Constants
{
internal static class WireMockConstants
{
public const int AdminPriority = int.MinValue;
public const int MinPriority = -1_000_000;
public const int ProxyPriority = -2_000_000;
}
}

View File

@@ -34,7 +34,7 @@ namespace WireMock
string Path { get; set; }
/// <summary>
/// Gets the priority.
/// Gets the priority. (A low value means higher priority.)
/// </summary>
int Priority { get; }
@@ -91,6 +91,14 @@ namespace WireMock
/// </value>
bool IsAdminInterface { get; }
/// <summary>
/// Gets a value indicating whether this mapping is a Proxy Mapping.
/// </summary>
/// <value>
/// <c>true</c> if this mapping is a Proxy Mapping; otherwise, <c>false</c>.
/// </value>
bool IsProxy { get; }
/// <summary>
/// Gets a value indicating whether this mapping to be logged.
/// </summary>

View File

@@ -52,6 +52,9 @@ namespace WireMock
/// <inheritdoc />
public bool IsAdminInterface => Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider || Provider is ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool IsProxy => Provider is ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool LogMapping => !(Provider is DynamicResponseProvider || Provider is DynamicAsyncResponseProvider);

View File

@@ -1,4 +1,4 @@
using System;
using System;
namespace WireMock.ResponseBuilders
{
@@ -8,14 +8,14 @@ namespace WireMock.ResponseBuilders
public interface IDelayResponseBuilder : ICallbackResponseBuilder
{
/// <summary>
/// The with delay.
/// The delay defined as a <see cref="TimeSpan"/>.
/// </summary>
/// <param name="delay">The TimeSpan to delay.</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithDelay(TimeSpan delay);
/// <summary>
/// The with delay.
/// The delay defined as milliseconds.
/// </summary>
/// <param name="milliseconds">The milliseconds to delay.</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>

View File

@@ -346,9 +346,7 @@ namespace WireMock.ResponseBuilders
return WithTransformer(TransformerType.Handlebars, false, options);
}
#pragma warning disable CS1574
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(TransformerType, bool, ReplaceNodeOptions)"/>
#pragma warning restore CS1574
/// <inheritdoc />
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.None)
{
UseTransformer = true;
@@ -358,26 +356,26 @@ namespace WireMock.ResponseBuilders
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(TimeSpan)"/>
/// <inheritdoc />
public IResponseBuilder WithDelay(TimeSpan delay)
{
Guard.Condition(delay, d => d > TimeSpan.Zero, nameof(delay));
Guard.Condition(delay, d => d == Timeout.InfiniteTimeSpan || d > TimeSpan.Zero);
Delay = delay;
return this;
}
/// <inheritdoc cref="IDelayResponseBuilder.WithDelay(int)"/>
/// <inheritdoc />
public IResponseBuilder WithDelay(int milliseconds)
{
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
}
/// <inheritdoc cref="IDelayResponseBuilder.WithRandomDelay(int, int)"/>
/// <inheritdoc />
public IResponseBuilder WithRandomDelay(int minimumMilliseconds = 0, int maximumMilliseconds = 60_000)
{
Guard.Condition(minimumMilliseconds, min => min >= 0, nameof(minimumMilliseconds));
Guard.Condition(maximumMilliseconds, max => max > minimumMilliseconds, nameof(maximumMilliseconds));
Guard.Condition(minimumMilliseconds, min => min >= 0);
Guard.Condition(maximumMilliseconds, max => max > minimumMilliseconds);
MinimumDelayMilliseconds = minimumMilliseconds;
MaximumDelayMilliseconds = maximumMilliseconds;

View File

@@ -1,5 +1,7 @@
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading;
using Stef.Validation;
using WireMock.Admin.Mappings;
using WireMock.Matchers.Request;
@@ -90,7 +92,7 @@ namespace WireMock.Serialization
}
else
{
mappingModel.Response.Delay = (int?)response.Delay?.TotalMilliseconds;
mappingModel.Response.Delay = (int?)(response.Delay == Timeout.InfiniteTimeSpan ? TimeSpan.MaxValue.TotalMilliseconds : response.Delay?.TotalMilliseconds);
}
if (mapping.Webhooks?.Length == 1)

View File

@@ -1,5 +1,6 @@
using System.IO;
using System.IO;
using System.Linq;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Settings;
using Stef.Validation;
@@ -13,13 +14,14 @@ namespace WireMock.Serialization
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
{
Guard.NotNull(settings, nameof(settings));
Guard.NotNull(settings);
Guard.NotNull(mappingConverter);
_settings = settings;
_mappingConverter = mappingConverter;
}
public void SaveMappingToFile(IMapping mapping, string folder = null)
public void SaveMappingToFile(IMapping mapping, [CanBeNull] string folder = null)
{
if (folder == null)
{

View File

@@ -10,6 +10,7 @@ using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
using Stef.Validation;
using WireMock.Constants;
namespace WireMock.Server
{

File diff suppressed because it is too large Load Diff

View File

@@ -20,511 +20,512 @@ using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
namespace WireMock.Server
namespace WireMock.Server;
/// <summary>
/// The fluent mock server.
/// </summary>
public partial class WireMockServer : IWireMockServer
{
private const int ServerStartDelayInMs = 100;
private readonly WireMockServerSettings _settings;
private readonly IOwinSelfHost _httpServer;
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
private readonly MappingConverter _mappingConverter;
private readonly MatcherMapper _matcherMapper;
private readonly MappingToFileSaver _mappingToFileSaver;
/// <inheritdoc cref="IWireMockServer.IsStarted" />
[PublicAPI]
public bool IsStarted => _httpServer != null && _httpServer.IsStarted;
/// <inheritdoc />
[PublicAPI]
public List<int> Ports { get; }
/// <inheritdoc />
[PublicAPI]
public int Port => Ports?.FirstOrDefault() ?? default(int);
/// <inheritdoc />
[PublicAPI]
public string[] Urls { get; }
/// <inheritdoc />
[PublicAPI]
public string Url => Urls?.FirstOrDefault();
/// <summary>
/// The fluent mock server.
/// Gets the mappings.
/// </summary>
public partial class WireMockServer : IWireMockServer
[PublicAPI]
public IEnumerable<IMapping> Mappings => _options.Mappings.Values.ToArray();
/// <inheritdoc cref="IWireMockServer.MappingModels" />
[PublicAPI]
public IEnumerable<MappingModel> MappingModels => ToMappingModels();
/// <summary>
/// Gets the scenarios.
/// </summary>
[PublicAPI]
public ConcurrentDictionary<string, ScenarioState> Scenarios => new ConcurrentDictionary<string, ScenarioState>(_options.Scenarios);
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
{
private const int ServerStartDelayInMs = 100;
Dispose(true);
GC.SuppressFinalize(this);
}
private readonly WireMockServerSettings _settings;
private readonly IOwinSelfHost _httpServer;
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
private readonly MappingConverter _mappingConverter;
private readonly MatcherMapper _matcherMapper;
private readonly MappingToFileSaver _mappingToFileSaver;
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
DisposeEnhancedFileSystemWatcher();
_httpServer?.StopAsync();
}
#endregion
/// <inheritdoc cref="IWireMockServer.IsStarted" />
[PublicAPI]
public bool IsStarted => _httpServer != null && _httpServer.IsStarted;
#region Start/Stop
/// <summary>
/// Starts this WireMockServer with the specified settings.
/// </summary>
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([NotNull] WireMockServerSettings settings)
{
Guard.NotNull(settings, nameof(settings));
/// <inheritdoc />
[PublicAPI]
public List<int> Ports { get; }
return new WireMockServer(settings);
}
/// <inheritdoc />
[PublicAPI]
public int Port => Ports?.FirstOrDefault() ?? default(int);
/// <inheritdoc />
[PublicAPI]
public string[] Urls { get; }
/// <inheritdoc />
[PublicAPI]
public string Url => Urls?.FirstOrDefault();
/// <summary>
/// Gets the mappings.
/// </summary>
[PublicAPI]
public IEnumerable<IMapping> Mappings => _options.Mappings.Values.ToArray();
/// <inheritdoc cref="IWireMockServer.MappingModels" />
[PublicAPI]
public IEnumerable<MappingModel> MappingModels => ToMappingModels();
/// <summary>
/// Gets the scenarios.
/// </summary>
[PublicAPI]
public ConcurrentDictionary<string, ScenarioState> Scenarios => new ConcurrentDictionary<string, ScenarioState>(_options.Scenarios);
#region IDisposable Members
/// <summary>
/// Performs application-defined tasks associated with freeing, releasing, or resetting unmanaged resources.
/// </summary>
public void Dispose()
/// <summary>
/// Start this WireMockServer.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([CanBeNull] int? port = 0, bool ssl = false)
{
return new WireMockServer(new WireMockServerSettings
{
Dispose(true);
GC.SuppressFinalize(this);
Port = port,
UseSSL = ssl
});
}
/// <summary>
/// Start this WireMockServer.
/// </summary>
/// <param name="urls">The urls to listen on.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls
});
}
/// <summary>
/// Start this WireMockServer with the admin interface.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterface(int? port = 0, bool ssl = false)
{
return new WireMockServer(new WireMockServerSettings
{
Port = port,
UseSSL = ssl,
StartAdminInterface = true
});
}
/// <summary>
/// Start this WireMockServer with the admin interface.
/// </summary>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterface(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls,
StartAdminInterface = true
});
}
/// <summary>
/// Start this WireMockServer with the admin interface and read static mappings.
/// </summary>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterfaceAndReadStaticMappings(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls,
StartAdminInterface = true,
ReadStaticMappings = true
});
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockServer"/> class.
/// </summary>
/// <param name="settings">The settings.</param>
/// <exception cref="WireMockException">
/// Service start failed with error: {_httpServer.RunningException.Message}
/// or
/// Service start failed with error: {startTask.Exception.Message}
/// </exception>
/// <exception cref="TimeoutException">Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}</exception>
protected WireMockServer(WireMockServerSettings settings)
{
_settings = settings;
// Set default values if not provided
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
_settings.Logger.Info("By Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
_settings.Logger.Debug("Server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
HostUrlOptions urlOptions;
if (settings.Urls != null)
{
urlOptions = new HostUrlOptions
{
Urls = settings.Urls
};
}
else
{
urlOptions = new HostUrlOptions
{
UseSSL = settings.UseSSL == true,
Port = settings.Port
};
}
/// <summary>
/// Releases unmanaged and - optionally - managed resources.
/// </summary>
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
protected virtual void Dispose(bool disposing)
{
DisposeEnhancedFileSystemWatcher();
_httpServer?.StopAsync();
}
#endregion
_options.FileSystemHandler = _settings.FileSystemHandler;
_options.PreWireMockMiddlewareInit = _settings.PreWireMockMiddlewareInit;
_options.PostWireMockMiddlewareInit = _settings.PostWireMockMiddlewareInit;
_options.Logger = _settings.Logger;
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
_options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
#region Start/Stop
/// <summary>
/// Starts this WireMockServer with the specified settings.
/// </summary>
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([NotNull] WireMockServerSettings settings)
if (settings.CustomCertificateDefined)
{
Guard.NotNull(settings, nameof(settings));
return new WireMockServer(settings);
_options.X509StoreName = settings.CertificateSettings.X509StoreName;
_options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
_options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
_options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
_options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
}
/// <summary>
/// Start this WireMockServer.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start([CanBeNull] int? port = 0, bool ssl = false)
{
return new WireMockServer(new WireMockServerSettings
{
Port = port,
UseSSL = ssl
});
}
/// <summary>
/// Start this WireMockServer.
/// </summary>
/// <param name="urls">The urls to listen on.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer Start(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls
});
}
/// <summary>
/// Start this WireMockServer with the admin interface.
/// </summary>
/// <param name="port">The port.</param>
/// <param name="ssl">The SSL support.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterface(int? port = 0, bool ssl = false)
{
return new WireMockServer(new WireMockServerSettings
{
Port = port,
UseSSL = ssl,
StartAdminInterface = true
});
}
/// <summary>
/// Start this WireMockServer with the admin interface.
/// </summary>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterface(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls,
StartAdminInterface = true
});
}
/// <summary>
/// Start this WireMockServer with the admin interface and read static mappings.
/// </summary>
/// <param name="urls">The urls.</param>
/// <returns>The <see cref="WireMockServer"/>.</returns>
[PublicAPI]
public static WireMockServer StartWithAdminInterfaceAndReadStaticMappings(params string[] urls)
{
Guard.NotNullOrEmpty(urls, nameof(urls));
return new WireMockServer(new WireMockServerSettings
{
Urls = urls,
StartAdminInterface = true,
ReadStaticMappings = true
});
}
/// <summary>
/// Initializes a new instance of the <see cref="WireMockServer"/> class.
/// </summary>
/// <param name="settings">The settings.</param>
/// <exception cref="WireMockException">
/// Service start failed with error: {_httpServer.RunningException.Message}
/// or
/// Service start failed with error: {startTask.Exception.Message}
/// </exception>
/// <exception cref="TimeoutException">Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}</exception>
protected WireMockServer(WireMockServerSettings settings)
{
_settings = settings;
// Set default values if not provided
_settings.Logger = settings.Logger ?? new WireMockNullLogger();
_settings.FileSystemHandler = settings.FileSystemHandler ?? new LocalFileSystemHandler();
_settings.Logger.Info("By Stef Heyenrath (https://github.com/WireMock-Net/WireMock.Net)");
_settings.Logger.Debug("Server settings {0}", JsonConvert.SerializeObject(settings, Formatting.Indented));
HostUrlOptions urlOptions;
if (settings.Urls != null)
{
urlOptions = new HostUrlOptions
{
Urls = settings.Urls
};
}
else
{
urlOptions = new HostUrlOptions
{
UseSSL = settings.UseSSL == true,
Port = settings.Port
};
}
_options.FileSystemHandler = _settings.FileSystemHandler;
_options.PreWireMockMiddlewareInit = _settings.PreWireMockMiddlewareInit;
_options.PostWireMockMiddlewareInit = _settings.PostWireMockMiddlewareInit;
_options.Logger = _settings.Logger;
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
_options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
if (settings.CustomCertificateDefined)
{
_options.X509StoreName = settings.CertificateSettings.X509StoreName;
_options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
_options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
_options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
_options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
}
_matcherMapper = new MatcherMapper(_settings);
_mappingConverter = new MappingConverter(_matcherMapper);
_mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter);
_matcherMapper = new MatcherMapper(_settings);
_mappingConverter = new MappingConverter(_matcherMapper);
_mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter);
#if USE_ASPNETCORE
_options.AdditionalServiceRegistration = _settings.AdditionalServiceRegistration;
_options.CorsPolicyOptions = _settings.CorsPolicyOptions;
_options.AdditionalServiceRegistration = _settings.AdditionalServiceRegistration;
_options.CorsPolicyOptions = _settings.CorsPolicyOptions;
_httpServer = new AspNetCoreSelfHost(_options, urlOptions);
_httpServer = new AspNetCoreSelfHost(_options, urlOptions);
#else
_httpServer = new OwinSelfHost(_options, urlOptions);
_httpServer = new OwinSelfHost(_options, urlOptions);
#endif
var startTask = _httpServer.StartAsync();
var startTask = _httpServer.StartAsync();
using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout))
using (var ctsStartTimeout = new CancellationTokenSource(settings.StartTimeout))
{
while (!_httpServer.IsStarted)
{
while (!_httpServer.IsStarted)
// Throw exception if service start fails
if (_httpServer.RunningException != null)
{
// Throw exception if service start fails
if (_httpServer.RunningException != null)
throw new WireMockException($"Service start failed with error: {_httpServer.RunningException.Message}", _httpServer.RunningException);
}
if (ctsStartTimeout.IsCancellationRequested)
{
// In case of an aggregate exception, throw the exception.
if (startTask.Exception != null)
{
throw new WireMockException($"Service start failed with error: {_httpServer.RunningException.Message}", _httpServer.RunningException);
throw new WireMockException($"Service start failed with error: {startTask.Exception.Message}", startTask.Exception);
}
if (ctsStartTimeout.IsCancellationRequested)
{
// In case of an aggregate exception, throw the exception.
if (startTask.Exception != null)
{
throw new WireMockException($"Service start failed with error: {startTask.Exception.Message}", startTask.Exception);
}
// Else throw TimeoutException
throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}");
}
ctsStartTimeout.Token.WaitHandle.WaitOne(ServerStartDelayInMs);
// Else throw TimeoutException
throw new TimeoutException($"Service start timed out after {TimeSpan.FromMilliseconds(settings.StartTimeout)}");
}
Urls = _httpServer.Urls.ToArray();
Ports = _httpServer.Ports;
ctsStartTimeout.Token.WaitHandle.WaitOne(ServerStartDelayInMs);
}
if (settings.AllowBodyForAllHttpMethods == true)
{
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to True");
}
if (settings.AllowOnlyDefinedHttpStatusCodeInResponse == true)
{
_options.AllowOnlyDefinedHttpStatusCodeInResponse = _settings.AllowOnlyDefinedHttpStatusCodeInResponse;
_settings.Logger.Info("AllowOnlyDefinedHttpStatusCodeInResponse is set to True");
}
if (settings.AllowPartialMapping == true)
{
AllowPartialMapping();
}
if (settings.StartAdminInterface == true)
{
if (!string.IsNullOrEmpty(settings.AdminUsername) && !string.IsNullOrEmpty(settings.AdminPassword))
{
SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword);
}
if (!string.IsNullOrEmpty(settings.AdminAzureADTenant) && !string.IsNullOrEmpty(settings.AdminAzureADAudience))
{
SetAzureADAuthentication(settings.AdminAzureADTenant, settings.AdminAzureADAudience);
}
InitAdmin();
}
if (settings.ReadStaticMappings == true)
{
ReadStaticMappings();
}
if (settings.WatchStaticMappings == true)
{
WatchStaticMappings();
}
if (settings.ProxyAndRecordSettings != null)
{
InitProxyAndRecord(settings);
}
if (settings.RequestLogExpirationDuration != null)
{
SetRequestLogExpirationDuration(settings.RequestLogExpirationDuration);
}
if (settings.MaxRequestLogCount != null)
{
SetMaxRequestLogCount(settings.MaxRequestLogCount);
}
Urls = _httpServer.Urls.ToArray();
Ports = _httpServer.Ports;
}
/// <inheritdoc cref="IWireMockServer.Stop" />
[PublicAPI]
public void Stop()
{
var result = _httpServer?.StopAsync();
result?.Wait(); // wait for stop to actually happen
}
#endregion
InitSettings(settings);
}
/// <inheritdoc cref="IWireMockServer.AddCatchAllMapping" />
[PublicAPI]
public void AddCatchAllMapping()
/// <inheritdoc cref="IWireMockServer.Stop" />
[PublicAPI]
public void Stop()
{
var result = _httpServer?.StopAsync();
result?.Wait(); // wait for stop to actually happen
}
#endregion
/// <inheritdoc cref="IWireMockServer.AddCatchAllMapping" />
[PublicAPI]
public void AddCatchAllMapping()
{
Given(Request.Create().WithPath("/*").UsingAnyMethod())
.WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
.AtPriority(1000)
.RespondWith(new DynamicResponseProvider(request => ResponseMessageBuilder.Create("No matching mapping found", 404)));
}
/// <inheritdoc cref="IWireMockServer.Reset" />
[PublicAPI]
public void Reset()
{
ResetLogEntries();
ResetMappings();
}
/// <inheritdoc cref="IWireMockServer.ResetMappings" />
[PublicAPI]
public void ResetMappings()
{
foreach (var nonAdmin in _options.Mappings.ToArray().Where(m => !m.Value.IsAdminInterface))
{
Given(Request.Create().WithPath("/*").UsingAnyMethod())
.WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
.AtPriority(1000)
.RespondWith(new DynamicResponseProvider(request => ResponseMessageBuilder.Create("No matching mapping found", 404)));
_options.Mappings.TryRemove(nonAdmin.Key, out _);
}
}
/// <inheritdoc cref="IWireMockServer.DeleteMapping" />
[PublicAPI]
public bool DeleteMapping(Guid guid)
{
// Check a mapping exists with the same GUID, if so, remove it.
if (_options.Mappings.ContainsKey(guid))
{
return _options.Mappings.TryRemove(guid, out _);
}
/// <inheritdoc cref="IWireMockServer.Reset" />
[PublicAPI]
public void Reset()
{
ResetLogEntries();
return false;
}
ResetMappings();
}
private bool DeleteMapping(string path)
{
// Check a mapping exists with the same path, if so, remove it.
var mapping = _options.Mappings.ToArray().FirstOrDefault(entry => string.Equals(entry.Value.Path, path, StringComparison.OrdinalIgnoreCase));
return DeleteMapping(mapping.Key);
}
/// <inheritdoc cref="IWireMockServer.ResetMappings" />
[PublicAPI]
public void ResetMappings()
{
foreach (var nonAdmin in _options.Mappings.ToArray().Where(m => !m.Value.IsAdminInterface))
{
_options.Mappings.TryRemove(nonAdmin.Key, out _);
}
}
/// <inheritdoc cref="IWireMockServer.AddGlobalProcessingDelay" />
[PublicAPI]
public void AddGlobalProcessingDelay(TimeSpan delay)
{
_options.RequestProcessingDelay = delay;
}
/// <inheritdoc cref="IWireMockServer.DeleteMapping" />
[PublicAPI]
public bool DeleteMapping(Guid guid)
{
// Check a mapping exists with the same GUID, if so, remove it.
if (_options.Mappings.ContainsKey(guid))
{
return _options.Mappings.TryRemove(guid, out _);
}
/// <inheritdoc cref="IWireMockServer.AllowPartialMapping" />
[PublicAPI]
public void AllowPartialMapping(bool allow = true)
{
_settings.Logger.Info("AllowPartialMapping is set to {0}", allow);
_options.AllowPartialMapping = allow;
}
return false;
}
private bool DeleteMapping(string path)
{
// Check a mapping exists with the same path, if so, remove it.
var mapping = _options.Mappings.ToArray().FirstOrDefault(entry => string.Equals(entry.Value.Path, path, StringComparison.OrdinalIgnoreCase));
return DeleteMapping(mapping.Key);
}
/// <inheritdoc cref="IWireMockServer.AddGlobalProcessingDelay" />
[PublicAPI]
public void AddGlobalProcessingDelay(TimeSpan delay)
{
_options.RequestProcessingDelay = delay;
}
/// <inheritdoc cref="IWireMockServer.AllowPartialMapping" />
[PublicAPI]
public void AllowPartialMapping(bool allow = true)
{
_settings.Logger.Info("AllowPartialMapping is set to {0}", allow);
_options.AllowPartialMapping = allow;
}
/// <inheritdoc cref="IWireMockServer.SetAzureADAuthentication(string, string)" />
[PublicAPI]
public void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience)
{
Guard.NotNull(tenant, nameof(tenant));
Guard.NotNull(audience, nameof(audience));
/// <inheritdoc cref="IWireMockServer.SetAzureADAuthentication(string, string)" />
[PublicAPI]
public void SetAzureADAuthentication([NotNull] string tenant, [NotNull] string audience)
{
Guard.NotNull(tenant, nameof(tenant));
Guard.NotNull(audience, nameof(audience));
#if NETSTANDARD1_3
throw new NotSupportedException("AzureADAuthentication is not supported for NETStandard 1.3");
#else
_options.AuthenticationMatcher = new AzureADAuthenticationMatcher(tenant, audience);
_options.AuthenticationMatcher = new AzureADAuthenticationMatcher(tenant, audience);
#endif
}
/// <inheritdoc cref="IWireMockServer.SetBasicAuthentication(string, string)" />
[PublicAPI]
public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
{
Guard.NotNull(username, nameof(username));
Guard.NotNull(password, nameof(password));
_options.AuthenticationMatcher = new BasicAuthenticationMatcher(username, password);
}
/// <inheritdoc cref="IWireMockServer.RemoveAuthentication" />
[PublicAPI]
public void RemoveAuthentication()
{
_options.AuthenticationMatcher = null;
}
/// <inheritdoc cref="IWireMockServer.SetMaxRequestLogCount" />
[PublicAPI]
public void SetMaxRequestLogCount([CanBeNull] int? maxRequestLogCount)
{
_options.MaxRequestLogCount = maxRequestLogCount;
}
/// <inheritdoc cref="IWireMockServer.SetRequestLogExpirationDuration" />
[PublicAPI]
public void SetRequestLogExpirationDuration([CanBeNull] int? requestLogExpirationDuration)
{
_options.RequestLogExpirationDuration = requestLogExpirationDuration;
}
/// <inheritdoc cref="IWireMockServer.ResetScenarios" />
[PublicAPI]
public void ResetScenarios()
{
_options.Scenarios.Clear();
}
/// <inheritdoc cref="IWireMockServer.WithMapping(MappingModel[])" />
[PublicAPI]
public IWireMockServer WithMapping(params MappingModel[] mappings)
{
foreach (var mapping in mappings)
{
ConvertMappingAndRegisterAsRespondProvider(mapping, mapping.Guid ?? Guid.NewGuid());
}
/// <inheritdoc cref="IWireMockServer.SetBasicAuthentication(string, string)" />
[PublicAPI]
public void SetBasicAuthentication([NotNull] string username, [NotNull] string password)
{
Guard.NotNull(username, nameof(username));
Guard.NotNull(password, nameof(password));
return this;
}
_options.AuthenticationMatcher = new BasicAuthenticationMatcher(username, password);
/// <inheritdoc cref="IWireMockServer.WithMapping(string)" />
[PublicAPI]
public IWireMockServer WithMapping(string mappings)
{
var mappingModels = DeserializeJsonToArray<MappingModel>(mappings);
foreach (var mappingModel in mappingModels)
{
ConvertMappingAndRegisterAsRespondProvider(mappingModel, mappingModel.Guid ?? Guid.NewGuid());
}
/// <inheritdoc cref="IWireMockServer.RemoveAuthentication" />
[PublicAPI]
public void RemoveAuthentication()
return this;
}
/// <summary>
/// The given.
/// </summary>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
[PublicAPI]
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
{
return new RespondWithAProvider(RegisterMapping, requestMatcher, _settings, saveToFile);
}
private void RegisterMapping(IMapping mapping, bool saveToFile)
{
// Check a mapping exists with the same Guid, if so, replace it.
if (_options.Mappings.ContainsKey(mapping.Guid))
{
_options.AuthenticationMatcher = null;
_options.Mappings[mapping.Guid] = mapping;
}
else
{
_options.Mappings.TryAdd(mapping.Guid, mapping);
}
/// <inheritdoc cref="IWireMockServer.SetMaxRequestLogCount" />
[PublicAPI]
public void SetMaxRequestLogCount([CanBeNull] int? maxRequestLogCount)
if (saveToFile)
{
_options.MaxRequestLogCount = maxRequestLogCount;
_mappingToFileSaver.SaveMappingToFile(mapping);
}
}
private void InitSettings(WireMockServerSettings settings)
{
if (settings.AllowBodyForAllHttpMethods == true)
{
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to True");
}
/// <inheritdoc cref="IWireMockServer.SetRequestLogExpirationDuration" />
[PublicAPI]
public void SetRequestLogExpirationDuration([CanBeNull] int? requestLogExpirationDuration)
if (settings.AllowOnlyDefinedHttpStatusCodeInResponse == true)
{
_options.RequestLogExpirationDuration = requestLogExpirationDuration;
_options.AllowOnlyDefinedHttpStatusCodeInResponse = _settings.AllowOnlyDefinedHttpStatusCodeInResponse;
_settings.Logger.Info("AllowOnlyDefinedHttpStatusCodeInResponse is set to True");
}
/// <inheritdoc cref="IWireMockServer.ResetScenarios" />
[PublicAPI]
public void ResetScenarios()
if (settings.AllowPartialMapping == true)
{
_options.Scenarios.Clear();
AllowPartialMapping();
}
/// <inheritdoc cref="IWireMockServer.WithMapping(MappingModel[])" />
[PublicAPI]
public IWireMockServer WithMapping(params MappingModel[] mappings)
if (settings.StartAdminInterface == true)
{
foreach (var mapping in mappings)
if (!string.IsNullOrEmpty(settings.AdminUsername) && !string.IsNullOrEmpty(settings.AdminPassword))
{
ConvertMappingAndRegisterAsRespondProvider(mapping, mapping.Guid ?? Guid.NewGuid());
SetBasicAuthentication(settings.AdminUsername, settings.AdminPassword);
}
return this;
if (!string.IsNullOrEmpty(settings.AdminAzureADTenant) && !string.IsNullOrEmpty(settings.AdminAzureADAudience))
{
SetAzureADAuthentication(settings.AdminAzureADTenant, settings.AdminAzureADAudience);
}
InitAdmin();
}
/// <inheritdoc cref="IWireMockServer.WithMapping(string)" />
[PublicAPI]
public IWireMockServer WithMapping(string mappings)
if (settings.ReadStaticMappings == true)
{
var mappingModels = DeserializeJsonToArray<MappingModel>(mappings);
foreach (var mappingModel in mappingModels)
{
ConvertMappingAndRegisterAsRespondProvider(mappingModel, mappingModel.Guid ?? Guid.NewGuid());
}
return this;
ReadStaticMappings();
}
/// <summary>
/// The given.
/// </summary>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
[PublicAPI]
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
if (settings.WatchStaticMappings == true)
{
return new RespondWithAProvider(RegisterMapping, requestMatcher, _settings, saveToFile);
WatchStaticMappings();
}
private void RegisterMapping(IMapping mapping, bool saveToFile)
{
// Check a mapping exists with the same Guid, if so, replace it.
if (_options.Mappings.ContainsKey(mapping.Guid))
{
_options.Mappings[mapping.Guid] = mapping;
}
else
{
_options.Mappings.TryAdd(mapping.Guid, mapping);
}
InitProxyAndRecord(settings);
if (saveToFile)
{
_mappingToFileSaver.SaveMappingToFile(mapping);
}
if (settings.RequestLogExpirationDuration != null)
{
SetRequestLogExpirationDuration(settings.RequestLogExpirationDuration);
}
if (settings.MaxRequestLogCount != null)
{
SetMaxRequestLogCount(settings.MaxRequestLogCount);
}
}
}

View File

@@ -43,5 +43,11 @@ namespace WireMock.Settings
/// </summary>
[PublicAPI]
public string[] ExcludedCookies { get; set; }
/// <summary>
/// Prefer the Proxy Mapping over the saved Mapping (in case SaveMapping is set to <c>true</c>).
/// </summary>
//[PublicAPI]
//public bool PreferProxyMapping { get; set; }
}
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Stef.Validation;
using WireMock.Logging;
@@ -35,34 +34,33 @@ namespace WireMock.Settings
settings = new WireMockServerSettings
{
StartAdminInterface = parser.GetBoolValue("StartAdminInterface", true),
ReadStaticMappings = parser.GetBoolValue("ReadStaticMappings"),
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
AllowPartialMapping = parser.GetBoolValue("AllowPartialMapping"),
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
AdminUsername = parser.GetStringValue("AdminUsername"),
AdminPassword = parser.GetStringValue("AdminPassword"),
AdminAzureADTenant = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADTenant)),
AdminAzureADAudience = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADAudience)),
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
AdminAzureADTenant = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADTenant)),
AdminPassword = parser.GetStringValue("AdminPassword"),
AdminUsername = parser.GetStringValue("AdminUsername"),
AllowBodyForAllHttpMethods = parser.GetBoolValue("AllowBodyForAllHttpMethods"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
AllowOnlyDefinedHttpStatusCodeInResponse = parser.GetBoolValue("AllowOnlyDefinedHttpStatusCodeInResponse"),
AllowPartialMapping = parser.GetBoolValue("AllowPartialMapping"),
DisableJsonBodyParsing = parser.GetBoolValue("DisableJsonBodyParsing"),
HandleRequestsSynchronously = parser.GetBoolValue("HandleRequestsSynchronously"),
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
ReadStaticMappings = parser.GetBoolValue("ReadStaticMappings"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
SaveUnmatchedRequests = parser.GetBoolValue(nameof(WireMockServerSettings.SaveUnmatchedRequests)),
StartAdminInterface = parser.GetBoolValue("StartAdminInterface", true),
ThrowExceptionWhenMatcherFails = parser.GetBoolValue("ThrowExceptionWhenMatcherFails"),
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
SaveUnmatchedRequests = parser.GetBoolValue(nameof(WireMockServerSettings.SaveUnmatchedRequests)),
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
};
#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.GetValue(nameof(WireMockServerSettings.CorsPolicyOptions), values =>
{
var value = string.Join(string.Empty, values);
return Enum.TryParse<CorsPolicyOptions>(value, true, out var corsPolicyOptions) ? corsPolicyOptions : CorsPolicyOptions.None;
});
#endif
if (logger != null)
@@ -75,9 +73,9 @@ namespace WireMock.Settings
settings.Logger = new WireMockConsoleLogger();
}
if (parser.Contains("Port"))
if (parser.Contains(nameof(WireMockServerSettings.Port)))
{
settings.Port = parser.GetIntValue("Port");
settings.Port = parser.GetIntValue(nameof(WireMockServerSettings.Port));
}
else
{
@@ -89,14 +87,15 @@ namespace WireMock.Settings
{
settings.ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = proxyUrl,
SaveMapping = parser.GetBoolValue("SaveMapping"),
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern"),
AllowAutoRedirect = parser.GetBoolValue("AllowAutoRedirect"),
ClientX509Certificate2ThumbprintOrSubjectName = parser.GetStringValue("ClientX509Certificate2ThumbprintOrSubjectName"),
ExcludedHeaders = parser.GetValues("ExcludedHeaders"),
ExcludedCookies = parser.GetValues("ExcludedCookies"),
AllowAutoRedirect = parser.GetBoolValue("AllowAutoRedirect")
ExcludedHeaders = parser.GetValues("ExcludedHeaders"),
// PreferProxyMapping = parser.GetBoolValue(nameof(ProxyAndRecordSettings.PreferProxyMapping)),
SaveMapping = parser.GetBoolValue("SaveMapping"),
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern"),
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
Url = proxyUrl
};
string proxyAddress = parser.GetStringValue("WebProxyAddress");

View File

@@ -0,0 +1,30 @@
using Nelibur.ObjectMapper;
using WireMock.Admin.Settings;
using WireMock.Settings;
namespace WireMock.Util
{
internal sealed class TinyMapperUtils
{
public static TinyMapperUtils Instance { get; } = new TinyMapperUtils();
private TinyMapperUtils()
{
TinyMapper.Bind<ProxyAndRecordSettings, ProxyAndRecordSettingsModel>();
TinyMapper.Bind<WebProxySettings, WebProxySettingsModel>();
TinyMapper.Bind<ProxyAndRecordSettingsModel, ProxyAndRecordSettings>();
TinyMapper.Bind<WebProxySettingsModel, WebProxySettings>();
}
public ProxyAndRecordSettingsModel Map(ProxyAndRecordSettings instance)
{
return instance == null ? null : TinyMapper.Map<ProxyAndRecordSettingsModel>(instance);
}
public ProxyAndRecordSettings Map(ProxyAndRecordSettingsModel model)
{
return model == null ? null : TinyMapper.Map<ProxyAndRecordSettings>(model);
}
}
}

View File

@@ -51,7 +51,7 @@
</PropertyGroup>
<ItemGroup>
<Compile Remove="Util\FileSystemWatcherExtensions.cs" />
<Compile Remove="Util\FileSystemWatcherExtensions.cs" />
</ItemGroup>
<ItemGroup>
@@ -64,7 +64,7 @@
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
<PackageReference Include="AnyOf" Version="0.3.0" />
<!--<PackageReference Include="TinyMapper" Version="3.0.3" />-->
<PackageReference Include="TinyMapper" Version="3.0.3" />
<!--<PackageReference Include="Mapster" Version="7.2.0" />-->
</ItemGroup>

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Threading;
using FluentAssertions;
using WireMock.Models;
using WireMock.RequestBuilders;
@@ -192,10 +193,36 @@ namespace WireMock.Net.Tests.Serialization
}
[Fact]
public void ToMappingModel_WithDelay_ReturnsCorrectModel()
public void ToMappingModel_WithDelayAsTimeSpan_ReturnsCorrectModel()
{
// Arrange
var tests = new[]
{
new { Delay = Timeout.InfiniteTimeSpan, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds },
new { Delay = TimeSpan.FromSeconds(1), Expected = 1000},
new { Delay = TimeSpan.MaxValue, Expected = (int) TimeSpan.MaxValue.TotalMilliseconds }
};
foreach (var test in tests)
{
var request = Request.Create();
var response = Response.Create().WithDelay(test.Delay);
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);
// Act
var model = _sut.ToMappingModel(mapping);
// Assert
model.Should().NotBeNull();
model.Response.Delay.Should().Be(test.Expected);
}
}
[Fact]
public void ToMappingModel_WithDelayAsMilleSeconds_ReturnsCorrectModel()
{
// Assign
int delay = 1000;
var delay = 1000;
var request = Request.Create();
var response = Response.Create().WithDelay(delay);
var mapping = new Mapping(Guid.NewGuid(), "", null, _settings, request, response, 42, null, null, null, null, null, null);

View File

@@ -3,6 +3,7 @@ using FluentAssertions;
using Moq;
using NFluent;
using WireMock.Authentication;
using WireMock.Constants;
using WireMock.Logging;
using WireMock.Owin;
using WireMock.Server;
@@ -79,13 +80,13 @@ namespace WireMock.Net.Tests
});
// Assert
var mappings = server.Mappings;
Check.That(mappings.Count()).IsEqualTo(25);
Check.That(mappings.All(m => m.Priority == int.MinValue)).IsTrue();
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(25);
server.Mappings.All(m => m.Priority == WireMockConstants.AdminPriority).Should().BeTrue();
}
[Fact]
public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPriority_Is1000_When_StartAdminInterface_IsTrue()
public void WireMockServer_WireMockServerSettings_ProxyAndRecordSettings_ProxyPriority_IsMinus2000000_When_StartAdminInterface_IsTrue()
{
// Assign and Act
var server = WireMockServer.Start(new WireMockServerSettings
@@ -98,10 +99,11 @@ namespace WireMock.Net.Tests
});
// Assert
var mappings = server.Mappings;
Check.That(mappings.Count()).IsEqualTo(26);
Check.That(mappings.Count(m => m.Priority == int.MinValue)).IsEqualTo(25);
Check.That(mappings.Count(m => m.Priority == 1000)).IsEqualTo(1);
server.Mappings.Should().NotBeNull();
server.Mappings.Should().HaveCount(26);
server.Mappings.Count(m => m.Priority == WireMockConstants.AdminPriority).Should().Be(25);
server.Mappings.Count(m => m.Priority == WireMockConstants.ProxyPriority).Should().Be(1);
}
[Fact]