Compare commits

..

13 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
Stef Heyenrath
5da6e103ba 1.4.40 2022-03-26 11:22:45 +01:00
Stef Heyenrath
cbf82836f5 Add Port and Url property to WireMockServer (#740) 2022-03-26 11:03:37 +01:00
Stef Heyenrath
0789b97883 1.4.39 2022-03-25 21:39:32 +01:00
Stef Heyenrath
ce4d39ae55 1.4.39 2022-03-25 21:39:14 +01:00
Stef Heyenrath
11c0782673 Upgrade NuGet for RandomDataGenerator.Net to 1.0.14 (#739)
* RandomDataGenerator.Net 1.0.14

* .
2022-03-25 20:34:39 +01:00
Stef Heyenrath
6b15b80605 launchsettings 2022-03-11 14:48:08 +01:00
Stef Heyenrath
55fbc52ce9 net6 (#737) 2022-03-11 14:46:25 +01:00
Stef Heyenrath
2a1d14b52c 1.4.38 2022-03-11 10:12:02 +01:00
Stef Heyenrath
bb3147eb8d Remove interface for all Settings (#736) 2022-03-10 20:58:18 +01:00
Stef Heyenrath
3087ce55b1 Icon for preview 2022-03-07 08:53:13 +01:00
75 changed files with 2526 additions and 1923 deletions

View File

@@ -1,3 +1,18 @@
# 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)
# 1.4.39 (25 March 2022)
- [#739](https://github.com/WireMock-Net/WireMock.Net/pull/739) - Upgrade NuGet for RandomDataGenerator.Net to 1.0.14 contributed by [StefH](https://github.com/StefH)
# 1.4.38 (11 March 2022)
- [#736](https://github.com/WireMock-Net/WireMock.Net/pull/736) - Remove interface for all Setting classes [feature] contributed by [StefH](https://github.com/StefH)
- [#737](https://github.com/WireMock-Net/WireMock.Net/pull/737) - Add WireMock.Net.WebApplication.NET6 example contributed by [StefH](https://github.com/StefH)
# 1.4.37 (02 March 2022)
- [#730](https://github.com/WireMock-Net/WireMock.Net/pull/730) - Fixed bug "dotnet nuget push -n" [bug] contributed by [StefH](https://github.com/StefH)
- [#732](https://github.com/WireMock-Net/WireMock.Net/pull/732) - Make X509CertificatePassword optional [feature] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.4.37</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.37
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,7 +1,6 @@
# 1.4.37 (02 March 2022)
- #730 Fixed bug &quot;dotnet nuget push -n&quot; [bug]
- #732 Make X509CertificatePassword optional [feature]
- #733 Fix FileSystemWatcher [bug]
- #726 Wiremock - WatchStaticMappings only works until the first request is made [bug]
# 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

@@ -29,7 +29,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
### NuGet packages
| | Official | Preview |
| | Official | Preview [:information_source:](https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) |
| - | - | - |
| &nbsp;&nbsp;**WireMock.Net** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://buildstats.info/myget/wiremock-net/WireMock.Net?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
| &nbsp;&nbsp;**WireMock.Net.StandAlone** | [![NuGet Badge WireMock.Net](https://buildstats.info/nuget/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://buildstats.info/myget/wiremock-net/WireMock.Net.StandAlone?includePreReleases=true)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)

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}"
@@ -99,6 +97,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.Abstractions",
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET6", "examples\WireMock.Net.Console.NET6\WireMock.Net.Console.NET6.csproj", "{2215055B-594E-4C2F-99B2-6DF337F02893}"
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
@@ -141,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
@@ -233,6 +231,14 @@ Global
{2215055B-594E-4C2F-99B2-6DF337F02893}.Debug|Any CPU.Build.0 = Debug|Any CPU
{2215055B-594E-4C2F-99B2-6DF337F02893}.Release|Any CPU.ActiveCfg = Release|Any CPU
{2215055B-594E-4C2F-99B2-6DF337F02893}.Release|Any CPU.Build.0 = Release|Any CPU
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{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
@@ -247,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}
@@ -272,6 +277,8 @@ Global
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{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

@@ -42,8 +42,8 @@
<Reference Include="AnyOf, Version=0.3.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.3.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Fare, Version=2.1.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\..\packages\Fare.2.1.2\lib\net35\Fare.dll</HintPath>
<Reference Include="Fare, Version=2.2.0.0, Culture=neutral, PublicKeyToken=ea68d375bf33a7c8, processorArchitecture=MSIL">
<HintPath>..\..\packages\Fare.2.2.0\lib\net35\Fare.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.1.0.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.1.0\lib\net46\Handlebars.dll</HintPath>
@@ -213,8 +213,8 @@
<Reference Include="Newtonsoft.Json, Version=11.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.11.0.2\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="RandomDataGenerator, Version=1.0.12.0, Culture=neutral, PublicKeyToken=ae5c571d29a3b8d9, processorArchitecture=MSIL">
<HintPath>..\..\packages\RandomDataGenerator.Net.1.0.12\lib\net45\RandomDataGenerator.dll</HintPath>
<Reference Include="RandomDataGenerator, Version=1.0.13.0, Culture=neutral, PublicKeyToken=ae5c571d29a3b8d9, processorArchitecture=MSIL">
<HintPath>..\..\packages\RandomDataGenerator.Net.1.0.14\lib\net45\RandomDataGenerator.dll</HintPath>
</Reference>
<Reference Include="Scriban.Signed, Version=2.1.4.0, Culture=neutral, PublicKeyToken=5675fb69b15f2433, processorArchitecture=MSIL">
<HintPath>..\..\packages\Scriban.Signed.2.1.4\lib\net45\Scriban.Signed.dll</HintPath>
@@ -241,8 +241,8 @@
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Pipelines.4.5.3\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.16.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.16\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.18.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.18\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Memory.4.5.4\lib\net461\System.Memory.dll</HintPath>

View File

@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.3.0" targetFramework="net472" />
<package id="Fare" version="2.1.2" targetFramework="net472" />
<package id="Fare" version="2.2.0" targetFramework="net472" />
<package id="Handlebars.Net" version="2.1.0" targetFramework="net472" />
<package id="Handlebars.Net.Helpers" version="2.3.2" targetFramework="net472" />
<package id="Handlebars.Net.Helpers.Core" version="2.3.3" targetFramework="net472" />
@@ -59,7 +59,7 @@
<package id="Microsoft.Extensions.Primitives" version="5.0.0" targetFramework="net472" />
<package id="Microsoft.Net.Http.Headers" version="2.2.0" targetFramework="net472" />
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
<package id="RandomDataGenerator.Net" version="1.0.12" targetFramework="net472" />
<package id="RandomDataGenerator.Net" version="1.0.14" targetFramework="net472" />
<package id="Scriban.Signed" version="2.1.4" targetFramework="net472" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
<package id="System.Buffers" version="4.5.1" targetFramework="net472" />
@@ -67,7 +67,7 @@
<package id="System.ComponentModel.Annotations" version="4.5.0" targetFramework="net472" />
<package id="System.Diagnostics.DiagnosticSource" version="4.5.0" targetFramework="net472" />
<package id="System.IO.Pipelines" version="4.5.3" targetFramework="net472" />
<package id="System.Linq.Dynamic.Core" version="1.2.16" targetFramework="net472" />
<package id="System.Linq.Dynamic.Core" version="1.2.18" targetFramework="net472" />
<package id="System.Memory" version="4.5.4" targetFramework="net472" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net472" />
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net472" />

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

@@ -225,8 +225,8 @@
<Reference Include="System.IO.Pipelines, Version=4.0.0.1, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.IO.Pipelines.4.5.2\lib\netstandard2.0\System.IO.Pipelines.dll</HintPath>
</Reference>
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.16.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.16\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
<Reference Include="System.Linq.Dynamic.Core, Version=1.2.18.0, Culture=neutral, PublicKeyToken=0f07ec44de6ac832, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Linq.Dynamic.Core.1.2.18\lib\net46\System.Linq.Dynamic.Core.dll</HintPath>
</Reference>
<Reference Include="System.Memory, Version=4.0.1.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.Memory.4.5.1\lib\netstandard2.0\System.Memory.dll</HintPath>

View File

@@ -65,7 +65,7 @@
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />
<package id="System.Diagnostics.DiagnosticSource" version="4.5.0" targetFramework="net461" />
<package id="System.IO.Pipelines" version="4.5.2" targetFramework="net461" />
<package id="System.Linq.Dynamic.Core" version="1.2.16" targetFramework="net461" />
<package id="System.Linq.Dynamic.Core" version="1.2.18" targetFramework="net461" />
<package id="System.Memory" version="4.5.1" targetFramework="net461" />
<package id="System.Numerics.Vectors" version="4.5.0" targetFramework="net461" />
<package id="System.Reflection.Metadata" version="1.6.0" targetFramework="net461" />

View File

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

View File

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

View File

@@ -0,0 +1,29 @@
using Microsoft.Extensions.Configuration;
using Microsoft.Extensions.DependencyInjection;
using Microsoft.Extensions.Hosting;
using Microsoft.Extensions.Logging;
using WireMock.Settings;
namespace WireMock.Net.WebApplication;
public class Program
{
public static void Main(string[] args)
{
CreateHostBuilder(args).Build().Run();
}
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());
services.AddTransient<IWireMockService, WireMockService>();
services.Configure<WireMockServerSettings>(configuration.GetSection("WireMockServerSettings"));
services.AddHostedService<App>();
}
}

View File

@@ -0,0 +1,12 @@
{
"profiles": {
"WireMock.Net.WebApplication.NET6": {
"commandName": "Project",
"launchBrowser": true,
"environmentVariables": {
"ASPNETCORE_ENVIRONMENT": "Development"
},
"applicationUrl": "https://localhost:54544;http://localhost:54545"
}
}
}

View File

@@ -0,0 +1,33 @@
<Project Sdk="Microsoft.NET.Sdk.Web">
<PropertyGroup>
<TargetFramework>net6</TargetFramework>
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
<RootNamespace>WireMock.Net.WebApplication</RootNamespace>
<UserSecretsId>efcf4a18-fd7c-4622-1111-336d65290599</UserSecretsId>
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
</PropertyGroup>
<ItemGroup>
<Content Remove="Properties\1.launchSettings.json" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
<ItemGroup>
<Content Update="appsettings.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
</ItemGroup>
</Project>

View File

@@ -0,0 +1,81 @@
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;
public class WireMockService : IWireMockService
{
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)
{
_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

@@ -0,0 +1,184 @@
{
"Guid": "1e0686d3-5eb0-4c30-9482-db3735a1e4c4",
"Title": "",
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/favicon.ico",
"IgnoreCase": false
}
]
},
"Methods": [
"GET"
],
"Headers": [
{
"Name": "Accept",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "image/avif,image/webp,image/apng,image/svg+xml,image/*,*/*;q=0.8",
"IgnoreCase": true
}
]
},
{
"Name": "Host",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "localhost:8081",
"IgnoreCase": true
}
]
},
{
"Name": "User-Agent",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/99.0.4844.51 Safari/537.36",
"IgnoreCase": true
}
]
},
{
"Name": ":method",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "GET",
"IgnoreCase": true
}
]
},
{
"Name": "Accept-Encoding",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "gzip, deflate, br",
"IgnoreCase": true
}
]
},
{
"Name": "Accept-Language",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "en-US,en;q=0.9,nl;q=0.8",
"IgnoreCase": true
}
]
},
{
"Name": "Referer",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "https://localhost:8081/__admin/mappings",
"IgnoreCase": true
}
]
},
{
"Name": "sec-ch-ua",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "\" Not A;Brand\";v=\"99\", \"Chromium\";v=\"99\", \"Google Chrome\";v=\"99\"",
"IgnoreCase": true
}
]
},
{
"Name": "sec-ch-ua-mobile",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "?0",
"IgnoreCase": true
}
]
},
{
"Name": "sec-ch-ua-platform",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "\"Windows\"",
"IgnoreCase": true
}
]
},
{
"Name": "sec-fetch-site",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "same-origin",
"IgnoreCase": true
}
]
},
{
"Name": "sec-fetch-mode",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "no-cors",
"IgnoreCase": true
}
]
},
{
"Name": "sec-fetch-dest",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "image",
"IgnoreCase": true
}
]
}
],
"Cookies": [
{
"Name": "ai_user",
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "4z4B71qxV7rOSA6Gf3IFZ1|2021-07-20T17:07:54.344Z",
"IgnoreCase": true
}
]
}
]
},
"Response": {
"StatusCode": 200,
"Body": "<!doctype html><html lang=\"en\"><head><script>!function(e,t,a,n,g){e[n]=e[n]||[],e[n].push({\"gtm.start\":(new Date).getTime(),event:\"gtm.js\"});var m=t.getElementsByTagName(a)[0],r=t.createElement(a);r.async=!0,r.src=\"https://www.googletagmanager.com/gtm.js?id=GTM-NTGJQ9S\",m.parentNode.insertBefore(r,m)}(window,document,\"script\",\"dataLayer\")</script><meta charset=\"utf-8\"/><link rel=\"icon\" type=\"image/png\" href=\"/favicon.png\"/><meta name=\"viewport\" content=\"width=device-width,initial-scale=1\"/><title>Product Support Portal | SmartBear Software</title><link href=\"https://fonts.googleapis.com/css?family=Open+Sans:300,400,400i,600,700|Roboto+Mono:400,400i\" rel=\"stylesheet\"><link rel=\"stylesheet\" href=\"https://pro.fontawesome.com/releases/v5.13.1/css/all.css\" integrity=\"sha384-B9BoFFAuBaCfqw6lxWBZrhg/z4NkwqdBci+E+Sc2XlK/Rz25RYn8Fetb+Aw5irxa\" crossorigin=\"anonymous\"><script src=\"https://code.jquery.com/jquery-3.3.1.min.js\" integrity=\"sha256-FgpCb/KJQlLNfOu91ta32o/NMZxltwRo8QtmkMRdAu8=\" crossorigin=\"anonymous\"></script><script src=\"https://cdn.jsdelivr.net/gh/google/code-prettify@master/loader/run_prettify.js\" type=\"text/javascript\"></script><link href=\"/static/css/main.f0fcb0c0.chunk.css\" rel=\"stylesheet\"></head><body><noscript><iframe src=\"https://www.googletagmanager.com/ns.html?id=GTM-NTGJQ9S\" height=\"0\" width=\"0\" style=\"display:none;visibility:hidden\"></iframe></noscript><noscript>You need to enable JavaScript to run this website.</noscript><div id=\"root\"></div><script>!function(e){function r(r){for(var n,p,l=r[0],a=r[1],f=r[2],c=0,s=[];c<l.length;c++)p=l[c],Object.prototype.hasOwnProperty.call(o,p)&&o[p]&&s.push(o[p][0]),o[p]=0;for(n in a)Object.prototype.hasOwnProperty.call(a,n)&&(e[n]=a[n]);for(i&&i(r);s.length;)s.shift()();return u.push.apply(u,f||[]),t()}function t(){for(var e,r=0;r<u.length;r++){for(var t=u[r],n=!0,l=1;l<t.length;l++){var a=t[l];0!==o[a]&&(n=!1)}n&&(u.splice(r--,1),e=p(p.s=t[0]))}return e}var n={},o={1:0},u=[];function p(r){if(n[r])return n[r].exports;var t=n[r]={i:r,l:!1,exports:{}};return e[r].call(t.exports,t,t.exports,p),t.l=!0,t.exports}p.m=e,p.c=n,p.d=function(e,r,t){p.o(e,r)||Object.defineProperty(e,r,{enumerable:!0,get:t})},p.r=function(e){\"undefined\"!=typeof Symbol&&Symbol.toStringTag&&Object.defineProperty(e,Symbol.toStringTag,{value:\"Module\"}),Object.defineProperty(e,\"__esModule\",{value:!0})},p.t=function(e,r){if(1&r&&(e=p(e)),8&r)return e;if(4&r&&\"object\"==typeof e&&e&&e.__esModule)return e;var t=Object.create(null);if(p.r(t),Object.defineProperty(t,\"default\",{enumerable:!0,value:e}),2&r&&\"string\"!=typeof e)for(var n in e)p.d(t,n,function(r){return e[r]}.bind(null,n));return t},p.n=function(e){var r=e&&e.__esModule?function(){return e.default}:function(){return e};return p.d(r,\"a\",r),r},p.o=function(e,r){return Object.prototype.hasOwnProperty.call(e,r)},p.p=\"/\";var l=this[\"webpackJsonpweb-support-react\"]=this[\"webpackJsonpweb-support-react\"]||[],a=l.push.bind(l);l.push=r,l=l.slice();for(var f=0;f<l.length;f++)r(l[f]);var i=a;t()}([])</script><script src=\"/static/js/2.cfa1a356.chunk.js\"></script><script src=\"/static/js/main.cb89e4ed.chunk.js\"></script></body></html>",
"Headers": {
"Content-Type": "text/html",
"Last-Modified": "Thu, 10 Mar 2022 08:39:07 GMT",
"Transfer-Encoding": "chunked",
"Connection": "keep-alive",
"Date": "Fri, 11 Mar 2022 09:21:22 GMT",
"ETag": "W/\"cd426e4e5a34d81:0\"",
"X-XSS-Protection": "1; mode=block",
"Strict-Transport-Security": "max-age=31536000; includeSubDomains; preload",
"X-Frame-Options": "SAMEORIGIN",
"X-Content-Type-Options": "nosniff",
"Content-Security-Policy": "frame-ancestors 'self'",
"Vary": "Accept-Encoding",
"X-Cache": "Miss from cloudfront",
"Via": "1.1 e328b143eb69c36369a2def78300d502.cloudfront.net (CloudFront)",
"X-Amz-Cf-Pop": "AMS1-C1",
"X-Amz-Cf-Id": "fUBp1b6g0N3JnLuj_VcueuCf0Rw-eXfBNKHq7luNlAOtqAxU5MUdcA=="
}
}
}

