mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-23 17:28:55 +02:00
Add WireMock.org RestClient (#631)
* wip... * x * . * . * . * r * 1.4.21-preview-02 * 1.4.21-preview-03 * . * usings * wip * . * ut * . * . * . * tests * . * comments * readme
This commit is contained in:
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.4.20</VersionPrefix>
|
<VersionPrefix>1.4.21-preview-04</VersionPrefix>
|
||||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||||
|
|||||||
@@ -34,9 +34,11 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
|||||||
| **WireMock.Net** | [](https://www.nuget.org/packages/WireMock.Net) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
|
| **WireMock.Net** | [](https://www.nuget.org/packages/WireMock.Net) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
|
||||||
| **WireMock.Net.StandAlone** | [](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
|
| **WireMock.Net.StandAlone** | [](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
|
||||||
| **WireMock.Net.FluentAssertions** | [](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
|
| **WireMock.Net.FluentAssertions** | [](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
|
||||||
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
|
||||||
| **WireMock.Net.Matchers.CSharpCode** | [](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
|
| **WireMock.Net.Matchers.CSharpCode** | [](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
|
||||||
| **WireMock.Net.OpenApiParser** | [](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
|
| **WireMock.Net.OpenApiParser** | [](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
|
||||||
|
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
||||||
|
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||||
|
|
||||||
|
|
||||||
## Development
|
## Development
|
||||||
For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page.
|
For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page.
|
||||||
|
|||||||
@@ -92,6 +92,10 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure Pipelines", "Azure Pi
|
|||||||
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
|
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Org.RestClient", "src\WireMock.Org.RestClient\WireMock.Org.RestClient.csproj", "{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Org.Abstractions", "src\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj", "{3BA5109E-5F30-4CC2-B699-02EC82560AA6}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -214,6 +218,14 @@ Global
|
|||||||
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
{6580580B-1EFD-4922-B0EC-FF290DB279EE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -250,6 +262,8 @@ Global
|
|||||||
{6580580B-1EFD-4922-B0EC-FF290DB279EE} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{6580580B-1EFD-4922-B0EC-FF290DB279EE} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
{1DAEFF47-D117-4E95-8B3E-4F7C8B92011A} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
||||||
{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
||||||
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
<PackageReference Include="RestEase" Version="1.5.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -204,8 +204,8 @@
|
|||||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="RestEase, Version=1.4.10.0, Culture=neutral, processorArchitecture=MSIL">
|
<Reference Include="RestEase, Version=1.5.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\RestEase.1.4.10\lib\net45\RestEase.dll</HintPath>
|
<HintPath>..\..\packages\RestEase.1.5.5\lib\net45\RestEase.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
|
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
|
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
|
||||||
|
|||||||
@@ -59,7 +59,7 @@
|
|||||||
<package id="MimeKitLite" version="2.0.7" targetFramework="net461" />
|
<package id="MimeKitLite" version="2.0.7" targetFramework="net461" />
|
||||||
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
|
<package id="Newtonsoft.Json" version="11.0.2" targetFramework="net461" />
|
||||||
<package id="Owin" version="1.0" targetFramework="net461" />
|
<package id="Owin" version="1.0" targetFramework="net461" />
|
||||||
<package id="RestEase" version="1.4.10" targetFramework="net461" />
|
<package id="RestEase" version="1.5.5" targetFramework="net461" />
|
||||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
|
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
|
||||||
<package id="System.Buffers" version="4.5.0" targetFramework="net461" />
|
<package id="System.Buffers" version="4.5.0" targetFramework="net461" />
|
||||||
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />
|
<package id="System.Collections.Immutable" version="1.5.0" targetFramework="net461" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>Commonly used interfaces, models, enumerations and types.</Description>
|
<Description>Commonly used models, enumerations and types.</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net45;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net45;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
|
|
||||||
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
||||||
<PackageId>WireMock.Net.Abstractions</PackageId>
|
<PackageId>WireMock.Net.Abstractions</PackageId>
|
||||||
<PackageTags>wiremock;interfaces;models;classes;enumerations;types</PackageTags>
|
<PackageTags>wiremock;wiremock.org;interfaces;models;classes;enumerations;types</PackageTags>
|
||||||
<RootNamespace>WireMock</RootNamespace>
|
<RootNamespace>WireMock</RootNamespace>
|
||||||
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid>
|
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
@@ -33,11 +33,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2020.1.0" PrivateAssets="All" />
|
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
|
||||||
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
|
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
|
||||||
<PackageReference Include="FluentBuilder" Version="0.0.7">
|
<PackageReference Include="FluentBuilder" Version="0.0.11">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>A RestClient using RestEase to access the admin interface.</Description>
|
<Description>A RestClient using RestEase to access the admin interface.</Description>
|
||||||
@@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
<PackageReference Include="RestEase" Version="1.5.5" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,167 +1,167 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using SimMetrics.Net;
|
using SimMetrics.Net;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Plugin;
|
using WireMock.Plugin;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Validation;
|
using WireMock.Validation;
|
||||||
|
|
||||||
namespace WireMock.Serialization
|
namespace WireMock.Serialization
|
||||||
{
|
{
|
||||||
internal class MatcherMapper
|
internal class MatcherMapper
|
||||||
{
|
{
|
||||||
private readonly IWireMockServerSettings _settings;
|
private readonly IWireMockServerSettings _settings;
|
||||||
|
|
||||||
public MatcherMapper(IWireMockServerSettings settings)
|
public MatcherMapper(IWireMockServerSettings settings)
|
||||||
{
|
{
|
||||||
Check.NotNull(settings, nameof(settings));
|
Check.NotNull(settings, nameof(settings));
|
||||||
_settings = settings;
|
_settings = settings;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMatcher[] Map([CanBeNull] IEnumerable<MatcherModel> matchers)
|
public IMatcher[] Map([CanBeNull] IEnumerable<MatcherModel> matchers)
|
||||||
{
|
{
|
||||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public IMatcher Map([CanBeNull] MatcherModel matcher)
|
public IMatcher Map([CanBeNull] MatcherModel matcher)
|
||||||
{
|
{
|
||||||
if (matcher == null)
|
if (matcher == null)
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
string[] parts = matcher.Name.Split('.');
|
|
||||||
string matcherName = parts[0];
|
|
||||||
string matcherType = parts.Length > 1 ? parts[1] : null;
|
|
||||||
|
|
||||||
string[] stringPatterns = (matcher.Patterns != null ? matcher.Patterns : new[] { matcher.Pattern }).OfType<string>().ToArray();
|
|
||||||
MatchBehaviour matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
|
||||||
bool ignoreCase = matcher.IgnoreCase == true;
|
|
||||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
|
||||||
|
|
||||||
switch (matcherName)
|
|
||||||
{
|
{
|
||||||
case "NotNullOrEmptyMatcher":
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
string[] parts = matcher.Name.Split('.');
|
||||||
|
string matcherName = parts[0];
|
||||||
|
string matcherType = parts.Length > 1 ? parts[1] : null;
|
||||||
|
|
||||||
|
string[] stringPatterns = (matcher.Patterns != null ? matcher.Patterns : new[] { matcher.Pattern }).OfType<string>().ToArray();
|
||||||
|
MatchBehaviour matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||||
|
bool ignoreCase = matcher.IgnoreCase == true;
|
||||||
|
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||||
|
|
||||||
|
switch (matcherName)
|
||||||
|
{
|
||||||
|
case "NotNullOrEmptyMatcher":
|
||||||
return new NotNullOrEmptyMatcher(matchBehaviour);
|
return new NotNullOrEmptyMatcher(matchBehaviour);
|
||||||
|
|
||||||
case "CSharpCodeMatcher":
|
case "CSharpCodeMatcher":
|
||||||
if (_settings.AllowCSharpCodeMatcher == true)
|
if (_settings.AllowCSharpCodeMatcher == true)
|
||||||
{
|
{
|
||||||
return PluginLoader.Load<ICSharpCodeMatcher>(matchBehaviour, stringPatterns);
|
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 IWireMockServerSettings.AllowCSharpCodeMatcher is not set to 'true'.");
|
||||||
|
|
||||||
case "LinqMatcher":
|
case "LinqMatcher":
|
||||||
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
return new LinqMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||||
|
|
||||||
case "ExactMatcher":
|
case "ExactMatcher":
|
||||||
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
return new ExactMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||||
|
|
||||||
case "ExactObjectMatcher":
|
case "ExactObjectMatcher":
|
||||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "RegexMatcher":
|
case "RegexMatcher":
|
||||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "JsonMatcher":
|
case "JsonMatcher":
|
||||||
object value = matcher.Pattern ?? matcher.Patterns;
|
object value = matcher.Pattern ?? matcher.Patterns;
|
||||||
return new JsonMatcher(matchBehaviour, value, ignoreCase, throwExceptionWhenMatcherFails);
|
return new JsonMatcher(matchBehaviour, value, ignoreCase, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "JsonPartialMatcher":
|
case "JsonPartialMatcher":
|
||||||
object matcherValue = matcher.Pattern ?? matcher.Patterns;
|
object matcherValue = matcher.Pattern ?? matcher.Patterns;
|
||||||
return new JsonPartialMatcher(matchBehaviour, matcherValue, ignoreCase, throwExceptionWhenMatcherFails);
|
return new JsonPartialMatcher(matchBehaviour, matcherValue, ignoreCase, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "JsonPathMatcher":
|
case "JsonPathMatcher":
|
||||||
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||||
|
|
||||||
case "JmesPathMatcher":
|
case "JmesPathMatcher":
|
||||||
return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
return new JmesPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||||
|
|
||||||
case "XPathMatcher":
|
case "XPathMatcher":
|
||||||
return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
return new XPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||||
|
|
||||||
case "WildcardMatcher":
|
case "WildcardMatcher":
|
||||||
return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
return new WildcardMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "ContentTypeMatcher":
|
case "ContentTypeMatcher":
|
||||||
return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
return new ContentTypeMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case "SimMetricsMatcher":
|
case "SimMetricsMatcher":
|
||||||
SimMetricType type = SimMetricType.Levenstein;
|
SimMetricType type = SimMetricType.Levenstein;
|
||||||
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
|
||||||
{
|
{
|
||||||
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
|
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return new SimMetricsMatcher(matchBehaviour, stringPatterns, type, throwExceptionWhenMatcherFails);
|
return new SimMetricsMatcher(matchBehaviour, stringPatterns, type, throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
|
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
public MatcherModel[] Map([CanBeNull] IEnumerable<IMatcher> matchers)
|
||||||
{
|
{
|
||||||
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
return matchers?.Select(Map).Where(m => m != null).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
public MatcherModel Map([CanBeNull] IMatcher matcher)
|
public MatcherModel Map([CanBeNull] IMatcher matcher)
|
||||||
{
|
{
|
||||||
if (matcher == null)
|
if (matcher == null)
|
||||||
{
|
{
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
object[] patterns = new object[0]; // Default empty array
|
object[] patterns = new object[0]; // Default empty array
|
||||||
switch (matcher)
|
switch (matcher)
|
||||||
{
|
{
|
||||||
// If the matcher is a IStringMatcher, get the patterns.
|
// If the matcher is a IStringMatcher, get the patterns.
|
||||||
case IStringMatcher stringMatcher:
|
case IStringMatcher stringMatcher:
|
||||||
patterns = stringMatcher.GetPatterns().Cast<object>().ToArray();
|
patterns = stringMatcher.GetPatterns().Cast<object>().ToArray();
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
// If the matcher is a IValueMatcher, get the value (can be string or object).
|
||||||
case IValueMatcher valueMatcher:
|
case IValueMatcher valueMatcher:
|
||||||
patterns = new[] { valueMatcher.Value };
|
patterns = new[] { valueMatcher.Value };
|
||||||
break;
|
break;
|
||||||
|
|
||||||
// If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes.
|
// If the matcher is a ExactObjectMatcher, get the ValueAsObject or ValueAsBytes.
|
||||||
case ExactObjectMatcher exactObjectMatcher:
|
case ExactObjectMatcher exactObjectMatcher:
|
||||||
patterns = new[] { exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes };
|
patterns = new[] { exactObjectMatcher.ValueAsObject ?? exactObjectMatcher.ValueAsBytes };
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null;
|
bool? ignoreCase = matcher is IIgnoreCaseMatcher ignoreCaseMatcher ? ignoreCaseMatcher.IgnoreCase : (bool?)null;
|
||||||
|
|
||||||
bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : (bool?)null;
|
bool? rejectOnMatch = matcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : (bool?)null;
|
||||||
|
|
||||||
return new MatcherModel
|
return new MatcherModel
|
||||||
{
|
{
|
||||||
RejectOnMatch = rejectOnMatch,
|
RejectOnMatch = rejectOnMatch,
|
||||||
IgnoreCase = ignoreCase,
|
IgnoreCase = ignoreCase,
|
||||||
Name = matcher.Name,
|
Name = matcher.Name,
|
||||||
Pattern = patterns.Length == 1 ? patterns.First() : null,
|
Pattern = patterns.Length == 1 ? patterns.First() : null,
|
||||||
Patterns = patterns.Length > 1 ? patterns : null
|
Patterns = patterns.Length > 1 ? patterns : null
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, string stringPattern, bool throwException)
|
private ExactObjectMatcher CreateExactObjectMatcher(MatchBehaviour matchBehaviour, string stringPattern, bool throwException)
|
||||||
{
|
{
|
||||||
byte[] bytePattern;
|
byte[] bytePattern;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
bytePattern = Convert.FromBase64String(stringPattern);
|
bytePattern = Convert.FromBase64String(stringPattern);
|
||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern));
|
throw new ArgumentException($"Matcher 'ExactObjectMatcher' has invalid pattern. The pattern value '{stringPattern}' is not a Base64String.", nameof(stringPattern));
|
||||||
}
|
}
|
||||||
|
|
||||||
return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException);
|
return new ExactObjectMatcher(matchBehaviour, bytePattern, throwException);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -39,6 +39,7 @@ namespace WireMock.Server
|
|||||||
private const string ContentTypeJson = "application/json";
|
private const string ContentTypeJson = "application/json";
|
||||||
private const string AdminFiles = "/__admin/files";
|
private const string AdminFiles = "/__admin/files";
|
||||||
private const string AdminMappings = "/__admin/mappings";
|
private const string AdminMappings = "/__admin/mappings";
|
||||||
|
private const string AdminMappingsWireMockOrg = "/__admin/mappings/wiremock.org";
|
||||||
private const string AdminRequests = "/__admin/requests";
|
private const string AdminRequests = "/__admin/requests";
|
||||||
private const string AdminSettings = "/__admin/settings";
|
private const string AdminSettings = "/__admin/settings";
|
||||||
private const string AdminScenarios = "/__admin/scenarios";
|
private const string AdminScenarios = "/__admin/scenarios";
|
||||||
@@ -58,6 +59,7 @@ namespace WireMock.Server
|
|||||||
// __admin/mappings
|
// __admin/mappings
|
||||||
Given(Request.Create().WithPath(AdminMappings).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsGet));
|
Given(Request.Create().WithPath(AdminMappings).UsingGet()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsGet));
|
||||||
Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
|
Given(Request.Create().WithPath(AdminMappings).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPost));
|
||||||
|
Given(Request.Create().WithPath(AdminMappingsWireMockOrg).UsingPost().WithHeader(HttpKnownHeaderNames.ContentType, _adminRequestContentTypeJson)).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsPostWireMockOrg));
|
||||||
Given(Request.Create().WithPath(AdminMappings).UsingDelete()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
|
Given(Request.Create().WithPath(AdminMappings).UsingDelete()).AtPriority(AdminPriority).RespondWith(new DynamicResponseProvider(MappingsDelete));
|
||||||
|
|
||||||
// __admin/mappings/reset
|
// __admin/mappings/reset
|
||||||
|
|||||||
306
src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs
Normal file
306
src/WireMock.Net/Server/WireMockServer.ImportWireMockOrg.cs
Normal file
@@ -0,0 +1,306 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using JetBrains.Annotations;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
using WireMock.Matchers;
|
||||||
|
using WireMock.RequestBuilders;
|
||||||
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.Util;
|
||||||
|
using WireMock.Validation;
|
||||||
|
using OrgMapping = WireMock.Org.Abstractions.Mapping;
|
||||||
|
|
||||||
|
namespace WireMock.Server
|
||||||
|
{
|
||||||
|
public partial class WireMockServer
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Read WireMock.org mapping json file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The path to the WireMock.org mapping json file.</param>
|
||||||
|
[PublicAPI]
|
||||||
|
public void ReadStaticWireMockOrgMappingAndAddOrUpdate([NotNull] string path)
|
||||||
|
{
|
||||||
|
Check.NotNull(path, nameof(path));
|
||||||
|
|
||||||
|
string filenameWithoutExtension = Path.GetFileNameWithoutExtension(path);
|
||||||
|
|
||||||
|
if (FileHelper.TryReadMappingFileWithRetryAndDelay(_settings.FileSystemHandler, path, out string value))
|
||||||
|
{
|
||||||
|
var mappings = DeserializeJsonToArray<OrgMapping>(value);
|
||||||
|
foreach (var mapping in mappings)
|
||||||
|
{
|
||||||
|
if (mappings.Length == 1 && Guid.TryParse(filenameWithoutExtension, out Guid guidFromFilename))
|
||||||
|
{
|
||||||
|
ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mapping, guidFromFilename, path);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mapping, null, path);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private ResponseMessage MappingsPostWireMockOrg(RequestMessage requestMessage)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var mappingModels = DeserializeRequestMessageToArray<OrgMapping>(requestMessage);
|
||||||
|
if (mappingModels.Length == 1)
|
||||||
|
{
|
||||||
|
Guid? guid = ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModels[0]);
|
||||||
|
return ResponseMessageBuilder.Create("Mapping added", 201, guid);
|
||||||
|
}
|
||||||
|
|
||||||
|
foreach (var mappingModel in mappingModels)
|
||||||
|
{
|
||||||
|
ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModel);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ResponseMessageBuilder.Create("Mappings added", 201);
|
||||||
|
}
|
||||||
|
catch (ArgumentException a)
|
||||||
|
{
|
||||||
|
_settings.Logger.Error("HttpStatusCode set to 400 {0}", a);
|
||||||
|
return ResponseMessageBuilder.Create(a.Message, 400);
|
||||||
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
_settings.Logger.Error("HttpStatusCode set to 500 {0}", e);
|
||||||
|
return ResponseMessageBuilder.Create(e.ToString(), 500);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private Guid? ConvertWireMockOrgMappingAndRegisterAsRespondProvider(OrgMapping mapping, Guid? guid = null, string path = null)
|
||||||
|
{
|
||||||
|
var requestBuilder = Request.Create();
|
||||||
|
|
||||||
|
var request = mapping.Request;
|
||||||
|
if (request != null)
|
||||||
|
{
|
||||||
|
if (request.Url != null)
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithUrl(request.Url);
|
||||||
|
}
|
||||||
|
else if (request.UrlPattern != null)
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithUrl(new RegexMatcher(request.UrlPattern));
|
||||||
|
}
|
||||||
|
else if (request.UrlPath != null)
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithPath(request.Url);
|
||||||
|
}
|
||||||
|
else if (request.UrlPathPattern != null)
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithPath(new RegexMatcher(request.UrlPathPattern));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Method != null)
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.UsingMethod(request.Method);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
"headers" : {
|
||||||
|
"Accept" : {
|
||||||
|
"contains" : "xml"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (request.Headers is JObject headers)
|
||||||
|
{
|
||||||
|
ProcessWireMockOrgJObjectAndUseStringMatcher(headers, (key, match) =>
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithHeader(key, match as IStringMatcher);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (request.Cookies is JObject cookies)
|
||||||
|
{
|
||||||
|
ProcessWireMockOrgJObjectAndUseStringMatcher(cookies, (key, match) =>
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithCookie(key, match as IStringMatcher);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
"queryParameters" : {
|
||||||
|
"search_term" : {
|
||||||
|
"equalTo" : "WireMock"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
*/
|
||||||
|
if (request.QueryParameters is JObject queryParameters)
|
||||||
|
{
|
||||||
|
ProcessWireMockOrgJObjectAndUseStringMatcher(queryParameters, (key, match) =>
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithParam(key, match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
"bodyPatterns" : [ {
|
||||||
|
"equalToJson" : "{ "cityName": "São Paulo", "cityCode": 5001 },
|
||||||
|
"ignoreArrayOrder" : true,
|
||||||
|
"ignoreExtraElements" : true
|
||||||
|
} ]
|
||||||
|
*/
|
||||||
|
if (request.BodyPatterns?.Any() == true)
|
||||||
|
{
|
||||||
|
var jObjectArray = request.BodyPatterns.Cast<JObject>();
|
||||||
|
var bodyPattern = jObjectArray.First();
|
||||||
|
ProcessWireMockOrgJObjectAndUseIMatcher(bodyPattern, (match) =>
|
||||||
|
{
|
||||||
|
requestBuilder = requestBuilder.WithBody(match);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
IResponseBuilder responseBuilder = Response.Create();
|
||||||
|
|
||||||
|
var response = mapping.Response;
|
||||||
|
if (response != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithStatusCode(response.Status);
|
||||||
|
|
||||||
|
if (response.Headers is JObject responseHeaders)
|
||||||
|
{
|
||||||
|
ProcessWireMockOrgJObjectAndConvertToIDictionary(responseHeaders, (headers) =>
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithHeaders(headers);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Transformers != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithTransformer();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Body != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithBody(response.Body);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.JsonBody != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithBodyAsJson(response.JsonBody);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.Base64Body != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithBody(Encoding.UTF8.GetString(Convert.FromBase64String(response.Base64Body)));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (response.BodyFileName != null)
|
||||||
|
{
|
||||||
|
responseBuilder = responseBuilder.WithBodyFromFile(response.BodyFileName);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
var respondProvider = Given(requestBuilder);
|
||||||
|
if (guid != null)
|
||||||
|
{
|
||||||
|
respondProvider = respondProvider.WithGuid(guid.Value);
|
||||||
|
}
|
||||||
|
else if (!string.IsNullOrEmpty(mapping.Uuid))
|
||||||
|
{
|
||||||
|
respondProvider = respondProvider.WithGuid(new Guid(mapping.Uuid));
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapping.Name != null)
|
||||||
|
{
|
||||||
|
respondProvider = respondProvider.WithTitle(mapping.Name);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (path != null)
|
||||||
|
{
|
||||||
|
respondProvider = respondProvider.WithPath(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
respondProvider.RespondWith(responseBuilder);
|
||||||
|
|
||||||
|
return respondProvider.Guid;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessWireMockOrgJObjectAndConvertToIDictionary(JObject items, Action<IDictionary<string, string>> action)
|
||||||
|
{
|
||||||
|
var dict = new Dictionary<string, string>();
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var key = item.Key;
|
||||||
|
var valueAsString = item.Value.Value<string>();
|
||||||
|
dict.Add(key, valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
action(dict);
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessWireMockOrgJObjectAndUseStringMatcher(JObject items, Action<string, IStringMatcher> action)
|
||||||
|
{
|
||||||
|
foreach (var item in items)
|
||||||
|
{
|
||||||
|
var key = item.Key;
|
||||||
|
var match = item.Value.First as JProperty;
|
||||||
|
var valueAsString = match?.Value.Value<string>();
|
||||||
|
if (string.IsNullOrEmpty(valueAsString))
|
||||||
|
{
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
var matcher = ProcessAsStringMatcher(match, valueAsString);
|
||||||
|
if (matcher != null)
|
||||||
|
{
|
||||||
|
action(key, matcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void ProcessWireMockOrgJObjectAndUseIMatcher(JObject items, Action<IMatcher> action)
|
||||||
|
{
|
||||||
|
IMatcher matcher = null;
|
||||||
|
|
||||||
|
var firstItem = items.First as JProperty;
|
||||||
|
|
||||||
|
if (firstItem?.Name == "equalToJson")
|
||||||
|
{
|
||||||
|
matcher = new JsonMatcher(firstItem.Value);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var valueAsString = (firstItem.Value as JValue)?.Value as string;
|
||||||
|
if (valueAsString == null)
|
||||||
|
{
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
matcher = ProcessAsStringMatcher(firstItem, valueAsString);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (matcher != null)
|
||||||
|
{
|
||||||
|
action(matcher);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IStringMatcher ProcessAsStringMatcher(JProperty match, string valueAsString)
|
||||||
|
{
|
||||||
|
switch (match?.Name)
|
||||||
|
{
|
||||||
|
case "contains":
|
||||||
|
return new WildcardMatcher(valueAsString);
|
||||||
|
|
||||||
|
case "matches":
|
||||||
|
return new RegexMatcher(valueAsString);
|
||||||
|
|
||||||
|
case "equalTo":
|
||||||
|
return new ExactMatcher(valueAsString);
|
||||||
|
|
||||||
|
default:
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -132,5 +132,6 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
12
src/WireMock.Org.Abstractions/BasicAuthCredentials.cs
Normal file
12
src/WireMock.Org.Abstractions/BasicAuthCredentials.cs
Normal file
@@ -0,0 +1,12 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Pre-emptive basic auth credentials to match against
|
||||||
|
/// </summary>
|
||||||
|
public class BasicAuthCredentials
|
||||||
|
{
|
||||||
|
public string Password { get; set; }
|
||||||
|
|
||||||
|
public string Username { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class GetAdminMappingsResponse
|
||||||
|
{
|
||||||
|
public Mapping[] Mappings { get; set; }
|
||||||
|
|
||||||
|
public Meta Meta { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class GetAdminRecordingsStatusResponse
|
||||||
|
{
|
||||||
|
public string Status { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class GetAdminRequestsUnmatchedNearMissesResponse
|
||||||
|
{
|
||||||
|
public NearMiss[] NearMisses { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class GetAdminScenariosResponse
|
||||||
|
{
|
||||||
|
public Scenario[] Scenarios { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
59
src/WireMock.Org.Abstractions/Mapping.cs
Normal file
59
src/WireMock.Org.Abstractions/Mapping.cs
Normal file
@@ -0,0 +1,59 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class Mapping
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// This stub mapping's unique identifier
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Alias for the id
|
||||||
|
/// </summary>
|
||||||
|
public string Uuid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The stub mapping's name
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public Request Request { get; set; }
|
||||||
|
|
||||||
|
public Response Response { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Indicates that the stub mapping should be persisted immediately on create/update/delete and survive resets to default.
|
||||||
|
/// </summary>
|
||||||
|
public bool Persistent { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// This stub mapping's priority relative to others. 1 is highest.
|
||||||
|
/// </summary>
|
||||||
|
public int Priority { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The name of the scenario that this stub mapping is part of
|
||||||
|
/// </summary>
|
||||||
|
public string ScenarioName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The required state of the scenario in order for this stub to be matched.
|
||||||
|
/// </summary>
|
||||||
|
public string RequiredScenarioState { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The new state for the scenario to be updated to after this stub is served.
|
||||||
|
/// </summary>
|
||||||
|
public string NewScenarioState { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A map of the names of post serve action extensions to trigger and their parameters.
|
||||||
|
/// </summary>
|
||||||
|
public object PostServeActions { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Arbitrary metadata to be used for e.g. tagging, documentation. Can also be used to find and remove stubs.
|
||||||
|
/// </summary>
|
||||||
|
public object Metadata { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
7
src/WireMock.Org.Abstractions/Meta.cs
Normal file
7
src/WireMock.Org.Abstractions/Meta.cs
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class Meta
|
||||||
|
{
|
||||||
|
public int Total { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
35
src/WireMock.Org.Abstractions/NearMiss.cs
Normal file
35
src/WireMock.Org.Abstractions/NearMiss.cs
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class NearMiss
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The HTTP request method
|
||||||
|
/// </summary>
|
||||||
|
public string Method { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path and query to match exactly against
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The full URL to match against
|
||||||
|
/// </summary>
|
||||||
|
public string AbsoluteUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object Headers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cookie patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object Cookies { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Body string to match against
|
||||||
|
/// </summary>
|
||||||
|
public string Body { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,7 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class PostAdminRequestsCountResponse
|
||||||
|
{
|
||||||
|
public int Count { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
55
src/WireMock.Org.Abstractions/Request.cs
Normal file
55
src/WireMock.Org.Abstractions/Request.cs
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class Request
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The HTTP request method e.g. GET
|
||||||
|
/// </summary>
|
||||||
|
public string Method { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path and query to match exactly against. Only one of url, urlPattern, urlPath or urlPathPattern may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string Url { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path to match exactly against. Only one of url, urlPattern, urlPath or urlPathPattern may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string UrlPath { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path regex to match against. Only one of url, urlPattern, urlPath or urlPathPattern may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string UrlPathPattern { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path and query regex to match against. Only one of url, urlPattern, urlPath or urlPathPattern may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string UrlPattern { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Query parameter patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object QueryParameters { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Header patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object Headers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Pre-emptive basic auth credentials to match against
|
||||||
|
/// </summary>
|
||||||
|
public BasicAuthCredentials BasicAuthCredentials { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Cookie patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object Cookies { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Request body patterns to match against in the <key>: { "<predicate>": "<value>" } form
|
||||||
|
/// </summary>
|
||||||
|
public object[] BodyPatterns { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
75
src/WireMock.Org.Abstractions/Response.cs
Normal file
75
src/WireMock.Org.Abstractions/Response.cs
Normal file
@@ -0,0 +1,75 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class Response
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The HTTP status code to be returned
|
||||||
|
/// </summary>
|
||||||
|
public int Status { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The HTTP status message to be returned
|
||||||
|
/// </summary>
|
||||||
|
public string StatusMessage { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Map of response headers to send
|
||||||
|
/// </summary>
|
||||||
|
public object Headers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Extra request headers to send when proxying to another host.
|
||||||
|
/// </summary>
|
||||||
|
public object AdditionalProxyRequestHeaders { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The response body as a string. Only one of body, base64Body, jsonBody or bodyFileName may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string Body { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The response body as a base64 encoded string (useful for binary content). Only one of body, base64Body, jsonBody or bodyFileName may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string Base64Body { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The response body as a JSON object. Only one of body, base64Body, jsonBody or bodyFileName may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public object JsonBody { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The path to the file containing the response body, relative to the configured file root. Only one of body, base64Body, jsonBody or bodyFileName may be specified.
|
||||||
|
/// </summary>
|
||||||
|
public string BodyFileName { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The fault to apply (instead of a full, valid response).
|
||||||
|
/// </summary>
|
||||||
|
public string Fault { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Number of milliseconds to delay be before sending the response.
|
||||||
|
/// </summary>
|
||||||
|
public int FixedDelayMilliseconds { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Read-only flag indicating false if this was the default, unmatched response. Not present otherwise.
|
||||||
|
/// </summary>
|
||||||
|
public bool FromConfiguredStub { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The base URL of the target to proxy matching requests to.
|
||||||
|
/// </summary>
|
||||||
|
public string ProxyBaseUrl { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parameters to apply to response transformers.
|
||||||
|
/// </summary>
|
||||||
|
public object TransformerParameters { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// List of names of transformers to apply to this response.
|
||||||
|
/// </summary>
|
||||||
|
public string Transformers { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
14
src/WireMock.Org.Abstractions/ResponseLogNormal.cs
Normal file
14
src/WireMock.Org.Abstractions/ResponseLogNormal.cs
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Log normal randomly distributed response delay.
|
||||||
|
/// </summary>
|
||||||
|
public class ResponseLogNormal
|
||||||
|
{
|
||||||
|
public int Median { get; set; }
|
||||||
|
|
||||||
|
public double Sigma { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Uniformly distributed random response delay.
|
||||||
|
/// </summary>
|
||||||
|
public class ResponseLogUniformlyDistributed
|
||||||
|
{
|
||||||
|
public int Lower { get; set; }
|
||||||
|
|
||||||
|
public string Type { get; set; }
|
||||||
|
|
||||||
|
public int Upper { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
22
src/WireMock.Org.Abstractions/Scenario.cs
Normal file
22
src/WireMock.Org.Abstractions/Scenario.cs
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
namespace WireMock.Org.Abstractions
|
||||||
|
{
|
||||||
|
public class Scenario
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The scenario ID
|
||||||
|
/// </summary>
|
||||||
|
public string Id { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The scenario name
|
||||||
|
/// </summary>
|
||||||
|
public string Name { get; set; }
|
||||||
|
|
||||||
|
public string PossibleStates { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The current state of this scenario
|
||||||
|
/// </summary>
|
||||||
|
public string State { get; set; }
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,41 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>Commonly used interfaces, models, enumerations and types.</Description>
|
||||||
|
<AssemblyTitle>WireMock.Org.Abstractions</AssemblyTitle>
|
||||||
|
<Authors>Stef Heyenrath</Authors>
|
||||||
|
<TargetFrameworks>net45;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
|
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<NoWarn>$(NoWarn);1591;8603</NoWarn>
|
||||||
|
|
||||||
|
<AssemblyName>WireMock.Org.Abstractions</AssemblyName>
|
||||||
|
<PackageId>WireMock.Org.Abstractions</PackageId>
|
||||||
|
<PackageTags>wiremock;wiremock.org;interfaces;models;classes;enumerations;types</PackageTags>
|
||||||
|
<RootNamespace>WireMock</RootNamespace>
|
||||||
|
<ProjectGuid>{3BA5109E-5F30-4CC2-B699-02EC82560AA6}</ProjectGuid>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
|
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<!--<DelaySign>true</DelaySign>-->
|
||||||
|
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<!--<PackageReference Include="AnyOf" Version="0.0.23" />-->
|
||||||
|
<PackageReference Include="JetBrains.Annotations" Version="2021.2.0" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
6332
src/WireMock.Org.Abstractions/wiremock.org.json
Normal file
6332
src/WireMock.Org.Abstractions/wiremock.org.json
Normal file
File diff suppressed because it is too large
Load Diff
232
src/WireMock.Org.RestClient/IWireMockOrgApi.cs
Normal file
232
src/WireMock.Org.RestClient/IWireMockOrgApi.cs
Normal file
@@ -0,0 +1,232 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using RestEase;
|
||||||
|
using WireMock.Org.Abstractions;
|
||||||
|
|
||||||
|
namespace WireMock.Org.RestClient
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// WireMockOrg
|
||||||
|
/// </summary>
|
||||||
|
public interface IWireMockOrgApi
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get all stub mappings
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="limit">The maximum number of results to return</param>
|
||||||
|
/// <param name="offset">The start index of the results to return</param>
|
||||||
|
[Get("/__admin/mappings")]
|
||||||
|
Task<GetAdminMappingsResponse> GetAdminMappingsAsync([Query] int? limit, [Query] int? offset);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a new stub mapping
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/mappings")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<Mapping> PostAdminMappingsAsync([Body] Mapping request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete all stub mappings
|
||||||
|
/// </summary>
|
||||||
|
[Delete("/__admin/mappings")]
|
||||||
|
Task DeleteAdminMappingsAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset stub mappings
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/mappings/reset")]
|
||||||
|
Task PostAdminMappingsResetAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Persist stub mappings
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/mappings/save")]
|
||||||
|
Task PostAdminMappingsSaveAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get stub mapping by ID
|
||||||
|
/// </summary>
|
||||||
|
[Get("/__admin/mappings/{stubMappingId}")]
|
||||||
|
Task<Mapping> GetAdminMappingsByStubMappingIdAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update a stub mapping
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Put("/__admin/mappings/{stubMappingId}")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<Mapping> PutAdminMappingsByStubMappingIdAsync([Body] Mapping request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete a stub mapping
|
||||||
|
/// </summary>
|
||||||
|
[Delete("/__admin/mappings/{stubMappingId}")]
|
||||||
|
Task DeleteAdminMappingsByStubMappingIdAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PostAdminMappingsFindByMetadata (/__admin/mappings/find-by-metadata)
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/mappings/find-by-metadata")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<GetAdminMappingsResponse> PostAdminMappingsFindByMetadataAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete stub mappings matching metadata
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/mappings/remove-by-metadata")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminMappingsRemoveByMetadataAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all requests in journal
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="limit">The maximum number of results to return</param>
|
||||||
|
/// <param name="since">Only return logged requests after this date</param>
|
||||||
|
[Get("/__admin/requests")]
|
||||||
|
Task GetAdminRequestsAsync([Query] string limit, [Query] string since);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete all requests in journal
|
||||||
|
/// </summary>
|
||||||
|
[Delete("/__admin/requests")]
|
||||||
|
Task DeleteAdminRequestsAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get request by ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestId">The UUID of the logged request</param>
|
||||||
|
[Get("/__admin/requests/{requestId}")]
|
||||||
|
Task GetAdminRequestsByRequestIdAsync([Path] string requestId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete request by ID
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestId">The UUID of the logged request</param>
|
||||||
|
[Delete("/__admin/requests/{requestId}")]
|
||||||
|
Task DeleteAdminRequestsByRequestIdAsync([Path] string requestId);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Empty the request journal
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/requests/reset")]
|
||||||
|
Task PostAdminRequestsResetAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Count requests by criteria
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/requests/count")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<PostAdminRequestsCountResponse> PostAdminRequestsCountAsync([Body] Request request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Remove requests by criteria
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/requests/remove")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminRequestsRemoveAsync([Body] Request request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete requests mappings matching metadata
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/requests/remove-by-metadata")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminRequestsRemoveByMetadataAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find requests by criteria
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/requests/find")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminRequestsFindAsync([Body] Request request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find unmatched requests
|
||||||
|
/// </summary>
|
||||||
|
[Get("/__admin/requests/unmatched")]
|
||||||
|
Task GetAdminRequestsUnmatchedAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// GetAdminRequestsUnmatchedNearMisses (/__admin/requests/unmatched/near-misses)
|
||||||
|
/// </summary>
|
||||||
|
[Get("/__admin/requests/unmatched/near-misses")]
|
||||||
|
Task<GetAdminRequestsUnmatchedNearMissesResponse> GetAdminRequestsUnmatchedNearMissesAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find near misses matching specific request
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/near-misses/request")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<GetAdminRequestsUnmatchedNearMissesResponse> PostAdminNearMissesRequestAsync([Body] NearMiss request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Find near misses matching request pattern
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/near-misses/request-pattern")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<GetAdminRequestsUnmatchedNearMissesResponse> PostAdminNearMissesRequestPatternAsync([Body] Request request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Start recording
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/recordings/start")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminRecordingsStartAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Stop recording
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/recordings/stop")]
|
||||||
|
Task<GetAdminMappingsResponse> PostAdminRecordingsStopAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get recording status
|
||||||
|
/// </summary>
|
||||||
|
[Get("/__admin/recordings/status")]
|
||||||
|
Task<GetAdminRecordingsStatusResponse> GetAdminRecordingsStatusAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Take a snapshot recording
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="request"></param>
|
||||||
|
[Post("/__admin/recordings/snapshot")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<GetAdminMappingsResponse> PostAdminRecordingsSnapshotAsync([Body] object request);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get all scenarios
|
||||||
|
/// </summary>
|
||||||
|
[Get("/__admin/scenarios")]
|
||||||
|
Task<GetAdminScenariosResponse> GetAdminScenariosAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset the state of all scenarios
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/scenarios/reset")]
|
||||||
|
Task PostAdminScenariosResetAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Update global settings
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/settings")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task PostAdminSettingsAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Reset mappings and request journal
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/reset")]
|
||||||
|
Task PostAdminResetAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// PostAdminShutdown (/__admin/shutdown)
|
||||||
|
/// </summary>
|
||||||
|
[Post("/__admin/shutdown")]
|
||||||
|
Task PostAdminShutdownAsync();
|
||||||
|
}
|
||||||
|
}
|
||||||
41
src/WireMock.Org.RestClient/WireMock.Org.RestClient.csproj
Normal file
41
src/WireMock.Org.RestClient/WireMock.Org.RestClient.csproj
Normal file
@@ -0,0 +1,41 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<Description>A WireMock.org RestClient using RestEase to access the admin interface.</Description>
|
||||||
|
<AssemblyTitle>WireMock.Org.RestClient</AssemblyTitle>
|
||||||
|
<Authors>Stef Heyenrath</Authors>
|
||||||
|
<TargetFrameworks>net45;netstandard1.1;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
|
<AssemblyName>WireMock.Org.RestClient</AssemblyName>
|
||||||
|
<PackageId>WireMock.Org.RestClient</PackageId>
|
||||||
|
<PackageTags>wiremock;wiremock.org;rest;client;restclient;restease;rest;json</PackageTags>
|
||||||
|
<RootNamespace>WireMock.Org.Client</RootNamespace>
|
||||||
|
<ProjectGuid>{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F}</ProjectGuid>
|
||||||
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
|
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||||
|
<SignAssembly>true</SignAssembly>
|
||||||
|
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||||
|
<!--<DelaySign>true</DelaySign>-->
|
||||||
|
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||||
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
|
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
|
||||||
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
|
||||||
|
<PackageReference Include="RestEase" Version="1.5.5" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
@@ -51,7 +51,7 @@
|
|||||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||||
<PackageReference Include="Moq" Version="4.16.0" />
|
<PackageReference Include="Moq" Version="4.16.0" />
|
||||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
<PackageReference Include="RestEase" Version="1.5.5" />
|
||||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.5.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||||
@@ -72,6 +72,9 @@
|
|||||||
<None Update="responsebody.json">
|
<None Update="responsebody.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
<None Update="__admin\mappings.org\mapping1.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json">
|
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
|
|||||||
31
test/WireMock.Net.Tests/WireMockServer.ImportWireMockOrg.cs
Normal file
31
test/WireMock.Net.Tests/WireMockServer.ImportWireMockOrg.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
|
using FluentAssertions;
|
||||||
|
using WireMock.Server;
|
||||||
|
using Xunit;
|
||||||
|
|
||||||
|
namespace WireMock.Net.Tests
|
||||||
|
{
|
||||||
|
public class WireMockServerImportWireMockOrgTests
|
||||||
|
{
|
||||||
|
// For for AppVeyor + OpenCover
|
||||||
|
private string GetCurrentFolder()
|
||||||
|
{
|
||||||
|
return Directory.GetCurrentDirectory();
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void WireMockServer_Admin_ReadStaticWireMockOrgMappingAndAddOrUpdate()
|
||||||
|
{
|
||||||
|
var server = WireMockServer.Start();
|
||||||
|
string path = Path.Combine(GetCurrentFolder(), "__admin", "mappings.org", "mapping1.json");
|
||||||
|
server.ReadStaticWireMockOrgMappingAndAddOrUpdate(path);
|
||||||
|
|
||||||
|
var mappings = server.Mappings.ToArray();
|
||||||
|
|
||||||
|
mappings.Should().HaveCount(1);
|
||||||
|
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -62,7 +62,7 @@ namespace WireMock.Net.Tests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var mappings = server.Mappings;
|
var mappings = server.Mappings;
|
||||||
Check.That(mappings.Count()).IsEqualTo(24);
|
Check.That(mappings.Count()).IsEqualTo(25);
|
||||||
Check.That(mappings.All(m => m.Priority == int.MinValue)).IsTrue();
|
Check.That(mappings.All(m => m.Priority == int.MinValue)).IsTrue();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -81,8 +81,8 @@ namespace WireMock.Net.Tests
|
|||||||
|
|
||||||
// Assert
|
// Assert
|
||||||
var mappings = server.Mappings;
|
var mappings = server.Mappings;
|
||||||
Check.That(mappings.Count()).IsEqualTo(25);
|
Check.That(mappings.Count()).IsEqualTo(26);
|
||||||
Check.That(mappings.Count(m => m.Priority == int.MinValue)).IsEqualTo(24);
|
Check.That(mappings.Count(m => m.Priority == int.MinValue)).IsEqualTo(25);
|
||||||
Check.That(mappings.Count(m => m.Priority == 1000)).IsEqualTo(1);
|
Check.That(mappings.Count(m => m.Priority == 1000)).IsEqualTo(1);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
38
test/WireMock.Net.Tests/__admin/mappings.org/mapping1.json
Normal file
38
test/WireMock.Net.Tests/__admin/mappings.org/mapping1.json
Normal file
@@ -0,0 +1,38 @@
|
|||||||
|
{
|
||||||
|
"id": "ef53ea56-f118-4b3a-8c69-a9484851d99a",
|
||||||
|
"name": "weatherforecast",
|
||||||
|
"request": {
|
||||||
|
"path": "/WeatherForecast/register-city",
|
||||||
|
"method": "POST",
|
||||||
|
"headers": {
|
||||||
|
"XXX": {
|
||||||
|
"contains": "xml"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"queryParameters": {
|
||||||
|
"search_term": {
|
||||||
|
"equalTo": "WireMock"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"bodyPatterns": [
|
||||||
|
{
|
||||||
|
"equalToJson": {
|
||||||
|
"cityName": "São Paulo",
|
||||||
|
"cityCode": 5001
|
||||||
|
},
|
||||||
|
"ignoreArrayOrder": true,
|
||||||
|
"ignoreExtraElements": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"response": {
|
||||||
|
"status": 200,
|
||||||
|
"body": "[{\"date\":\"2021-09-09T20:44:48.0992639-03:00\",\"temperatureC\":51,\"temperatureF\":123,\"summary\":\"Hot\"},{\"date\":\"2021-09-10T20:44:48.0992692-03:00\",\"temperatureC\":34,\"temperatureF\":93,\"summary\":\"Mild\"},{\"date\":\"2021-09-11T20:44:48.0992696-03:00\",\"temperatureC\":43,\"temperatureF\":109,\"summary\":\"Sweltering\"},{\"date\":\"2021-09-12T20:44:48.0992698-03:00\",\"temperatureC\":46,\"temperatureF\":114,\"summary\":\"Cool\"},{\"date\":\"2021-09-13T20:44:48.0992701-03:00\",\"temperatureC\":3,\"temperatureF\":37,\"summary\":\"Freezing\"}]",
|
||||||
|
"headers": {
|
||||||
|
"Content-Type": "application/json; charset=utf-8"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"uuid": "ef53ea56-f118-4b3a-8c69-a9484851d99a",
|
||||||
|
"persistent": true,
|
||||||
|
"insertionIndex": 1
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user