View File

@@ -0,0 +1,29 @@
{
"Logging": {
"IncludeScopes": false,
"Debug": {
"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
}
}
}

View File

@@ -0,0 +1,21 @@
# Running in IIS
Follow these links / steps:
* https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS
* https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/development-time-iis-support?view=aspnetcore-2.1
* Create a `web.config` file
## IIS Sites
![IIS Multiple](resources/iis-wiremock1and2.png)
## App Pool settings
![IIS Multiple](resources/iis-apppool.png)
## Publish Profiles
Two example publish profiles are created:
* [IIS Localhost 1](./Properties/PublishProfiles/IIS%20Localhost%201.pubxml)
* [IIS Localhost 2](./Properties/PublishProfiles/IIS%20Localhost%202.pubxml)
## Debugging
Select the debug "IIS" if you want to debug in IIS.
![IIS Debug](resources/iis-debug.png)

View File

@@ -0,0 +1,12 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<!--
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
-->
<system.webServer>
<handlers>
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
</handlers>
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
</system.webServer>
</configuration>

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

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

View File

@@ -38,11 +38,21 @@ namespace WireMock.Server
/// </summary>
List<int> Ports { get; }
/// <summary>
/// Gets the first port.
/// </summary>
int Port { get; }
/// <summary>
/// Gets the urls.
/// </summary>
string[] Urls { get; }
/// <summary>
/// Gets the first url.
/// </summary>
string Url { get; }
//ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
/// <summary>

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

@@ -25,7 +25,7 @@
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
<PackageReference Include="JetBrains.Annotations" Version="2021.3.0" PrivateAssets="All" />
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />
<PackageReference Include="Stef.Validation" Version="0.1.0" />
</ItemGroup>

View File

@@ -16,11 +16,11 @@ namespace WireMock.Net.StandAlone
private static readonly string Version = typeof(StandAloneApp).GetTypeInfo().Assembly.GetName().Version.ToString();
/// <summary>
/// Start WireMock.Net standalone Server based on the IWireMockServerSettings.
/// Start WireMock.Net standalone Server based on the WireMockServerSettings.
/// </summary>
/// <param name="settings">The IWireMockServerSettings</param>
/// <param name="settings">The WireMockServerSettings</param>
[PublicAPI]
public static WireMockServer Start([NotNull] IWireMockServerSettings settings)
public static WireMockServer Start([NotNull] WireMockServerSettings settings)
{
Guard.NotNull(settings, nameof(settings));

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

@@ -7,7 +7,7 @@ namespace WireMock.Http
{
internal static class HttpClientBuilder
{
public static HttpClient Build(IHttpClientSettings settings)
public static HttpClient Build(HttpClientSettings settings)
{
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0 || NET6_0
var handler = new HttpClientHandler

View File

@@ -19,9 +19,9 @@ namespace WireMock.Http
{
private const string ClientIp = "::1";
private readonly IWireMockServerSettings _settings;
private readonly WireMockServerSettings _settings;
public WebhookSender(IWireMockServerSettings settings)
public WebhookSender(WireMockServerSettings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}

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; }
@@ -76,8 +76,8 @@ namespace WireMock
/// <summary>
/// The WireMockServerSettings.
/// </summary>
IWireMockServerSettings Settings { get; }
WireMockServerSettings Settings { get; }
/// <summary>
/// Is State started ?
/// </summary>
@@ -90,7 +90,15 @@ namespace WireMock
/// <c>true</c> if this mapping is an Admin Interface; otherwise, <c>false</c>.
/// </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

@@ -44,7 +44,7 @@ namespace WireMock
public IResponseProvider Provider { get; }
/// <inheritdoc />
public IWireMockServerSettings Settings { get; }
public WireMockServerSettings Settings { get; }
/// <inheritdoc />
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
@@ -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);
@@ -81,7 +84,7 @@ namespace WireMock
Guid guid,
[CanBeNull] string title,
[CanBeNull] string path,
[NotNull] IWireMockServerSettings settings,
[NotNull] WireMockServerSettings settings,
[NotNull] IRequestMatcher requestMatcher,
[NotNull] IResponseProvider provider,
int priority,

View File

@@ -17,15 +17,15 @@ namespace WireMock.Proxy
{
internal class ProxyHelper
{
private readonly IWireMockServerSettings _settings;
private readonly WireMockServerSettings _settings;
public ProxyHelper([NotNull] IWireMockServerSettings settings)
public ProxyHelper([NotNull] WireMockServerSettings settings)
{
_settings = Guard.NotNull(settings, nameof(settings));
}
public async Task<(ResponseMessage Message, IMapping Mapping)> SendAsync(
[NotNull] IProxyAndRecordSettings proxyAndRecordSettings,
[NotNull] ProxyAndRecordSettings proxyAndRecordSettings,
[NotNull] HttpClient client,
[NotNull] RequestMessage requestMessage,
[NotNull] string url)
@@ -59,7 +59,7 @@ namespace WireMock.Proxy
return (responseMessage, mapping);
}
private IMapping ToMapping(IProxyAndRecordSettings proxyAndRecordSettings, RequestMessage requestMessage, ResponseMessage responseMessage)
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, RequestMessage requestMessage, ResponseMessage responseMessage)
{
string[] excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
string[] excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };

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

@@ -1,4 +1,4 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
using WireMock.Settings;
namespace WireMock.ResponseBuilders
@@ -21,6 +21,6 @@ namespace WireMock.ResponseBuilders
/// </summary>
/// <param name="settings">The IProxyAndRecordSettings.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] IProxyAndRecordSettings settings);
IResponseBuilder WithProxy([NotNull] ProxyAndRecordSettings settings);
}
}

View File

@@ -10,7 +10,7 @@ namespace WireMock.ResponseBuilders
{
/// <summary>
/// The with status code.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
@@ -18,7 +18,7 @@ namespace WireMock.ResponseBuilders
/// <summary>
/// The with status code.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
@@ -26,7 +26,7 @@ namespace WireMock.ResponseBuilders
/// <summary>
/// The with status code.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// By default all status codes are allowed, to change this behaviour, see <inheritdoc cref="WireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>.
/// </summary>
/// <param name="code">The code.</param>
/// <returns>The <see cref="IResponseBuilder"/>.</returns>

View File

@@ -1,4 +1,4 @@
using System.Net.Http;
using System.Net.Http;
using WireMock.Http;
using WireMock.Settings;
using Stef.Validation;
@@ -12,7 +12,7 @@ namespace WireMock.ResponseBuilders
/// <summary>
/// The WebProxy settings.
/// </summary>
public IProxyAndRecordSettings ProxyAndRecordSettings { get; private set; }
public ProxyAndRecordSettings ProxyAndRecordSettings { get; private set; }
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(string, string)"/>
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null)
@@ -28,8 +28,8 @@ namespace WireMock.ResponseBuilders
return WithProxy(settings);
}
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(IProxyAndRecordSettings)"/>
public IResponseBuilder WithProxy(IProxyAndRecordSettings settings)
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(ProxyAndRecordSettings)"/>
public IResponseBuilder WithProxy(ProxyAndRecordSettings settings)
{
Guard.NotNull(settings, nameof(settings));

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;
@@ -385,8 +383,8 @@ namespace WireMock.ResponseBuilders
return this;
}
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IWireMockServerSettings)"/>
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, WireMockServerSettings)"/>
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
{
Guard.NotNull(requestMessage, nameof(requestMessage));
Guard.NotNull(settings, nameof(settings));

View File

@@ -13,7 +13,7 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc;
}
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage).ConfigureAwait(false), null);
}

View File

@@ -1,4 +1,4 @@
using System;
using System;
using System.Threading.Tasks;
using WireMock.Settings;
@@ -13,7 +13,7 @@ namespace WireMock.ResponseProviders
_responseMessageFunc = responseMessageFunc;
}
public Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
public Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
{
(ResponseMessage responseMessage, IMapping mapping) result = (_responseMessageFunc(requestMessage), null);
return Task.FromResult(result);

View File

@@ -17,6 +17,6 @@ namespace WireMock.ResponseProviders
/// <param name="requestMessage">The request.</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] IWireMockServerSettings settings);
Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync([NotNull] RequestMessage requestMessage, [NotNull] WireMockServerSettings settings);
}
}

View File

@@ -6,16 +6,16 @@ namespace WireMock.ResponseProviders
{
internal class ProxyAsyncResponseProvider : IResponseProvider
{
private readonly Func<RequestMessage, IWireMockServerSettings, Task<ResponseMessage>> _responseMessageFunc;
private readonly IWireMockServerSettings _settings;
private readonly Func<RequestMessage, WireMockServerSettings, Task<ResponseMessage>> _responseMessageFunc;
private readonly WireMockServerSettings _settings;
public ProxyAsyncResponseProvider(Func<RequestMessage, IWireMockServerSettings, Task<ResponseMessage>> responseMessageFunc, IWireMockServerSettings settings)
public ProxyAsyncResponseProvider(Func<RequestMessage, WireMockServerSettings, Task<ResponseMessage>> responseMessageFunc, WireMockServerSettings settings)
{
_responseMessageFunc = responseMessageFunc;
_settings = settings;
}
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
public async Task<(ResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(RequestMessage requestMessage, WireMockServerSettings settings)
{
return (await _responseMessageFunc(requestMessage, _settings).ConfigureAwait(false), null);
}

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)
@@ -209,7 +211,7 @@ namespace WireMock.Serialization
return mappingModel;
}
private static WebProxyModel MapWebProxy(IWebProxySettings settings)
private static WebProxyModel MapWebProxy(WebProxySettings settings)
{
return settings != null ? new WebProxyModel
{

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;
@@ -8,18 +9,19 @@ namespace WireMock.Serialization
{
internal class MappingToFileSaver
{
private readonly IWireMockServerSettings _settings;
private readonly WireMockServerSettings _settings;
private readonly MappingConverter _mappingConverter;
public MappingToFileSaver(IWireMockServerSettings settings, MappingConverter mappingConverter)
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

@@ -15,9 +15,9 @@ namespace WireMock.Serialization
{
internal class MatcherMapper
{
private readonly IWireMockServerSettings _settings;
private readonly WireMockServerSettings _settings;
public MatcherMapper(IWireMockServerSettings settings)
public MatcherMapper(WireMockServerSettings settings)
{
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
}
@@ -54,7 +54,7 @@ namespace WireMock.Serialization
return PluginLoader.Load<ICSharpCodeMatcher>(matchBehaviour, stringPatterns);
}
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because IWireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
throw new NotSupportedException("It's not allowed to use the 'CSharpCodeMatcher' because WireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
case nameof(LinqMatcher):
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);

View File

@@ -10,6 +10,7 @@ using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
using Stef.Validation;
using WireMock.Constants;
namespace WireMock.Server
{
@@ -27,7 +28,7 @@ namespace WireMock.Server
private int _timesInSameState = 1;
private readonly RegistrationCallback _registrationCallback;
private readonly IRequestMatcher _requestMatcher;
private readonly IWireMockServerSettings _settings;
private readonly WireMockServerSettings _settings;
private readonly bool _saveToFile;
public Guid Guid { get; private set; } = Guid.NewGuid();
@@ -43,7 +44,7 @@ namespace WireMock.Server
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher, IWireMockServerSettings settings, bool saveToFile = false)
public RespondWithAProvider(RegistrationCallback registrationCallback, IRequestMatcher requestMatcher, WireMockServerSettings settings, bool saveToFile = false)
{
_registrationCallback = registrationCallback;
_requestMatcher = requestMatcher;

File diff suppressed because it is too large Load Diff

View File

@@ -7,6 +7,7 @@ using System.Linq;
using System.Threading;
using JetBrains.Annotations;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Admin.Mappings;
using WireMock.Authentication;
using WireMock.Exceptions;
@@ -18,505 +19,513 @@ using WireMock.RequestBuilders;
using WireMock.ResponseProviders;
using WireMock.Serialization;
using WireMock.Settings;
using Stef.Validation;
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 IWireMockServerSettings _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 cref="IWireMockServer.Ports" />
[PublicAPI]
public List<int> Ports { get; }
return new WireMockServer(settings);
}
/// <inheritdoc cref="IWireMockServer.Urls" />
[PublicAPI]
public string[] Urls { get; }
/// <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] IWireMockServerSettings 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(IWireMockServerSettings 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

@@ -1,17 +1,24 @@
namespace WireMock.Settings
namespace WireMock.Settings
{
/// <summary>
/// HttpClientSettings
/// </summary>
public class HttpClientSettings : IHttpClientSettings
public class HttpClientSettings
{
/// <inheritdoc cref="IHttpClientSettings.ClientX509Certificate2ThumbprintOrSubjectName"/>
/// <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; }
/// <inheritdoc cref="IHttpClientSettings.WebProxySettings"/>
public IWebProxySettings WebProxySettings { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
public WebProxySettings WebProxySettings { get; set; }
/// <inheritdoc cref="IHttpClientSettings.AllowAutoRedirect"/>
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
public bool? AllowAutoRedirect { get; set; }
}
}

View File

@@ -1,24 +0,0 @@
namespace WireMock.Settings
{
/// <summary>
/// IHttpClientSettings
/// </summary>
public interface IHttpClientSettings
{
/// <summary>
/// The clientCertificate thumbprint or subject name fragment to use.
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
/// </summary>
string ClientX509Certificate2ThumbprintOrSubjectName { get; set; }
/// <summary>
/// Defines the WebProxySettings.
/// </summary>
IWebProxySettings WebProxySettings { get; set; }
/// <summary>
/// Proxy requests should follow redirection (30x).
/// </summary>
bool? AllowAutoRedirect { get; set; }
}
}

View File

@@ -1,42 +0,0 @@
using JetBrains.Annotations;
namespace WireMock.Settings
{
/// <summary>
/// IProxyAndRecordSettings
/// </summary>
public interface IProxyAndRecordSettings : IHttpClientSettings
{
/// <summary>
/// The URL to proxy.
/// </summary>
string Url { get; set; }
/// <summary>
/// Save the mapping for each request/response to the internal Mappings.
/// </summary>
bool SaveMapping { 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>
[CanBeNull]
string SaveMappingForStatusCodePattern { get; set; }
/// <summary>
/// Save the mapping for each request/response to a .json mapping file.
/// </summary>
bool SaveMappingToFile { get; set; }
/// <summary>
/// Defines a list from headers which will be excluded from the saved mappings.
/// </summary>
string[] ExcludedHeaders { get; set; }
/// <summary>
/// Defines a list of cookies which will be excluded from the saved mappings.
/// </summary>
string[] ExcludedCookies { get; set; }
}
}

View File

@@ -1,9 +0,0 @@
namespace WireMock.Settings
{
/// <summary>
/// IWebhookSettings
/// </summary>
public interface IWebhookSettings : IHttpClientSettings
{
}
}

View File

@@ -1,44 +0,0 @@
namespace WireMock.Settings
{
/// <summary>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
///
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
public interface IWireMockCertificateSettings
{
/// <summary>
/// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher)
/// </summary>
string X509StoreName { get; set; }
/// <summary>
/// X509 StoreLocation (CurrentUser or LocalMachine)
/// </summary>
string X509StoreLocation { get; set; }
/// <summary>
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
/// </summary>
string X509StoreThumbprintOrSubjectName { get; set; }
/// <summary>
/// X509Certificate FilePath
/// </summary>
string X509CertificateFilePath { get; set; }
/// <summary>
/// X509Certificate Password
/// </summary>
string X509CertificatePassword { get; set; }
/// <summary>
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
bool IsDefined { get; }
}
}

View File

@@ -1,249 +0,0 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using HandlebarsDotNet;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Admin.Mappings;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.RegularExpressions;
#if USE_ASPNETCORE
using Microsoft.Extensions.DependencyInjection;
using WireMock.Types;
#endif
namespace WireMock.Settings
{
/// <summary>
/// IWireMockServerSettings
/// </summary>
public interface IWireMockServerSettings
{
/// <summary>
/// Gets or sets the port.
/// </summary>
[PublicAPI]
int? Port { get; set; }
/// <summary>
/// Gets or sets the use SSL.
/// </summary>
// ReSharper disable once InconsistentNaming
[PublicAPI]
bool? UseSSL { get; set; }
/// <summary>
/// Gets or sets whether to start admin interface.
/// </summary>
[PublicAPI]
bool? StartAdminInterface { get; set; }
/// <summary>
/// Gets or sets if the static mappings should be read at startup.
/// </summary>
[PublicAPI]
bool? ReadStaticMappings { get; set; }
/// <summary>
/// Watch the static mapping files + folder for changes when running.
/// </summary>
[PublicAPI]
bool? WatchStaticMappings { get; set; }
/// <summary>
/// A value indicating whether subdirectories within the static mappings path should be monitored.
/// </summary>
[PublicAPI]
bool? WatchStaticMappingsInSubdirectories { get; set; }
/// <summary>
/// Gets or sets if the proxy and record settings.
/// </summary>
[PublicAPI]
IProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
/// <summary>
/// Gets or sets the urls.
/// </summary>
[PublicAPI]
string[] Urls { get; set; }
/// <summary>
/// StartTimeout
/// </summary>
[PublicAPI]
int StartTimeout { get; set; }
/// <summary>
/// Allow Partial Mapping (default set to false).
/// </summary>
[PublicAPI]
bool? AllowPartialMapping { get; set; }
/// <summary>
/// The username needed for __admin access.
/// </summary>
[PublicAPI]
string AdminUsername { get; set; }
/// <summary>
/// The password needed for __admin access.
/// </summary>
[PublicAPI]
string AdminPassword { get; set; }
/// <summary>
/// The AzureAD Tenant needed for __admin access.
/// </summary>
[PublicAPI]
string AdminAzureADTenant { get; set; }
/// <summary>
/// The AzureAD Audience / Resource for __admin access.
/// </summary>
[PublicAPI]
string AdminAzureADAudience { get; set; }
/// <summary>
/// The RequestLog expiration in hours (optional).
/// </summary>
[PublicAPI]
int? RequestLogExpirationDuration { get; set; }
/// <summary>
/// The MaxRequestLog count (optional).
/// </summary>
[PublicAPI]
int? MaxRequestLogCount { get; set; }
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
Action<object> PreWireMockMiddlewareInit { get; set; }
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
Action<object> PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE
/// <summary>
/// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional]
/// </summary>
[PublicAPI]
Action<IServiceCollection> AdditionalServiceRegistration { get; set; }
/// <summary>
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
/// </summary>
[PublicAPI]
CorsPolicyOptions? CorsPolicyOptions { get; set; }
#endif
/// <summary>
/// The IWireMockLogger which logs Debug, Info, Warning or Error
/// </summary>
[PublicAPI]
IWireMockLogger Logger { get; set; }
/// <summary>
/// Handler to interact with the file system to read and write static mapping files.
/// </summary>
[PublicAPI]
IFileSystemHandler FileSystemHandler { get; set; }
/// <summary>
/// Action which can be used to add additional Handlebars registrations. [Optional]
/// </summary>
[PublicAPI]
Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
/// <summary>
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
/// </summary>
[PublicAPI]
bool? AllowCSharpCodeMatcher { get; set; }
/// <summary>
/// Allow a Body for all HTTP Methods. (default set to false).
/// </summary>
[PublicAPI]
bool? AllowBodyForAllHttpMethods { get; set; }
/// <summary>
/// Allow only a HttpStatus Code in the response which is defined. (default set to false).
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
/// </summary>
[PublicAPI]
bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
/// <summary>
/// Set to true to disable Json deserialization when processing requests. (default set to false).
/// </summary>
[PublicAPI]
bool? DisableJsonBodyParsing { get; set; }
/// <summary>
/// Disable support for GZip and Deflate request body decompression. (default set to false).
/// </summary>
[PublicAPI]
bool? DisableRequestBodyDecompressing { get; set; }
/// <summary>
/// Handle all requests synchronously. (default set to false).
/// </summary>
[PublicAPI]
bool? HandleRequestsSynchronously { get; set; }
/// <summary>
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to false).
/// </summary>
[PublicAPI]
bool? ThrowExceptionWhenMatcherFails { get; set; }
/// <summary>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
///
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
[PublicAPI]
IWireMockCertificateSettings CertificateSettings { get; set; }
/// <summary>
/// Defines if custom CertificateSettings are defined
/// </summary>
[PublicAPI]
bool CustomCertificateDefined { get; }
/// <summary>
/// Defines the global IWebhookSettings to use.
/// </summary>
[PublicAPI]
IWebhookSettings WebhookSettings { get; set; }
/// <summary>
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
/// </summary>
[PublicAPI]
bool? UseRegexExtended { get; set; }
/// <summary>
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to false).
/// </summary>
[PublicAPI]
bool? SaveUnmatchedRequests { get; set; }
/// <summary>
/// Custom matcher mappings for static mappings
/// </summary>
[PublicAPI, JsonIgnore]
IDictionary<string, Func<MatcherModel, IMatcher>> CustomMatcherMappings { get; set; }
}
}

View File

@@ -1,11 +1,11 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
namespace WireMock.Settings
{
/// <summary>
/// ProxyAndRecordSettings
/// </summary>
public class ProxyAndRecordSettings : HttpClientSettings, IProxyAndRecordSettings
public class ProxyAndRecordSettings : HttpClientSettings
{
/// <summary>
/// The URL to proxy.
@@ -32,12 +32,22 @@ namespace WireMock.Settings
[PublicAPI]
public string SaveMappingForStatusCodePattern { get; set; } = "*";
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedHeaders"/>
/// <summary>
/// Defines a list from headers which will be excluded from the saved mappings.
/// </summary>
[PublicAPI]
public string[] ExcludedHeaders { get; set; }
/// <inheritdoc cref="IProxyAndRecordSettings.ExcludedCookies"/>
/// <summary>
/// Defines a list of cookies which will be excluded from the saved mappings.
/// </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,19 +1,27 @@
using JetBrains.Annotations;
using JetBrains.Annotations;
namespace WireMock.Settings
{
/// <seealso cref="IWebProxySettings" />
public class WebProxySettings : IWebProxySettings
/// <summary>
/// WebProxySettings
/// </summary>
public class WebProxySettings
{
/// <inheritdoc cref="IWebProxySettings.Address"/>
/// <summary>
/// A string instance that contains the address of the proxy server.
/// </summary>
[PublicAPI]
public string Address { get; set; }
/// <inheritdoc cref="IWebProxySettings.UserName"/>
/// <summary>
/// The user name associated with the credentials.
/// </summary>
[PublicAPI]
public string UserName { get; set; }
/// <inheritdoc cref="IWebProxySettings.Password"/>
/// <summary>
/// The password for the user name associated with the credentials.
/// </summary>
[PublicAPI]
public string Password { get; set; }
}

View File

@@ -1,9 +1,9 @@
namespace WireMock.Settings
namespace WireMock.Settings
{
/// <summary>
/// WebhookSettings
/// </summary>
public class WebhookSettings : HttpClientSettings, IWebhookSettings
public class WebhookSettings : HttpClientSettings
{
}
}

View File

@@ -3,31 +3,49 @@ using JetBrains.Annotations;
namespace WireMock.Settings
{
/// <summary>
/// <see cref="IWireMockCertificateSettings"/>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
///
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
public class WireMockCertificateSettings : IWireMockCertificateSettings
public class WireMockCertificateSettings
{
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreName"/>
/// <summary>
/// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher)
/// </summary>
[PublicAPI]
public string X509StoreName { get; set; }
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreLocation"/>
/// <summary>
/// X509 StoreLocation (CurrentUser or LocalMachine)
/// </summary>
[PublicAPI]
public string X509StoreLocation { get; set; }
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreThumbprintOrSubjectName"/>
/// <summary>
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
/// </summary>
[PublicAPI]
public string X509StoreThumbprintOrSubjectName { get; set; }
/// <inheritdoc cref="IWireMockCertificateSettings.X509CertificateFilePath"/>
/// <summary>
/// X509Certificate FilePath
/// </summary>
[PublicAPI]
public string X509CertificateFilePath { get; set; }
/// <inheritdoc cref="IWireMockCertificateSettings.X509CertificatePassword"/>
/// <summary>
/// X509Certificate Password
/// </summary>
[PublicAPI]
public string X509CertificatePassword { get; set; }
/// <inheritdoc cref="IWireMockCertificateSettings.IsDefined"/>
/// <summary>
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
[PublicAPI]
public bool IsDefined =>
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||

View File

@@ -1,5 +1,6 @@
using System;
using System.Collections.Generic;
using System.Text.RegularExpressions;
using HandlebarsDotNet;
using JetBrains.Annotations;
using Newtonsoft.Json;
@@ -7,6 +8,7 @@ using WireMock.Admin.Mappings;
using WireMock.Handlers;
using WireMock.Logging;
using WireMock.Matchers;
using WireMock.RegularExpressions;
using WireMock.Types;
#if USE_ASPNETCORE
using Microsoft.Extensions.DependencyInjection;
@@ -17,157 +19,236 @@ namespace WireMock.Settings
/// <summary>
/// WireMockServerSettings
/// </summary>
public class WireMockServerSettings : IWireMockServerSettings
public class WireMockServerSettings
{
/// <inheritdoc cref="IWireMockServerSettings.Port"/>
/// <summary>
/// Gets or sets the port.
/// </summary>
[PublicAPI]
public int? Port { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.UseSSL"/>
/// <summary>
/// Gets or sets the use SSL.
/// </summary>
// ReSharper disable once InconsistentNaming
[PublicAPI]
public bool? UseSSL { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.StartAdminInterface"/>
/// <summary>
/// Gets or sets whether to start admin interface.
/// </summary>
[PublicAPI]
public bool? StartAdminInterface { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.ReadStaticMappings"/>
/// <summary>
/// Gets or sets if the static mappings should be read at startup.
/// </summary>
[PublicAPI]
public bool? ReadStaticMappings { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.WatchStaticMappings"/>
/// <summary>
/// Watch the static mapping files + folder for changes when running.
/// </summary>
[PublicAPI]
public bool? WatchStaticMappings { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.WatchStaticMappingsInSubdirectories"/>
/// <summary>
/// A value indicating whether subdirectories within the static mappings path should be monitored.
/// </summary>
[PublicAPI]
public bool? WatchStaticMappingsInSubdirectories { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.ProxyAndRecordSettings"/>
/// <summary>
/// Gets or sets if the proxy and record settings.
/// </summary>
[PublicAPI]
public IProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
public ProxyAndRecordSettings ProxyAndRecordSettings { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.Urls"/>
/// <summary>
/// Gets or sets the urls.
/// </summary>
[PublicAPI]
public string[] Urls { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.StartTimeout"/>
/// <summary>
/// StartTimeout
/// </summary>
[PublicAPI]
public int StartTimeout { get; set; } = 10000;
/// <inheritdoc cref="IWireMockServerSettings.AllowPartialMapping"/>
/// <summary>
/// Allow Partial Mapping (default set to false).
/// </summary>
[PublicAPI]
public bool? AllowPartialMapping { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminUsername"/>
/// <summary>
/// The username needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminUsername { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminPassword"/>
/// <summary>
/// The password needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminPassword { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminAzureADTenant"/>
/// <summary>
/// The AzureAD Tenant needed for __admin access.
/// </summary>
[PublicAPI]
public string AdminAzureADTenant { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AdminAzureADAudience"/>
/// <summary>
/// The AzureAD Audience / Resource for __admin access.
/// </summary>
[PublicAPI]
public string AdminAzureADAudience { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.RequestLogExpirationDuration"/>
/// <summary>
/// The RequestLog expiration in hours (optional).
/// </summary>
[PublicAPI]
public int? RequestLogExpirationDuration { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.MaxRequestLogCount"/>
/// <summary>
/// The MaxRequestLog count (optional).
/// </summary>
[PublicAPI]
public int? MaxRequestLogCount { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.PreWireMockMiddlewareInit"/>
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) before the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<object> PreWireMockMiddlewareInit { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.PostWireMockMiddlewareInit"/>
/// <summary>
/// Action which is called (with the IAppBuilder or IApplicationBuilder) after the internal WireMockMiddleware is initialized. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<object> PostWireMockMiddlewareInit { get; set; }
#if USE_ASPNETCORE
/// <inheritdoc cref="IWireMockServerSettings.AdditionalServiceRegistration"/>
/// <summary>
/// Action which is called with IServiceCollection when ASP.NET Core DI is being configured. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<IServiceCollection> AdditionalServiceRegistration { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.CorsPolicyOptions"/>
/// <summary>
/// Policies to use when using CORS. By default CORS is disabled. [Optional]
/// </summary>
[PublicAPI]
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
#endif
/// <inheritdoc cref="IWireMockServerSettings.Logger"/>
/// <summary>
/// The IWireMockLogger which logs Debug, Info, Warning or Error
/// </summary>
[PublicAPI]
[JsonIgnore]
public IWireMockLogger Logger { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.FileSystemHandler"/>
/// <summary>
/// Handler to interact with the file system to read and write static mapping files.
/// </summary>
[PublicAPI]
[JsonIgnore]
public IFileSystemHandler FileSystemHandler { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.HandlebarsRegistrationCallback"/>
/// <summary>
/// Action which can be used to add additional Handlebars registrations. [Optional]
/// </summary>
[PublicAPI]
[JsonIgnore]
public Action<IHandlebars, IFileSystemHandler> HandlebarsRegistrationCallback { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AllowCSharpCodeMatcher"/>
/// <summary>
/// Allow the usage of CSharpCodeMatcher (default is not allowed).
/// </summary>
[PublicAPI]
public bool? AllowCSharpCodeMatcher { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AllowBodyForAllHttpMethods"/>
/// <summary>
/// Allow a Body for all HTTP Methods. (default set to false).
/// </summary>
[PublicAPI]
public bool? AllowBodyForAllHttpMethods { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>
/// <summary>
/// Allow only a HttpStatus Code in the response which is defined. (default set to false).
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
/// </summary>
[PublicAPI]
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.DisableJsonBodyParsing"/>
/// <summary>
/// Set to true to disable Json deserialization when processing requests. (default set to false).
/// </summary>
[PublicAPI]
public bool? DisableJsonBodyParsing { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.DisableRequestBodyDecompressing"/>
/// <summary>
/// Disable support for GZip and Deflate request body decompression. (default set to false).
/// </summary>
[PublicAPI]
public bool? DisableRequestBodyDecompressing { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.HandleRequestsSynchronously"/>
/// <summary>
/// Handle all requests synchronously. (default set to false).
/// </summary>
[PublicAPI]
public bool? HandleRequestsSynchronously { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.ThrowExceptionWhenMatcherFails"/>
/// <summary>
/// Throw an exception when the <see cref="IMatcher"/> fails because of invalid input. (default set to false).
/// </summary>
[PublicAPI]
public bool? ThrowExceptionWhenMatcherFails { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.CertificateSettings"/>
/// <summary>
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
///
/// X509StoreName and X509StoreLocation should be defined
/// OR
/// X509CertificateFilePath and X509CertificatePassword should be defined
/// </summary>
[PublicAPI]
public IWireMockCertificateSettings CertificateSettings { get; set; }
public WireMockCertificateSettings CertificateSettings { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.CustomCertificateDefined"/>
/// <summary>
/// Defines if custom CertificateSettings are defined
/// </summary>
[PublicAPI]
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
/// <inheritdoc cref="IWireMockServerSettings.WebhookSettings"/>
/// <summary>
/// Defines the global IWebhookSettings to use.
/// </summary>
[PublicAPI]
public IWebhookSettings WebhookSettings { get; set; }
public WebhookSettings WebhookSettings { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.UseRegexExtended"/>
/// <summary>
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/> (default set to true).
/// </summary>
[PublicAPI]
public bool? UseRegexExtended { get; set; } = true;
/// <inheritdoc cref="IWireMockServerSettings.SaveUnmatchedRequests"/>
/// <summary>
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/> (default set to false).
/// </summary>
[PublicAPI]
public bool? SaveUnmatchedRequests { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.CustomMatcherMappings"/>
/// <summary>
/// Custom matcher mappings for static mappings
/// </summary>
[PublicAPI, JsonIgnore]
public IDictionary<string, Func<MatcherModel, IMatcher>> CustomMatcherMappings { get; set; }
}

View File

@@ -1,5 +1,4 @@
using System;
using System.Linq;
using JetBrains.Annotations;
using Stef.Validation;
using WireMock.Logging;
@@ -8,7 +7,7 @@ using WireMock.Types;
namespace WireMock.Settings
{
/// <summary>
/// A static helper class to parse commandline arguments into IWireMockServerSettings.
/// A static helper class to parse commandline arguments into WireMockServerSettings.
/// </summary>
public static class WireMockServerSettingsParser
{
@@ -19,7 +18,7 @@ namespace WireMock.Settings
/// <param name="logger">The logger (optional, can be null)</param>
/// <param name="settings">The parsed settings</param>
[PublicAPI]
public static bool TryParseArguments([NotNull] string[] args, out IWireMockServerSettings settings, [CanBeNull] IWireMockLogger logger = null)
public static bool TryParseArguments([NotNull] string[] args, out WireMockServerSettings settings, [CanBeNull] IWireMockLogger logger = null)
{
Guard.HasNoNulls(args, nameof(args));
@@ -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"),
AdminAzureADAudience = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADAudience)),
AdminAzureADTenant = parser.GetStringValue(nameof(WireMockServerSettings.AdminAzureADTenant)),
AdminPassword = parser.GetStringValue("AdminPassword"),
AdminAzureADTenant = parser.GetStringValue(nameof(IWireMockServerSettings.AdminAzureADTenant)),
AdminAzureADAudience = parser.GetStringValue(nameof(IWireMockServerSettings.AdminAzureADAudience)),
MaxRequestLogCount = parser.GetIntValue("MaxRequestLogCount"),
RequestLogExpirationDuration = parser.GetIntValue("RequestLogExpirationDuration"),
AllowCSharpCodeMatcher = parser.GetBoolValue("AllowCSharpCodeMatcher"),
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(IWireMockServerSettings.UseRegexExtended), true),
SaveUnmatchedRequests = parser.GetBoolValue(nameof(IWireMockServerSettings.SaveUnmatchedRequests)),
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
};
#if USE_ASPNETCORE
settings.CorsPolicyOptions = parser.GetValue(
nameof(IWireMockServerSettings.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>
@@ -60,11 +60,11 @@
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="Stef.Validation" Version="0.1.0" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.17" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.18" />
<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

@@ -11,7 +11,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
{
public class ResponseWithStatusCodeTests
{
private readonly Mock<IWireMockServerSettings> _settingsMock = new Mock<IWireMockServerSettings>();
private readonly Mock<WireMockServerSettings> _settingsMock = new Mock<WireMockServerSettings>();
private const string ClientIp = "::1";
[Theory]

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

@@ -52,14 +52,14 @@
<PackageReference Include="Moq" Version="4.16.1" />
<PackageReference Include="System.Threading" Version="4.3.0" />
<PackageReference Include="RestEase" Version="1.5.5" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.13" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.14" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NFluent" Version="2.7.2" />
<!--<PackageReference Include="OpenCover" Version="4.7.922" />-->
<!--<PackageReference Include="ReportGenerator" Version="4.8.1" />-->
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.17" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.2.18" />
<!--<PackageReference Include="StrongNamer" Version="0.2.5" />-->
<PackageReference Include="AnyOf" Version="0.3.0" />
<!--<PackageReference Include="TinyMapper" Version="3.0.3" />-->

View File

@@ -324,7 +324,7 @@ namespace WireMock.Net.Tests
Check.That(mappings).HasSize(2);
// when
var response = await new HttpClient().GetAsync("http://localhost:" + server.Ports[0] + "/1").ConfigureAwait(false);
var response = await new HttpClient().GetAsync("http://localhost:" + server.Port + "/1").ConfigureAwait(false);
// then
Check.That((int)response.StatusCode).IsEqualTo(400);

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]

View File

@@ -328,7 +328,7 @@ namespace WireMock.Net.Tests
var server = WireMockServer.StartWithAdminInterface();
// Act
var response = await new HttpClient().PostAsync($"{server.Urls[0]}/__admin/mappings", stringContent).ConfigureAwait(false);
var response = await new HttpClient().PostAsync($"{server.Url}/__admin/mappings", stringContent).ConfigureAwait(false);
// Assert
Check.That(response.StatusCode).Equals(HttpStatusCode.Created);