mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-14 07:33:33 +01:00
Compare commits
21 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
775c4fb2e3 | ||
|
|
2d4f513753 | ||
|
|
3d29d7fb2f | ||
|
|
f704de65d8 | ||
|
|
f0d6ed26bc | ||
|
|
330559b9fd | ||
|
|
e2bd56531d | ||
|
|
d2a1d0f069 | ||
|
|
b1af37f044 | ||
|
|
be4b0addca | ||
|
|
ae91ed2a79 | ||
|
|
968aa598e2 | ||
|
|
bdd421e128 | ||
|
|
150b448d07 | ||
|
|
717179fd35 | ||
|
|
9b7e5908cb | ||
|
|
b1032c9dcd | ||
|
|
4d0f96eabe | ||
|
|
ef12cb70cc | ||
|
|
c212d07c53 | ||
|
|
b9afb126cf |
32
CHANGELOG.md
32
CHANGELOG.md
@@ -1,3 +1,35 @@
|
||||
# 1.5.4 (24 August 2022)
|
||||
- [#778](https://github.com/WireMock-Net/WireMock.Net/pull/778) - Fix Proxying when StartAdminInterface=true [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#781](https://github.com/WireMock-Net/WireMock.Net/pull/781) - Update some NuGet packages [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#783](https://github.com/WireMock-Net/WireMock.Net/pull/783) - Fix WithBody when using Pact and added more nullable annotations [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#787](https://github.com/WireMock-Net/WireMock.Net/pull/787) - Add support for PEM certificates contributed by [StefH](https://github.com/StefH)
|
||||
- [#789](https://github.com/WireMock-Net/WireMock.Net/pull/789) - Add support for Matcher.Pattern in Pact Body mapping [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#790](https://github.com/WireMock-Net/WireMock.Net/pull/790) - Add Response.WithBody with IJsonConverter [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#795](https://github.com/WireMock-Net/WireMock.Net/pull/795) - Add check for duplicate Guids when posting multiple mappings in one request contributed by [StefH](https://github.com/StefH)
|
||||
- [#797](https://github.com/WireMock-Net/WireMock.Net/pull/797) - Fix WithHeader when using RejectOnMatch [bug] contributed by [flts](https://github.com/flts)
|
||||
- [#775](https://github.com/WireMock-Net/WireMock.Net/issues/775) - When "StartAdminInterface" is true then each time is generated new mapping from the proxy [bug]
|
||||
- [#784](https://github.com/WireMock-Net/WireMock.Net/issues/784) - Response body is missing in generated pact file when IBodyResponseBuilder.WithBody is used [bug]
|
||||
- [#785](https://github.com/WireMock-Net/WireMock.Net/issues/785) - Support for PEM certificates when using ssl [feature]
|
||||
- [#788](https://github.com/WireMock-Net/WireMock.Net/issues/788) - Request body is missing in generated pact file for requests that include matching on request body [bug]
|
||||
- [#796](https://github.com/WireMock-Net/WireMock.Net/issues/796) - RequestMessageHeaderMatcher with MatchBehaviour.RejectOnMatch reverses match results twice [bug]
|
||||
|
||||
# 1.5.3 (29 July 2022)
|
||||
- [#777](https://github.com/WireMock-Net/WireMock.Net/pull/777) - Update Scriban.Signed to version 5.5.0 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#776](https://github.com/WireMock-Net/WireMock.Net/issues/776) - Update Scriban.Signed to support more functions, e.g math.random [feature]
|
||||
|
||||
# 1.5.2 (24 July 2022)
|
||||
- [#769](https://github.com/WireMock-Net/WireMock.Net/pull/769) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.3 to 2.1.7 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#770](https://github.com/WireMock-Net/WireMock.Net/pull/770) - Added some more tests for JsonMatcher + refactored some code to use nullable [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#771](https://github.com/WireMock-Net/WireMock.Net/pull/771) - JsonPartialMatcher - support Regex [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.5.1 (08 July 2022)
|
||||
- [#762](https://github.com/WireMock-Net/WireMock.Net/pull/762) - Bump Newtonsoft.Json from 11.0.2 to 13.0.1 in /examples/WireMock.Net.WebApplication.NETCore2 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#763](https://github.com/WireMock-Net/WireMock.Net/pull/763) - Bump Newtonsoft.Json from 6.0.1 to 13.0.1 in /examples/WireMock.Net.Client.Net472 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#765](https://github.com/WireMock-Net/WireMock.Net/pull/765) - Update WireMock.Org.Abstractions and WireMock.Org.RestClient [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#766](https://github.com/WireMock-Net/WireMock.Net/pull/766) - Bump Microsoft.AspNetCore.Http from 2.1.1 to 2.1.22 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#767](https://github.com/WireMock-Net/WireMock.Net/pull/767) - Rename (WireMock.Pact.Models.V2)-Request to PactRequest and -Response to PactResponse [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#764](https://github.com/WireMock-Net/WireMock.Net/issues/764) - Wrong mapping of method GetAdminMappingsAsync from IWireMockOrgApi [bug]
|
||||
|
||||
# 1.5.0 (09 June 2022)
|
||||
- [#755](https://github.com/WireMock-Net/WireMock.Net/pull/755) - Add MatchOperator "Or", "And" and "Average" for patterns [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.5.0</VersionPrefix>
|
||||
<VersionPrefix>1.5.4</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
@@ -25,10 +25,6 @@
|
||||
<!--<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)' != '' ">
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.5.0
|
||||
SET version=1.5.4
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||
|
||||
|
||||
@@ -1,4 +1,16 @@
|
||||
# 1.5.0 (09 June 2022)
|
||||
- #755 Add MatchOperator "Or", "And" and "Average" for patterns [feature]
|
||||
# 1.5.4 (24 August 2022)
|
||||
- #778 Fix Proxying when StartAdminInterface=true [bug]
|
||||
- #781 Update some NuGet packages [feature]
|
||||
- #783 Fix WithBody when using Pact and added more nullable annotations [feature]
|
||||
- #787 Add support for PEM certificates
|
||||
- #789 Add support for Matcher.Pattern in Pact Body mapping [feature]
|
||||
- #790 Add Response.WithBody with IJsonConverter [feature]
|
||||
- #795 Add check for duplicate Guids when posting multiple mappings in one request
|
||||
- #797 Fix WithHeader when using RejectOnMatch [bug]
|
||||
- #775 When "StartAdminInterface" is true then each time is generated new mapping from the proxy [bug]
|
||||
- #784 Response body is missing in generated pact file when IBodyResponseBuilder.WithBody is used [bug]
|
||||
- #785 Support for PEM certificates when using ssl [feature]
|
||||
- #788 Request body is missing in generated pact file for requests that include matching on request body [bug]
|
||||
- #796 RequestMessageHeaderMatcher with MatchBehaviour.RejectOnMatch reverses match results twice [bug]
|
||||
|
||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||
@@ -103,6 +103,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET6.WithCertificate", "examples\WireMock.Net.Console.NET6.WithCertificate\WireMock.Net.Console.NET6.WithCertificate.csproj", "{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -245,6 +247,10 @@ Global
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -286,6 +292,7 @@ Global
|
||||
{3F7AA023-6833-4856-A08A-4B5717B592B8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -1,18 +1,22 @@
|
||||
<wpf:ResourceDictionary xml:space="preserve" xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml" xmlns:s="clr-namespace:System;assembly=mscorlib" xmlns:ss="urn:shemas-jetbrains-com:settings-storage-xaml" xmlns:wpf="http://schemas.microsoft.com/winfx/2006/xaml/presentation">
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=AD/@EntryIndexedValue">AD</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CS/@EntryIndexedValue">CS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=EC/@EntryIndexedValue">EC</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=ID/@EntryIndexedValue">ID</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=IP/@EntryIndexedValue">IP</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=MD/@EntryIndexedValue">MD5</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=RSA/@EntryIndexedValue">RSA</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=SSL/@EntryIndexedValue">SSL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TE/@EntryIndexedValue">TE</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TSV/@EntryIndexedValue">TSV</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=TTL/@EntryIndexedValue">TTL</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WWW/@EntryIndexedValue">WWW</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XMS/@EntryIndexedValue">XMS</s:String>
|
||||
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XUA/@EntryIndexedValue">XUA</s:String>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Flurl/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=funcs/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=guidb/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Guids/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heyenrath/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pacticipant/@EntryIndexedValue">True</s:Boolean>
|
||||
@@ -24,6 +28,7 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremock/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=wiremockserver/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=xunit/@EntryIndexedValue">True</s:Boolean>
|
||||
</wpf:ResourceDictionary>
|
||||
@@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="Brutal.Dev.StrongNameSigner" version="2.7.1" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="6.0.1" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
|
||||
<package id="RestEase" version="1.4.10" targetFramework="net472" />
|
||||
<package id="WireMock.Net.Abstractions" version="1.2.0" targetFramework="net472" />
|
||||
<package id="WireMock.Net.RestClient" version="1.2.0" targetFramework="net472" />
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="RestEase" Version="1.5.6" />
|
||||
<PackageReference Include="RestEase" Version="1.5.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
16
examples/WireMock.Net.Console.NET6.WithCertificate/HowTo.txt
Normal file
16
examples/WireMock.Net.Console.NET6.WithCertificate/HowTo.txt
Normal file
@@ -0,0 +1,16 @@
|
||||
https://www.scottbrady91.com/openssl/creating-elliptical-curve-keys-using-openssl
|
||||
|
||||
# find your curve
|
||||
openssl ecparam -list_curves
|
||||
|
||||
# generate a private key for a curve
|
||||
openssl ecparam -name prime256v1 -genkey -noout -out private-key.pem
|
||||
|
||||
# generate corresponding public key
|
||||
openssl ec -in private-key.pem -pubout -out public-key.pem
|
||||
|
||||
# optional: create a self-signed certificate
|
||||
openssl req -new -x509 -key private-key.pem -out cert.pem -days 360
|
||||
|
||||
# optional: convert pem to pfx
|
||||
openssl pkcs12 -export -inkey private-key.pem -in cert.pem -out cert.pfx
|
||||
@@ -0,0 +1,52 @@
|
||||
using System.IO;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.Console.NET6.WithCertificate;
|
||||
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var serverEC = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Urls = new[] { "https://localhost:8433/" },
|
||||
StartAdminInterface = true,
|
||||
Logger = new WireMockConsoleLogger(),
|
||||
CertificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
// https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
|
||||
// https://www.scottbrady91.com/openssl/creating-elliptical-curve-keys-using-openssl
|
||||
X509CertificateFilePath = "cert.pem",
|
||||
X509CertificatePassword = @"
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJZTv6ujGrEwxW+ab1+CtZouRd8PK7PsklVMvJwm1uDmoAoGCCqGSM49
|
||||
AwEHoUQDQgAE39VoI268uDuIeKmRzr9e9jgMSGeuJTvTG7+cSXmeDymrVgIGXQgm
|
||||
qKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
|
||||
-----END EC PRIVATE KEY-----"
|
||||
}
|
||||
});
|
||||
System.Console.WriteLine("WireMockServer listening at {0}", serverEC.Url);
|
||||
|
||||
var serverRSA = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Urls = new[] { "https://localhost:8434/" },
|
||||
StartAdminInterface = true,
|
||||
Logger = new WireMockConsoleLogger(),
|
||||
CertificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
// https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
|
||||
// https://www.scottbrady91.com/openssl/creating-rsa-keys-using-openssl
|
||||
X509CertificateFilePath = "cert-rsa.pem",
|
||||
X509CertificatePassword = File.ReadAllText("private-key-rsa.pem")
|
||||
}
|
||||
});
|
||||
System.Console.WriteLine("WireMockServer listening at {0}", serverRSA.Url);
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server(s)");
|
||||
System.Console.ReadKey();
|
||||
serverEC.Stop();
|
||||
serverRSA.Stop();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="*.pem">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="*.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="nlog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIErzCCAxegAwIBAgIUeVJ5l3LJPakcwhBGXNfa7UawgPcwDQYJKoZIhvcNAQEL
|
||||
BQAwZzELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxFTATBgNVBAoM
|
||||
DFdpcmVNb2NrLk5ldDEVMBMGA1UECwwMV2lyZU1vY2suTmV0MRUwEwYDVQQDDAxX
|
||||
aXJlTW9jay5OZXQwHhcNMjIwODEyMTQzMjUxWhcNMzIwNjIwMTQzMjUxWjBnMQsw
|
||||
CQYDVQQGEwJOTDETMBEGA1UECAwKU29tZS1TdGF0ZTEVMBMGA1UECgwMV2lyZU1v
|
||||
Y2suTmV0MRUwEwYDVQQLDAxXaXJlTW9jay5OZXQxFTATBgNVBAMMDFdpcmVNb2Nr
|
||||
Lk5ldDCCAaIwDQYJKoZIhvcNAQEBBQADggGPADCCAYoCggGBALyF2sKsueDaZ78r
|
||||
fQ5IyqWJLYXnYRT94xVfiPoRQNex7JMYwdIt+xEPcfhIlyODxYRxzYTSuXi/cBOM
|
||||
/svTewIdBmDDyyCDboZ+P8THlzdwCLNHUPONQqJtc0msLVfwPuvDeZIwhIn9CDwC
|
||||
1EXstWLEePxu1i2/PAfUudYeQunjrP10DE06fyW+ZH7sMSPOSyY4BO4Rt0dk3Cws
|
||||
U/CEl+bSN5Kx2WkyPxbOvZLa66JmQEaeSZ4ypkhujWE1LuIIQE94P28BzFpHtDWO
|
||||
1+42K8mqjdnO8eH1/IfAMmOE/o3rKoI4C5aUPyJpDOaz5KFCqdCSBHlb2uo3lqgd
|
||||
yYOCrVOLIsljp8H4ncfs1AUo+tExNW/5jWYegAZGXLArrWktHEbwa4f+9ZMa7+VS
|
||||
lKpx6hLI7eMSHBCsQJ7yH8QyLhr0HMjoDw38isGV+mK/N1u47s4oaTQyG+HXH+e/
|
||||
Shj5OSKnLWBV/eX7YSAJ1hqHgmAbwl/BnuGI3SBXSK4mcjcNvQIDAQABo1MwUTAd
|
||||
BgNVHQ4EFgQUYhrgWXNdcFpnyz0mifPqYM+kyK4wHwYDVR0jBBgwFoAUYhrgWXNd
|
||||
cFpnyz0mifPqYM+kyK4wDwYDVR0TAQH/BAUwAwEB/zANBgkqhkiG9w0BAQsFAAOC
|
||||
AYEAmfJZJ019pO7ZXDQ85nEC99+x9+MUnSZ6UuMIiy2VMcS/oea8ugQ4NBYVPpQS
|
||||
O/xiYENpw36+H4+ctv1tdAbZELGGLBahkkzZedLyiFObxDALu0PP7jQYr4nUjfQj
|
||||
B/fWuTcCrVmuH3yiutw/sALd1su63VjjZiOCwxMB8LV4T0ojBTHA2D4rqLTiSRgs
|
||||
sP3CRoWDI2JIr2afM/K8SMczRbo/5ovv0YF9kFcwG9WDEa/oQ67Yu05GFBnItYmT
|
||||
QP+Br5WiPTLOON9TKm1ZgxLwrhJNHfD2+u9uudkVF5uWyg9ZvB8sYmIw5wSvUFl5
|
||||
SDj1Pxy4olim54BL5wIwlMMQu+fKp6T89iShgN/NEot3JKW3zDpa/t93IjJXGOlh
|
||||
O4ECoUzXCtDTnc6aais2SoYjbveP2wduS9MHAQinjTiepzYbhJbySURKqCBu1mN2
|
||||
EFsU9Pzd1+MA3ZbRfhvl8Jvwdp5GqaFyCqgqmP5oPOcd9ncJowyfobfdqzYMXPGl
|
||||
bu9i
|
||||
-----END CERTIFICATE-----
|
||||
13
examples/WireMock.Net.Console.NET6.WithCertificate/cert.pem
Normal file
13
examples/WireMock.Net.Console.NET6.WithCertificate/cert.pem
Normal file
@@ -0,0 +1,13 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIB9TCCAZugAwIBAgIUYH7UM/DAXzosxsT+ea2jdYvhqqMwCgYIKoZIzj0EAwIw
|
||||
UDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUtU3RhdGUxFTATBgNVBAoMDFdp
|
||||
cmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2suTmV0MB4XDTIyMDgxMTE2MjE0
|
||||
NFoXDTMyMDYxOTE2MjE0NFowUDELMAkGA1UEBhMCTkwxEzARBgNVBAgMClNvbWUt
|
||||
U3RhdGUxFTATBgNVBAoMDFdpcmVNb2NrLk5ldDEVMBMGA1UEAwwMV2lyZU1vY2su
|
||||
TmV0MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgM
|
||||
SGeuJTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspaNT
|
||||
MFEwHQYDVR0OBBYEFILL8V+fAtMnccWKGAdkx2Dh/v/TMB8GA1UdIwQYMBaAFILL
|
||||
8V+fAtMnccWKGAdkx2Dh/v/TMA8GA1UdEwEB/wQFMAMBAf8wCgYIKoZIzj0EAwID
|
||||
SAAwRQIgKDLAG8OWK6GF5HV4kmWz3kp2V3yVsNK2V9Lw3dSE+YsCIQCK1EEBvuqc
|
||||
0ncZV4ETVnOY23PWFOMk1VwN2aoTi5n++Q==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -0,0 +1,39 @@
|
||||
-----BEGIN RSA PRIVATE KEY-----
|
||||
MIIG5AIBAAKCAYEAvIXawqy54Npnvyt9DkjKpYkthedhFP3jFV+I+hFA17HskxjB
|
||||
0i37EQ9x+EiXI4PFhHHNhNK5eL9wE4z+y9N7Ah0GYMPLIINuhn4/xMeXN3AIs0dQ
|
||||
841Com1zSawtV/A+68N5kjCEif0IPALURey1YsR4/G7WLb88B9S51h5C6eOs/XQM
|
||||
TTp/Jb5kfuwxI85LJjgE7hG3R2TcLCxT8ISX5tI3krHZaTI/Fs69ktrromZARp5J
|
||||
njKmSG6NYTUu4ghAT3g/bwHMWke0NY7X7jYryaqN2c7x4fX8h8AyY4T+jesqgjgL
|
||||
lpQ/ImkM5rPkoUKp0JIEeVva6jeWqB3Jg4KtU4siyWOnwfidx+zUBSj60TE1b/mN
|
||||
Zh6ABkZcsCutaS0cRvBrh/71kxrv5VKUqnHqEsjt4xIcEKxAnvIfxDIuGvQcyOgP
|
||||
DfyKwZX6Yr83W7juzihpNDIb4dcf579KGPk5IqctYFX95fthIAnWGoeCYBvCX8Ge
|
||||
4YjdIFdIriZyNw29AgMBAAECggGBAJcMsNDWUECG/iVAFP0C+ctUdDMbxr9pBS+0
|
||||
0i168XdhSeo6JeHfkZCDzY9fqil8hR+vhznrFUxYJtajW+u4UJDK7LdPaUttw3rj
|
||||
YPir6s8yZuYuOABMqJ04EO1wlQwmpGOGxbuKQEfHg3eB1M8J7/No9H9d1yHkXZbw
|
||||
rM2QhZCdKZgSCWE/g2ycdizz1hOYUMIYlGqjqzP67iY+hirqMkNxH7Hb6hTNe5ss
|
||||
ntwxqCcAwnNSlC2661yRp5nBYQUeEfgXAx/cZZ6cILjX6JanDsML/PRY1hOm5hCZ
|
||||
8/8satOGtd37rgr1cP/kvNMf7uLI8hIeC4JSCymUh6lU6ERpWRoQV8DUE60ztFbi
|
||||
bQbGU/rseznBN8O1cM6fjduno/n8d4q5wGLjAbIai+xxxTSksbnlvkthRAUfK9/Y
|
||||
rUdMxqgkDnecCAHof8UPz/Vg3n9J9wl6waFrKa+Kseda1wEB/jf51fb/t0sJP2Dq
|
||||
n2kcp239zwalUr2XnXfENfeL9IDBiQKBwQDsogaTFy7E5P+66B1ZRDP2X6WgFedH
|
||||
tjMCVXG4K4VOWp6xMfhieq2d+amMoYi/J3cxS8qDIM64q55caTaB3KTodGrzmvax
|
||||
avqG58Mpyv9VdEDzMI29D7Xtx5ykoAAWOmQaByH/4J+3IBX6efRDGmSvmoqPoa0V
|
||||
ChMO0Gw6O9GsH/kVEy2nRaj9dJpOqo05jhh9LLye2stPycCHzYybYqjs0Nt1uboY
|
||||
3mbiCJBWJ8jZk9KeFhrqCkYB1zZJIJVybJ8CgcEAy/PRm0NZDUx6IJKnwDXBriE0
|
||||
Qih1ZcvdVi907nhYAlBpAPWisGls6EghBQsfvQ4ZPwHAFBlDu/72JrqGJhkP61mP
|
||||
D/xT9d59xSU5N90doiInrTHAOoyZEdpul9QvCXxKuFFl3RZnxn0RwPgc23sZUcny
|
||||
aM4DIWk1541Z84Lxv3tFLXoG5uvqpCkSwEBd9iu0EMHlmoPFkEkY41Q3/zTs46FY
|
||||
fnWLSdRahKDFHrZTgyu4i/3clbbp9m1cpWLwzUwjAoHAVpSWCT2jPCF5vD5vdpjw
|
||||
1kV6yU8aV2+/zCvNNxCdbuTTSYw6EHZIjhOqSK1V5nMfNmc/yqi3WnRYtgE9E1jS
|
||||
8cae11Es0A+PaMrl6qW+tNqbZR+vzKwx6bVuiAGO5pMoyyku9HuQlKVlxUbX67F9
|
||||
g47tAc6rEJamEHaMEuaOOgdc0Kw6uQhQ46PFTeEzWQq3xR0YSptNZn0wN8AqoTQB
|
||||
ENz+X128TJsbU7rEbPGTmKBwoKz/3gAySzwePbVxWPOLAoHAAsqehtKAKIdwcHux
|
||||
YhcaRIjdzz4AhVkp+WEC57Sr97QkC8hQ5rs6q185XHlPgOXtgIhEmcHSxILz2Yna
|
||||
BjF3n1AFfkGE4Kuf6w/cXaBgJHT1OBCjQenkunLT6q4TyrxxxV4P19vTpcrWcF60
|
||||
/mgL66uo7rhLIKzw+O9dWNDlACruwnWWHJkECCUrxYfcAV+NwmD1BI1jKdtmRM5F
|
||||
Se/ughsWO/zd4C/Q4VnV+Nqj//qcNwZNe5saTq4mg3j8NMMjAoHBANRR+WLpgr3f
|
||||
Kh9vNA+v1gnBUFImheWrJ+Eu75q1sGKrz3gZ8glhewf37YbJVuSKFMEBAg1qobWG
|
||||
/2B26beXia/NprVuV5vqJNuts29W1/WuDKE7BsNya/quDA1WxTQAzhSA54DYtWXw
|
||||
UgVTPtEQXL9Wbk2wF98tWiUio4VjV++geVql4qKQUet1IMo1RgRgbQL5hn/rDH0g
|
||||
ZOX552VdK1xivWQRVA4486eKHlW/lbKJjX0Os6qhNIF57qVquIRQPw==
|
||||
-----END RSA PRIVATE KEY-----
|
||||
@@ -0,0 +1,5 @@
|
||||
-----BEGIN EC PRIVATE KEY-----
|
||||
MHcCAQEEIJZTv6ujGrEwxW+ab1+CtZouRd8PK7PsklVMvJwm1uDmoAoGCCqGSM49
|
||||
AwEHoUQDQgAE39VoI268uDuIeKmRzr9e9jgMSGeuJTvTG7+cSXmeDymrVgIGXQgm
|
||||
qKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
|
||||
-----END EC PRIVATE KEY-----
|
||||
@@ -0,0 +1,11 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MIIBojANBgkqhkiG9w0BAQEFAAOCAY8AMIIBigKCAYEAvIXawqy54Npnvyt9DkjK
|
||||
pYkthedhFP3jFV+I+hFA17HskxjB0i37EQ9x+EiXI4PFhHHNhNK5eL9wE4z+y9N7
|
||||
Ah0GYMPLIINuhn4/xMeXN3AIs0dQ841Com1zSawtV/A+68N5kjCEif0IPALURey1
|
||||
YsR4/G7WLb88B9S51h5C6eOs/XQMTTp/Jb5kfuwxI85LJjgE7hG3R2TcLCxT8ISX
|
||||
5tI3krHZaTI/Fs69ktrromZARp5JnjKmSG6NYTUu4ghAT3g/bwHMWke0NY7X7jYr
|
||||
yaqN2c7x4fX8h8AyY4T+jesqgjgLlpQ/ImkM5rPkoUKp0JIEeVva6jeWqB3Jg4Kt
|
||||
U4siyWOnwfidx+zUBSj60TE1b/mNZh6ABkZcsCutaS0cRvBrh/71kxrv5VKUqnHq
|
||||
Esjt4xIcEKxAnvIfxDIuGvQcyOgPDfyKwZX6Yr83W7juzihpNDIb4dcf579KGPk5
|
||||
IqctYFX95fthIAnWGoeCYBvCX8Ge4YjdIFdIriZyNw29AgMBAAE=
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -0,0 +1,4 @@
|
||||
-----BEGIN PUBLIC KEY-----
|
||||
MFkwEwYHKoZIzj0CAQYIKoZIzj0DAQcDQgAE39VoI268uDuIeKmRzr9e9jgMSGeu
|
||||
JTvTG7+cSXmeDymrVgIGXQgmqKA8TDXpJNrRhWMd/fpsnWu1JwJUjBmspQ==
|
||||
-----END PUBLIC KEY-----
|
||||
@@ -0,0 +1,73 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that <see langword="null"/> is allowed as an input even if the
|
||||
/// corresponding type disallows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property,
|
||||
Inherited = false
|
||||
)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class AllowNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AllowNullAttribute"/> class.
|
||||
/// </summary>
|
||||
#endif
|
||||
public AllowNullAttribute() { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,73 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that <see langword="null"/> is disallowed as an input even if the
|
||||
/// corresponding type allows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Field | AttributeTargets.Parameter | AttributeTargets.Property,
|
||||
Inherited = false
|
||||
)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class DisallowNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DisallowNullAttribute"/> class.
|
||||
/// </summary>
|
||||
#endif
|
||||
public DisallowNullAttribute() { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,70 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that a method that will never return under any circumstance.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Method, Inherited = false)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class DoesNotReturnAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DoesNotReturnAttribute"/> class.
|
||||
/// </summary>
|
||||
///
|
||||
#endif
|
||||
public DoesNotReturnAttribute() { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,88 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that the method will not return if the associated <see cref="Boolean"/>
|
||||
/// parameter is passed the specified value.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class DoesNotReturnIfAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets the condition parameter value.
|
||||
/// Code after the method is considered unreachable by diagnostics if the argument
|
||||
/// to the associated parameter matches this value.
|
||||
/// </summary>
|
||||
#endif
|
||||
public bool ParameterValue { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="DoesNotReturnIfAttribute"/>
|
||||
/// class with the specified parameter value.
|
||||
/// </summary>
|
||||
/// <param name="parameterValue">
|
||||
/// The condition parameter value.
|
||||
/// Code after the method is considered unreachable by diagnostics if the argument
|
||||
/// to the associated parameter matches this value.
|
||||
/// </param>
|
||||
#endif
|
||||
public DoesNotReturnIfAttribute(bool parameterValue)
|
||||
{
|
||||
ParameterValue = parameterValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,74 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that an output may be <see langword="null"/> even if the
|
||||
/// corresponding type disallows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Field | AttributeTargets.Parameter |
|
||||
AttributeTargets.Property | AttributeTargets.ReturnValue,
|
||||
Inherited = false
|
||||
)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class MaybeNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="MaybeNullAttribute"/> class.
|
||||
/// </summary>
|
||||
#endif
|
||||
public MaybeNullAttribute() { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,85 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that when a method returns <see cref="ReturnValue"/>,
|
||||
/// the parameter may be <see langword="null"/> even if the corresponding type disallows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class MaybeNullWhenAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets the return value condition.
|
||||
/// If the method returns this value, the associated parameter may be <see langword="null"/>.
|
||||
/// </summary>
|
||||
#endif
|
||||
public bool ReturnValue { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the specified return value condition.
|
||||
/// </summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition.
|
||||
/// If the method returns this value, the associated parameter may be <see langword="null"/>.
|
||||
/// </param>
|
||||
#endif
|
||||
public MaybeNullWhenAttribute(bool returnValue)
|
||||
{
|
||||
ReturnValue = returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,96 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that the method or property will ensure that the listed field and property members have
|
||||
/// not-<see langword="null"/> values.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class MemberNotNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets field or property member names.
|
||||
/// </summary>
|
||||
#endif
|
||||
public string[] Members { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with a field or property member.
|
||||
/// </summary>
|
||||
/// <param name="member">
|
||||
/// The field or property member that is promised to be not-null.
|
||||
/// </param>
|
||||
#endif
|
||||
public MemberNotNullAttribute(string member)
|
||||
{
|
||||
Members = new[] { member };
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the list of field and property members.
|
||||
/// </summary>
|
||||
/// <param name="members">
|
||||
/// The list of field and property members that are promised to be not-null.
|
||||
/// </param>
|
||||
#endif
|
||||
public MemberNotNullAttribute(params string[] members)
|
||||
{
|
||||
Members = members;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,114 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that the method or property will ensure that the listed field and property members have
|
||||
/// non-<see langword="null"/> values when returning with the specified return value condition.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Method | AttributeTargets.Property, Inherited = false, AllowMultiple = true)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class MemberNotNullWhenAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets the return value condition.
|
||||
/// </summary>
|
||||
#endif
|
||||
public bool ReturnValue { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets field or property member names.
|
||||
/// </summary>
|
||||
#endif
|
||||
public string[] Members { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the specified return value condition and a field or property member.
|
||||
/// </summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value,
|
||||
/// the associated parameter will not be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <param name="member">
|
||||
/// The field or property member that is promised to be not-<see langword="null"/>.
|
||||
/// </param>
|
||||
#endif
|
||||
public MemberNotNullWhenAttribute(bool returnValue, string member)
|
||||
{
|
||||
ReturnValue = returnValue;
|
||||
Members = new[] { member };
|
||||
}
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the specified return value condition and list
|
||||
/// of field and property members.
|
||||
/// </summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition. If the method returns this value,
|
||||
/// the associated parameter will not be <see langword="null"/>.
|
||||
/// </param>
|
||||
/// <param name="members">
|
||||
/// The list of field and property members that are promised to be not-null.
|
||||
/// </param>
|
||||
#endif
|
||||
public MemberNotNullWhenAttribute(bool returnValue, params string[] members)
|
||||
{
|
||||
ReturnValue = returnValue;
|
||||
Members = members;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,74 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that an output is not <see langword="null"/> even if the
|
||||
/// corresponding type allows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Field | AttributeTargets.Parameter |
|
||||
AttributeTargets.Property | AttributeTargets.ReturnValue,
|
||||
Inherited = false
|
||||
)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class NotNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="NotNullAttribute"/> class.
|
||||
/// </summary>
|
||||
#endif
|
||||
public NotNullAttribute() { }
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,91 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that the output will be non-<see langword="null"/> if the
|
||||
/// named parameter is non-<see langword="null"/>.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(
|
||||
AttributeTargets.Parameter | AttributeTargets.Property | AttributeTargets.ReturnValue,
|
||||
AllowMultiple = true,
|
||||
Inherited = false
|
||||
)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class NotNullIfNotNullAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets the associated parameter name.
|
||||
/// The output will be non-<see langword="null"/> if the argument to the
|
||||
/// parameter specified is non-<see langword="null"/>.
|
||||
/// </summary>
|
||||
#endif
|
||||
public string ParameterName { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the associated parameter name.
|
||||
/// </summary>
|
||||
/// <param name="parameterName">
|
||||
/// The associated parameter name.
|
||||
/// The output will be non-<see langword="null"/> if the argument to the
|
||||
/// parameter specified is non-<see langword="null"/>.
|
||||
/// </param>
|
||||
#endif
|
||||
public NotNullIfNotNullAttribute(string parameterName)
|
||||
{
|
||||
ParameterName = parameterName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -0,0 +1,85 @@
|
||||
// <auto-generated>
|
||||
// This code file has automatically been added by the "Nullable" NuGet package (https://www.nuget.org/packages/Nullable).
|
||||
// Please see https://github.com/manuelroemer/Nullable for more information.
|
||||
//
|
||||
// IMPORTANT:
|
||||
// DO NOT DELETE THIS FILE if you are using a "packages.config" file to manage your NuGet references.
|
||||
// Consider migrating to PackageReferences instead:
|
||||
// https://docs.microsoft.com/en-us/nuget/consume-packages/migrate-packages-config-to-package-reference
|
||||
// Migrating brings the following benefits:
|
||||
// * The "Nullable" folder and the nullable "*Attribute.cs" files don't appear in your project.
|
||||
// * The added files are immutable and can therefore not be modified by coincidence.
|
||||
// * Updating/Uninstalling the package will work flawlessly.
|
||||
// </auto-generated>
|
||||
|
||||
#region License
|
||||
// MIT License
|
||||
//
|
||||
// Copyright (c) Manuel Römer
|
||||
//
|
||||
// Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||
// of this software and associated documentation files (the "Software"), to deal
|
||||
// in the Software without restriction, including without limitation the rights
|
||||
// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||
// copies of the Software, and to permit persons to whom the Software is
|
||||
// furnished to do so, subject to the following conditions:
|
||||
//
|
||||
// The above copyright notice and this permission notice shall be included in all
|
||||
// copies or substantial portions of the Software.
|
||||
//
|
||||
// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||
// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||
// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||
// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
||||
// SOFTWARE.
|
||||
#endregion
|
||||
|
||||
#if !NULLABLE_ATTRIBUTES_DISABLE
|
||||
#nullable enable
|
||||
#pragma warning disable
|
||||
|
||||
namespace System.Diagnostics.CodeAnalysis
|
||||
{
|
||||
using global::System;
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Specifies that when a method returns <see cref="ReturnValue"/>,
|
||||
/// the parameter will not be <see langword="null"/> even if the corresponding type allows it.
|
||||
/// </summary>
|
||||
#endif
|
||||
[AttributeUsage(AttributeTargets.Parameter, Inherited = false)]
|
||||
#if !NULLABLE_ATTRIBUTES_INCLUDE_IN_CODE_COVERAGE
|
||||
[DebuggerNonUserCode]
|
||||
#endif
|
||||
internal sealed class NotNullWhenAttribute : Attribute
|
||||
{
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Gets the return value condition.
|
||||
/// If the method returns this value, the associated parameter will not be <see langword="null"/>.
|
||||
/// </summary>
|
||||
#endif
|
||||
public bool ReturnValue { get; }
|
||||
|
||||
#if DEBUG
|
||||
/// <summary>
|
||||
/// Initializes the attribute with the specified return value condition.
|
||||
/// </summary>
|
||||
/// <param name="returnValue">
|
||||
/// The return value condition.
|
||||
/// If the method returns this value, the associated parameter will not be <see langword="null"/>.
|
||||
/// </param>
|
||||
#endif
|
||||
public NotNullWhenAttribute(bool returnValue)
|
||||
{
|
||||
ReturnValue = returnValue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#pragma warning restore
|
||||
#nullable restore
|
||||
#endif // NULLABLE_ATTRIBUTES_DISABLE
|
||||
@@ -43,7 +43,7 @@
|
||||
<HintPath>..\..\packages\AnyOf.0.3.0\lib\net45\AnyOf.dll</HintPath>
|
||||
</Reference>
|
||||
<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>
|
||||
<HintPath>..\..\packages\Fare.2.2.1\lib\net35\Fare.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||
@@ -54,23 +54,23 @@
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.5\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.3.3\lib\net452\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.3.5\lib\net452\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.3.3\lib\net452\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.3.5\lib\net452\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.3.3\lib\net452\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.3.5\lib\net452\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.3.3\lib\net452\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.3.5\lib\net452\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.3.3\lib\net452\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.3.5\lib\net452\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.3.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.3.3\lib\net452\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
||||
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.3.5.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.3.5\lib\net452\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Humanizer, Version=2.14.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Humanizer.Core.2.14.1\lib\netstandard2.0\Humanizer.dll</HintPath>
|
||||
@@ -246,11 +246,23 @@
|
||||
<Reference Include="Microsoft.Net.Http.Headers, Version=2.2.0.0, Culture=neutral, PublicKeyToken=adb9793829ddae60, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.Net.Http.Headers.2.2.0\lib\netstandard2.0\Microsoft.Net.Http.Headers.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Namotion.Reflection, Version=2.0.10.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Namotion.Reflection.2.0.10\lib\net45\Namotion.Reflection.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Newtonsoft.Json.13.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
|
||||
</Reference>
|
||||
<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 Include="NJsonSchema, Version=10.6.10.0, Culture=neutral, PublicKeyToken=c2f9c3bdfae56102, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NJsonSchema.10.6.10\lib\net45\NJsonSchema.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NJsonSchema.Extensions, Version=0.1.0.0, Culture=neutral, PublicKeyToken=e52fadf300daf456, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NJsonSchema.Extensions.0.1.0\lib\net45\NJsonSchema.Extensions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="NSwag.Core, Version=13.15.10.0, Culture=neutral, PublicKeyToken=c2d88086e098d109, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\NSwag.Core.13.15.10\lib\net45\NSwag.Core.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RandomDataGenerator, Version=1.0.15.0, Culture=neutral, PublicKeyToken=ae5c571d29a3b8d9, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\RandomDataGenerator.Net.1.0.16\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>
|
||||
@@ -289,6 +301,10 @@
|
||||
<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>
|
||||
</Reference>
|
||||
<Reference Include="System.Net" />
|
||||
<Reference Include="System.Net.Http.Formatting, Version=5.2.8.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Microsoft.AspNet.WebApi.Client.5.2.8\lib\net45\System.Net.Http.Formatting.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Net.Http.WebRequest" />
|
||||
<Reference Include="System.Numerics" />
|
||||
<Reference Include="System.Numerics.Vectors, Version=4.1.4.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
@@ -300,6 +316,7 @@
|
||||
<Reference Include="System.Runtime.CompilerServices.Unsafe, Version=5.0.0.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Runtime.CompilerServices.Unsafe.5.0.0\lib\net45\System.Runtime.CompilerServices.Unsafe.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="System.Runtime.Serialization" />
|
||||
<Reference Include="System.Security.Cryptography.Cng, Version=4.3.1.0, Culture=neutral, PublicKeyToken=b03f5f7f11d50a3a, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\System.Security.Cryptography.Cng.4.5.0\lib\net47\System.Security.Cryptography.Cng.dll</HintPath>
|
||||
</Reference>
|
||||
@@ -325,14 +342,14 @@
|
||||
<Reference Include="TinyMapper, Version=3.0.1.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\TinyMapper.3.0.3\lib\net40\TinyMapper.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WireMock.Net, Version=1.4.41.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Net.1.4.41\lib\net461\WireMock.Net.dll</HintPath>
|
||||
<Reference Include="WireMock.Net, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Net.1.5.3\lib\net461\WireMock.Net.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WireMock.Net.Abstractions, Version=1.4.41.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Net.Abstractions.1.4.41\lib\net451\WireMock.Net.Abstractions.dll</HintPath>
|
||||
<Reference Include="WireMock.Net.Abstractions, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Net.Abstractions.1.5.3\lib\net451\WireMock.Net.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="WireMock.Org.Abstractions, Version=1.4.41.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Org.Abstractions.1.4.41\lib\net45\WireMock.Org.Abstractions.dll</HintPath>
|
||||
<Reference Include="WireMock.Org.Abstractions, Version=1.5.3.0, Culture=neutral, PublicKeyToken=c8d65537854e1f03, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\WireMock.Org.Abstractions.1.5.3\lib\net45\WireMock.Org.Abstractions.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="XPath2, Version=1.1.3.0, Culture=neutral, PublicKeyToken=463c6d7fb740c7e5, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\XPath2.1.1.3\lib\net452\XPath2.dll</HintPath>
|
||||
@@ -351,6 +368,17 @@
|
||||
<Compile Include="..\WireMock.Net.Console.Net452.Classic\Program.cs">
|
||||
<Link>Program.cs</Link>
|
||||
</Compile>
|
||||
<Compile Include="Nullable\AllowNullAttribute.cs" />
|
||||
<Compile Include="Nullable\DisallowNullAttribute.cs" />
|
||||
<Compile Include="Nullable\DoesNotReturnAttribute.cs" />
|
||||
<Compile Include="Nullable\DoesNotReturnIfAttribute.cs" />
|
||||
<Compile Include="Nullable\MaybeNullAttribute.cs" />
|
||||
<Compile Include="Nullable\MaybeNullWhenAttribute.cs" />
|
||||
<Compile Include="Nullable\MemberNotNullAttribute.cs" />
|
||||
<Compile Include="Nullable\MemberNotNullWhenAttribute.cs" />
|
||||
<Compile Include="Nullable\NotNullAttribute.cs" />
|
||||
<Compile Include="Nullable\NotNullIfNotNullAttribute.cs" />
|
||||
<Compile Include="Nullable\NotNullWhenAttribute.cs" />
|
||||
<Compile Include="Properties\AssemblyInfo.cs" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,16 +1,16 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<packages>
|
||||
<package id="AnyOf" version="0.3.0" targetFramework="net472" />
|
||||
<package id="Fare" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Fare" version="2.2.1" targetFramework="net472" />
|
||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Humanizer" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Json" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Random" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Xeger" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.XPath" version="2.3.3" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Humanizer" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Json" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Random" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.Xeger" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Handlebars.Net.Helpers.XPath" version="2.3.5" targetFramework="net472" />
|
||||
<package id="Humanizer" version="2.14.1" targetFramework="net472" />
|
||||
<package id="Humanizer.Core" version="2.14.1" targetFramework="net472" />
|
||||
<package id="Humanizer.Core.af" version="2.14.1" targetFramework="net472" />
|
||||
@@ -63,6 +63,7 @@
|
||||
<package id="Humanizer.Core.zh-Hant" version="2.14.1" targetFramework="net472" />
|
||||
<package id="JmesPath.Net" version="1.0.125" targetFramework="net472" />
|
||||
<package id="log4net" version="2.0.14" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.8" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNetCore" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNetCore.Authentication.Abstractions" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Microsoft.AspNetCore.Authentication.Core" version="2.2.0" targetFramework="net472" />
|
||||
@@ -119,8 +120,13 @@
|
||||
<package id="Microsoft.IdentityModel.Protocols.OpenIdConnect" version="6.12.2" targetFramework="net472" />
|
||||
<package id="Microsoft.IdentityModel.Tokens" version="6.12.2" targetFramework="net472" />
|
||||
<package id="Microsoft.Net.Http.Headers" version="2.2.0" targetFramework="net472" />
|
||||
<package id="Namotion.Reflection" version="2.0.10" targetFramework="net472" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net472" />
|
||||
<package id="RandomDataGenerator.Net" version="1.0.14" targetFramework="net472" />
|
||||
<package id="NJsonSchema" version="10.6.10" targetFramework="net472" />
|
||||
<package id="NJsonSchema.Extensions" version="0.1.0" targetFramework="net472" />
|
||||
<package id="NSwag.Core" version="13.15.10" targetFramework="net472" />
|
||||
<package id="Nullable" version="1.3.0" targetFramework="net472" developmentDependency="true" />
|
||||
<package id="RandomDataGenerator.Net" version="1.0.16" targetFramework="net472" />
|
||||
<package id="Scriban.Signed" version="2.1.4" targetFramework="net472" />
|
||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net461" />
|
||||
<package id="Stef.Validation" version="0.1.0" targetFramework="net472" />
|
||||
@@ -141,9 +147,9 @@
|
||||
<package id="System.Threading.Tasks.Extensions" version="4.5.1" targetFramework="net472" />
|
||||
<package id="System.ValueTuple" version="4.5.0" targetFramework="net472" />
|
||||
<package id="TinyMapper" version="3.0.3" targetFramework="net472" />
|
||||
<package id="WireMock.Net" version="1.4.41" targetFramework="net472" />
|
||||
<package id="WireMock.Net.Abstractions" version="1.4.41" targetFramework="net472" />
|
||||
<package id="WireMock.Org.Abstractions" version="1.4.41" targetFramework="net472" />
|
||||
<package id="WireMock.Net" version="1.5.3" targetFramework="net472" />
|
||||
<package id="WireMock.Net.Abstractions" version="1.5.3" targetFramework="net472" />
|
||||
<package id="WireMock.Org.Abstractions" version="1.5.3" targetFramework="net472" />
|
||||
<package id="XPath2" version="1.1.3" targetFramework="net472" />
|
||||
<package id="XPath2.Extensions" version="1.1.3" targetFramework="net472" />
|
||||
</packages>
|
||||
@@ -204,8 +204,8 @@
|
||||
<Reference Include="Owin, Version=1.0.0.0, Culture=neutral, PublicKeyToken=f0ebd12fd5e55cc5, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\Owin.1.0\lib\net40\Owin.dll</HintPath>
|
||||
</Reference>
|
||||
<Reference Include="RestEase, Version=1.5.5.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\RestEase.1.5.5\lib\net45\RestEase.dll</HintPath>
|
||||
<Reference Include="RestEase, Version=1.5.7.0, Culture=neutral, processorArchitecture=MSIL">
|
||||
<HintPath>..\..\packages\RestEase.1.5.7\lib\net452\RestEase.dll</HintPath>
|
||||
</Reference>
|
||||
<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>
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
<package id="Microsoft.AspNetCore.Hosting" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Hosting.Abstractions" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Hosting.Server.Abstractions" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Http" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Http" version="2.1.22" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Http.Abstractions" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Http.Extensions" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Http.Features" version="2.1.1" targetFramework="net461" />
|
||||
@@ -24,7 +24,7 @@
|
||||
<package id="Microsoft.AspNetCore.Routing.Abstractions" version="2.1.1" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.IISIntegration" version="2.1.2" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel" version="2.1.3" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Core" version="2.1.3" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Core" version="2.1.7" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Https" version="2.1.3" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Abstractions" version="2.1.3" targetFramework="net461" />
|
||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" version="2.1.3" targetFramework="net461" />
|
||||
@@ -59,7 +59,7 @@
|
||||
<package id="MimeKitLite" version="2.0.7" targetFramework="net461" />
|
||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
|
||||
<package id="Owin" version="1.0" targetFramework="net461" />
|
||||
<package id="RestEase" version="1.5.5" targetFramework="net461" />
|
||||
<package id="RestEase" version="1.5.7" 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.Collections.Immutable" version="1.5.0" targetFramework="net461" />
|
||||
|
||||
@@ -12,7 +12,7 @@
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.0'">
|
||||
<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.2" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.All" Version="2.0.9" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp2.1'">
|
||||
|
||||
@@ -1,48 +1,52 @@
|
||||
namespace WireMock.Admin.Mappings
|
||||
namespace WireMock.Admin.Mappings;
|
||||
|
||||
/// <summary>
|
||||
/// MatcherModel
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class MatcherModel
|
||||
{
|
||||
/// <summary>
|
||||
/// MatcherModel
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class MatcherModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the name.
|
||||
/// </summary>
|
||||
public string Name { get; set; }
|
||||
public string Name { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pattern. Can be a string (default) or an object.
|
||||
/// </summary>
|
||||
public object? Pattern { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the pattern. Can be a string (default) or an object.
|
||||
/// </summary>
|
||||
public object? Pattern { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the patterns. Can be array of strings (default) or an array of objects.
|
||||
/// </summary>
|
||||
public object[]? Patterns { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the patterns. Can be array of strings (default) or an array of objects.
|
||||
/// </summary>
|
||||
public object[]? Patterns { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the pattern as a file.
|
||||
/// </summary>
|
||||
public string? PatternAsFile { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the pattern as a file.
|
||||
/// </summary>
|
||||
public string? PatternAsFile { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the ignore case.
|
||||
/// </summary>
|
||||
public bool? IgnoreCase { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the ignore case.
|
||||
/// </summary>
|
||||
public bool? IgnoreCase { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Reject on match.
|
||||
/// </summary>
|
||||
public bool? RejectOnMatch { get; set; }
|
||||
/// <summary>
|
||||
/// Reject on match.
|
||||
/// </summary>
|
||||
public bool? RejectOnMatch { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The Operator to use when multiple patterns are defined. Optional.
|
||||
/// - null = Same as "or".
|
||||
/// - "or" = Only one pattern should match.
|
||||
/// - "and" = All patterns should match.
|
||||
/// - "average" = The average value from all patterns.
|
||||
/// </summary>
|
||||
public string? MatchOperator { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// The Operator to use when multiple patterns are defined. Optional.
|
||||
/// - null = Same as "or".
|
||||
/// - "or" = Only one pattern should match.
|
||||
/// - "and" = All patterns should match.
|
||||
/// - "average" = The average value from all patterns.
|
||||
/// </summary>
|
||||
public string? MatchOperator { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Support Regex, only used for JsonPartialMatcher.
|
||||
/// </summary>
|
||||
public bool? Regex { get; set; }
|
||||
}
|
||||
@@ -1,24 +1,23 @@
|
||||
namespace WireMock.Admin.Mappings
|
||||
namespace WireMock.Admin.Mappings;
|
||||
|
||||
/// <summary>
|
||||
/// WebProxy settings
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class WebProxyModel
|
||||
{
|
||||
/// <summary>
|
||||
/// WebProxy settings
|
||||
/// A string instance that contains the address of the proxy server.
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class WebProxyModel
|
||||
{
|
||||
/// <summary>
|
||||
/// A string instance that contains the address of the proxy server.
|
||||
/// </summary>
|
||||
public string Address { get; set; }
|
||||
public string Address { get; set; } = null!;
|
||||
|
||||
/// <summary>
|
||||
/// The user name associated with the credentials.
|
||||
/// </summary>
|
||||
public string UserName { get; set; }
|
||||
/// <summary>
|
||||
/// The user name associated with the credentials. [optional]
|
||||
/// </summary>
|
||||
public string? UserName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The password for the user name associated with the credentials.
|
||||
/// </summary>
|
||||
public string Password { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// The password for the user name associated with the credentials. [optional]
|
||||
/// </summary>
|
||||
public string? Password { get; set; }
|
||||
}
|
||||
@@ -1,52 +1,50 @@
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Admin.Mappings
|
||||
namespace WireMock.Admin.Mappings;
|
||||
|
||||
/// <summary>
|
||||
/// RequestModel
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class WebhookRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// RequestModel
|
||||
/// Gets or sets the Url.
|
||||
/// </summary>
|
||||
[FluentBuilder.AutoGenerateBuilder]
|
||||
public class WebhookRequestModel
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the Url.
|
||||
/// </summary>
|
||||
public string Url { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The methods
|
||||
/// </summary>
|
||||
public string Method { get; set; }
|
||||
/// <summary>
|
||||
/// The method
|
||||
/// </summary>
|
||||
public string Method { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, string> Headers { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the headers.
|
||||
/// </summary>
|
||||
public IDictionary<string, string>? Headers { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
public string Body { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
public string? Body { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body (as JSON object).
|
||||
/// </summary>
|
||||
public object BodyAsJson { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the body (as JSON object).
|
||||
/// </summary>
|
||||
public object? BodyAsJson { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Use ResponseMessage Transformer.
|
||||
/// </summary>
|
||||
public bool? UseTransformer { get; set; }
|
||||
/// <summary>
|
||||
/// Use ResponseMessage Transformer.
|
||||
/// </summary>
|
||||
public bool? UseTransformer { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the type of the transformer.
|
||||
/// </summary>
|
||||
public string TransformerType { get; set; }
|
||||
/// <summary>
|
||||
/// Gets the type of the transformer.
|
||||
/// </summary>
|
||||
public string? TransformerType { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||
/// </summary>
|
||||
public string TransformerReplaceNodeOptions { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||
/// </summary>
|
||||
public string? TransformerReplaceNodeOptions { get; set; }
|
||||
}
|
||||
@@ -30,12 +30,12 @@ public class LogEntryModel
|
||||
/// <summary>
|
||||
/// The mapping unique title.
|
||||
/// </summary>
|
||||
public string MappingTitle { get; set; }
|
||||
public string? MappingTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The request match result.
|
||||
/// </summary>
|
||||
public LogRequestMatchModel RequestMatchResult { get; set; }
|
||||
public LogRequestMatchModel? RequestMatchResult { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The partial mapping unique identifier.
|
||||
@@ -45,10 +45,10 @@ public class LogEntryModel
|
||||
/// <summary>
|
||||
/// The partial mapping unique title.
|
||||
/// </summary>
|
||||
public string PartialMappingTitle { get; set; }
|
||||
public string? PartialMappingTitle { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// The partial request match result.
|
||||
/// </summary>
|
||||
public LogRequestMatchModel PartialRequestMatchResult { get; set; }
|
||||
public LogRequestMatchModel? PartialRequestMatchResult { get; set; }
|
||||
}
|
||||
@@ -3,60 +3,59 @@ using WireMock.ResponseBuilders;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock
|
||||
namespace WireMock;
|
||||
|
||||
/// <summary>
|
||||
/// IResponseMessage
|
||||
/// </summary>
|
||||
public interface IResponseMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// IResponseMessage
|
||||
/// The Body.
|
||||
/// </summary>
|
||||
public interface IResponseMessage
|
||||
{
|
||||
/// <summary>
|
||||
/// The Body.
|
||||
/// </summary>
|
||||
IBodyData? BodyData { get; }
|
||||
IBodyData? BodyData { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the body destination (SameAsSource, String or Bytes).
|
||||
/// </summary>
|
||||
string BodyDestination { get; }
|
||||
/// <summary>
|
||||
/// Gets the body destination (Null, SameAsSource, String or Bytes).
|
||||
/// </summary>
|
||||
string? BodyDestination { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
string BodyOriginal { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the body.
|
||||
/// </summary>
|
||||
string? BodyOriginal { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the Fault percentage.
|
||||
/// </summary>
|
||||
double? FaultPercentage { get; }
|
||||
/// <summary>
|
||||
/// Gets the Fault percentage.
|
||||
/// </summary>
|
||||
double? FaultPercentage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The FaultType.
|
||||
/// </summary>
|
||||
FaultType FaultType { get; }
|
||||
/// <summary>
|
||||
/// The FaultType.
|
||||
/// </summary>
|
||||
FaultType FaultType { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
IDictionary<string, WireMockList<string>>? Headers { get; }
|
||||
/// <summary>
|
||||
/// Gets the headers.
|
||||
/// </summary>
|
||||
IDictionary<string, WireMockList<string>>? Headers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the status code.
|
||||
/// </summary>
|
||||
object StatusCode { get; }
|
||||
/// <summary>
|
||||
/// Gets or sets the status code.
|
||||
/// </summary>
|
||||
object? StatusCode { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void AddHeader(string name, string value);
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="value">The value.</param>
|
||||
void AddHeader(string name, string value);
|
||||
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
void AddHeader(string name, params string[] values);
|
||||
}
|
||||
/// <summary>
|
||||
/// Adds the header.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="values">The values.</param>
|
||||
void AddHeader(string name, params string[] values);
|
||||
}
|
||||
@@ -1,56 +1,55 @@
|
||||
using System;
|
||||
using System;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Logging
|
||||
namespace WireMock.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// ILogEntry
|
||||
/// </summary>
|
||||
public interface ILogEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// ILogEntry
|
||||
/// Gets the unique identifier.
|
||||
/// </summary>
|
||||
public interface ILogEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the unique identifier.
|
||||
/// </summary>
|
||||
Guid Guid { get; }
|
||||
Guid Guid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mapping unique identifier.
|
||||
/// </summary>
|
||||
Guid? MappingGuid { get; }
|
||||
/// <summary>
|
||||
/// Gets the mapping unique identifier.
|
||||
/// </summary>
|
||||
Guid? MappingGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the mapping unique title.
|
||||
/// </summary>
|
||||
string MappingTitle { get; }
|
||||
/// <summary>
|
||||
/// Gets the mapping unique title.
|
||||
/// </summary>
|
||||
string? MappingTitle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the partial mapping unique identifier.
|
||||
/// </summary>
|
||||
Guid? PartialMappingGuid { get; }
|
||||
/// <summary>
|
||||
/// Gets the partial mapping unique identifier.
|
||||
/// </summary>
|
||||
Guid? PartialMappingGuid { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the partial mapping unique title.
|
||||
/// </summary>
|
||||
string PartialMappingTitle { get; }
|
||||
/// <summary>
|
||||
/// Gets the partial mapping unique title.
|
||||
/// </summary>
|
||||
string? PartialMappingTitle { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the partial match result.
|
||||
/// </summary>
|
||||
IRequestMatchResult PartialMatchResult { get; }
|
||||
/// <summary>
|
||||
/// Gets the partial match result.
|
||||
/// </summary>
|
||||
IRequestMatchResult PartialMatchResult { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request match result.
|
||||
/// </summary>
|
||||
IRequestMatchResult RequestMatchResult { get; }
|
||||
/// <summary>
|
||||
/// Gets the request match result.
|
||||
/// </summary>
|
||||
IRequestMatchResult RequestMatchResult { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request message.
|
||||
/// </summary>
|
||||
IRequestMessage RequestMessage { get; }
|
||||
/// <summary>
|
||||
/// Gets the request message.
|
||||
/// </summary>
|
||||
IRequestMessage RequestMessage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the response message.
|
||||
/// </summary>
|
||||
IResponseMessage ResponseMessage { get; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets the response message.
|
||||
/// </summary>
|
||||
IResponseMessage ResponseMessage { get; }
|
||||
}
|
||||
@@ -1,20 +1,17 @@
|
||||
using JetBrains.Annotations;
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
/// <summary>
|
||||
/// The RequestMatcher interface.
|
||||
/// </summary>
|
||||
public interface IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The RequestMatcher interface.
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
public interface IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified RequestMessage is match.
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult);
|
||||
}
|
||||
/// <param name="requestMessage">The RequestMessage.</param>
|
||||
/// <param name="requestMatchResult">The RequestMatchResult.</param>
|
||||
/// <returns>
|
||||
/// A value between 0.0 - 1.0 of the similarity.
|
||||
/// </returns>
|
||||
double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult);
|
||||
}
|
||||
@@ -1,25 +1,24 @@
|
||||
using System;
|
||||
|
||||
namespace WireMock.Models
|
||||
namespace WireMock.Models;
|
||||
|
||||
/// <summary>
|
||||
/// TimeSettings: Start, End and TTL
|
||||
/// </summary>
|
||||
public interface ITimeSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// TimeSettings: Start, End and TTL
|
||||
/// Gets or sets the DateTime from which this mapping should be used. In case this is not defined, it's used (default behavior).
|
||||
/// </summary>
|
||||
public interface ITimeSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets or sets the DateTime from which this mapping should be used. In case this is not defined, it's used (default behavior).
|
||||
/// </summary>
|
||||
DateTime? Start { get; set; }
|
||||
DateTime? Start { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the DateTime from until this mapping should be used. In case this is not defined, it's used forever (default behavior).
|
||||
/// </summary>
|
||||
DateTime? End { get; set; }
|
||||
/// <summary>
|
||||
/// Gets or sets the DateTime from until this mapping should be used. In case this is not defined, it's used forever (default behavior).
|
||||
/// </summary>
|
||||
DateTime? End { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets or sets the TTL (Time To Live) in seconds for this mapping. In case this is not defined, it's used (default behavior).
|
||||
/// </summary>
|
||||
int? TTL { get; set; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Gets or sets the TTL (Time To Live) in seconds for this mapping. In case this is not defined, it's used (default behavior).
|
||||
/// </summary>
|
||||
int? TTL { get; set; }
|
||||
}
|
||||
@@ -1,13 +1,12 @@
|
||||
namespace WireMock.Models
|
||||
namespace WireMock.Models;
|
||||
|
||||
/// <summary>
|
||||
/// IWebhook
|
||||
/// </summary>
|
||||
public interface IWebhook
|
||||
{
|
||||
/// <summary>
|
||||
/// IWebhook
|
||||
/// Request
|
||||
/// </summary>
|
||||
public interface IWebhook
|
||||
{
|
||||
/// <summary>
|
||||
/// Request
|
||||
/// </summary>
|
||||
IWebhookRequest Request { get; set; }
|
||||
}
|
||||
IWebhookRequest Request { get; set; }
|
||||
}
|
||||
@@ -35,7 +35,7 @@
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
|
||||
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
|
||||
<PackageReference Include="FluentBuilder" Version="0.4.4">
|
||||
<PackageReference Include="FluentBuilder" Version="0.5.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -59,7 +59,7 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
public double IsMatch(string input)
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
return IsMatchInternal(input);
|
||||
}
|
||||
|
||||
@@ -25,7 +25,7 @@
|
||||
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.15" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.16" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
|
||||
@@ -31,7 +31,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="RestEase" Version="1.5.6" />
|
||||
<PackageReference Include="RestEase" Version="1.5.7" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
#if !NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IdentityModel.Tokens.Jwt;
|
||||
using System.Text.RegularExpressions;
|
||||
@@ -6,67 +7,72 @@ using AnyOfTypes;
|
||||
using Microsoft.IdentityModel.Protocols;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Stef.Validation;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Authentication
|
||||
namespace WireMock.Authentication;
|
||||
|
||||
/// <summary>
|
||||
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
|
||||
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
|
||||
/// </summary>
|
||||
internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// https://www.c-sharpcorner.com/article/how-to-validate-azure-ad-token-using-console-application/
|
||||
/// https://stackoverflow.com/questions/38684865/validation-of-an-azure-ad-bearer-token-in-a-console-application
|
||||
/// </summary>
|
||||
internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
private const string BearerPrefix = "Bearer ";
|
||||
|
||||
private readonly string _audience;
|
||||
private readonly string _stsDiscoveryEndpoint;
|
||||
|
||||
public AzureADAuthenticationMatcher(string tenant, string audience)
|
||||
{
|
||||
private const string BearerPrefix = "Bearer ";
|
||||
_audience = Guard.NotNullOrEmpty(audience);
|
||||
_stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", Guard.NotNullOrEmpty(tenant));
|
||||
}
|
||||
|
||||
private readonly string _audience;
|
||||
private readonly string _stsDiscoveryEndpoint;
|
||||
public string Name => nameof(AzureADAuthenticationMatcher);
|
||||
|
||||
public AzureADAuthenticationMatcher(string tenant, string audience)
|
||||
public MatchBehaviour MatchBehaviour => MatchBehaviour.AcceptOnMatch;
|
||||
|
||||
public bool ThrowException => false;
|
||||
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return EmptyArray<AnyOf<string, StringPattern>>.Value;
|
||||
}
|
||||
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input))
|
||||
{
|
||||
_audience = audience;
|
||||
_stsDiscoveryEndpoint = string.Format(CultureInfo.InvariantCulture, "https://login.microsoftonline.com/{0}/.well-known/openid-configuration", tenant);
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
public string Name => nameof(AzureADAuthenticationMatcher);
|
||||
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
|
||||
|
||||
public MatchBehaviour MatchBehaviour => MatchBehaviour.AcceptOnMatch;
|
||||
|
||||
public bool ThrowException => false;
|
||||
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
try
|
||||
{
|
||||
return new AnyOf<string, StringPattern>[0];
|
||||
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(_stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
|
||||
var config = configManager.GetConfigurationAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
var validationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidAudience = _audience,
|
||||
ValidIssuer = config.Issuer,
|
||||
IssuerSigningKeys = config.SigningKeys,
|
||||
ValidateLifetime = true
|
||||
};
|
||||
|
||||
// Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)
|
||||
new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var _);
|
||||
|
||||
return MatchScores.Perfect;
|
||||
}
|
||||
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
|
||||
public double IsMatch(string input)
|
||||
catch
|
||||
{
|
||||
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
|
||||
|
||||
try
|
||||
{
|
||||
var configManager = new ConfigurationManager<OpenIdConnectConfiguration>(_stsDiscoveryEndpoint, new OpenIdConnectConfigurationRetriever());
|
||||
var config = configManager.GetConfigurationAsync().ConfigureAwait(false).GetAwaiter().GetResult();
|
||||
|
||||
var validationParameters = new TokenValidationParameters
|
||||
{
|
||||
ValidAudience = _audience,
|
||||
ValidIssuer = config.Issuer,
|
||||
IssuerSigningKeys = config.SigningKeys,
|
||||
ValidateLifetime = true
|
||||
};
|
||||
|
||||
// Throws an Exception as the token is invalid (expired, invalid-formatted, etc.)
|
||||
new JwtSecurityTokenHandler().ValidateToken(token, validationParameters, out var _);
|
||||
|
||||
return MatchScores.Perfect;
|
||||
}
|
||||
catch
|
||||
{
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,19 +2,18 @@ using System;
|
||||
using System.Text;
|
||||
using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.Authentication
|
||||
namespace WireMock.Authentication;
|
||||
|
||||
internal class BasicAuthenticationMatcher : RegexMatcher
|
||||
{
|
||||
internal class BasicAuthenticationMatcher : RegexMatcher
|
||||
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
|
||||
{
|
||||
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
|
||||
{
|
||||
}
|
||||
}
|
||||
|
||||
public override string Name => nameof(BasicAuthenticationMatcher);
|
||||
public override string Name => nameof(BasicAuthenticationMatcher);
|
||||
|
||||
private static string BuildPattern(string username, string password)
|
||||
{
|
||||
return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$";
|
||||
}
|
||||
private static string BuildPattern(string username, string password)
|
||||
{
|
||||
return "^(?i)BASIC " + Convert.ToBase64String(Encoding.GetEncoding("ISO-8859-1").GetBytes(username + ":" + password)) + "$";
|
||||
}
|
||||
}
|
||||
11
src/WireMock.Net/Compatibility/EmptyArray.cs
Normal file
11
src/WireMock.Net/Compatibility/EmptyArray.cs
Normal file
@@ -0,0 +1,11 @@
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System;
|
||||
|
||||
internal static class EmptyArray<T>
|
||||
{
|
||||
#if NET451 || NET452
|
||||
public static readonly T[] Value = new T[0];
|
||||
#else
|
||||
public static readonly T[] Value = Array.Empty<T>();
|
||||
#endif
|
||||
}
|
||||
@@ -1,28 +1,26 @@
|
||||
#if NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Net;
|
||||
#if NETSTANDARD1_3
|
||||
|
||||
namespace System.Net
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System.Net;
|
||||
|
||||
internal class WebProxy : IWebProxy
|
||||
{
|
||||
internal class WebProxy : IWebProxy
|
||||
private readonly string _proxy;
|
||||
public ICredentials? Credentials { get; set; }
|
||||
|
||||
public WebProxy(string proxy)
|
||||
{
|
||||
private readonly string _proxy;
|
||||
public ICredentials Credentials { get; set; }
|
||||
_proxy = proxy;
|
||||
}
|
||||
|
||||
public WebProxy(string proxy)
|
||||
{
|
||||
_proxy = proxy;
|
||||
}
|
||||
public Uri GetProxy(Uri destination)
|
||||
{
|
||||
return new Uri(_proxy);
|
||||
}
|
||||
|
||||
public Uri GetProxy(Uri destination)
|
||||
{
|
||||
return new Uri(_proxy);
|
||||
}
|
||||
|
||||
public bool IsBypassed(Uri host)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
public bool IsBypassed(Uri host)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,26 +1,24 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Extensions
|
||||
namespace WireMock.Extensions;
|
||||
|
||||
internal static class AnyOfExtensions
|
||||
{
|
||||
internal static class AnyOfExtensions
|
||||
public static string GetPattern(this AnyOf<string, StringPattern> value)
|
||||
{
|
||||
public static string GetPattern([NotNull] this AnyOf<string, StringPattern> value)
|
||||
{
|
||||
return value.IsFirst ? value.First : value.Second.Pattern;
|
||||
}
|
||||
return value.IsFirst ? value.First : value.Second.Pattern;
|
||||
}
|
||||
|
||||
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns([NotNull] this IEnumerable<string> patterns)
|
||||
{
|
||||
return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
|
||||
}
|
||||
public static AnyOf<string, StringPattern>[] ToAnyOfPatterns(this IEnumerable<string> patterns)
|
||||
{
|
||||
return patterns.Select(p => p.ToAnyOfPattern()).ToArray();
|
||||
}
|
||||
|
||||
public static AnyOf<string, StringPattern> ToAnyOfPattern([CanBeNull] this string pattern)
|
||||
{
|
||||
return new AnyOf<string, StringPattern>(pattern);
|
||||
}
|
||||
public static AnyOf<string, StringPattern> ToAnyOfPattern(this string pattern)
|
||||
{
|
||||
return new AnyOf<string, StringPattern>(pattern);
|
||||
}
|
||||
}
|
||||
@@ -1,35 +1,34 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Extensions
|
||||
namespace WireMock.Extensions;
|
||||
|
||||
internal static class TimeSettingsExtensions
|
||||
{
|
||||
internal static class TimeSettingsExtensions
|
||||
public static bool IsValid(this ITimeSettings? settings)
|
||||
{
|
||||
public static bool IsValid([CanBeNull] this ITimeSettings settings)
|
||||
if (settings == null)
|
||||
{
|
||||
if (settings == null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
var start = settings.Start != null ? settings.Start.Value : now;
|
||||
DateTime end;
|
||||
if (settings.End != null)
|
||||
{
|
||||
end = settings.End.Value;
|
||||
}
|
||||
else if (settings.TTL != null)
|
||||
{
|
||||
end = start.AddSeconds(settings.TTL.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = DateTime.MaxValue;
|
||||
}
|
||||
|
||||
return now >= start && now <= end;
|
||||
return true;
|
||||
}
|
||||
|
||||
var now = DateTime.Now;
|
||||
var start = settings.Start ?? now;
|
||||
DateTime end;
|
||||
|
||||
if (settings.End != null)
|
||||
{
|
||||
end = settings.End.Value;
|
||||
}
|
||||
else if (settings.TTL != null)
|
||||
{
|
||||
end = start.AddSeconds(settings.TTL.Value);
|
||||
}
|
||||
else
|
||||
{
|
||||
end = DateTime.MaxValue;
|
||||
}
|
||||
|
||||
return now >= start && now <= end;
|
||||
}
|
||||
}
|
||||
@@ -1,30 +1,28 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal static class ByteArrayContentHelper
|
||||
{
|
||||
internal static class ByteArrayContentHelper
|
||||
/// <summary>
|
||||
/// Creates a ByteArrayContent object.
|
||||
/// </summary>
|
||||
/// <param name="content">The byte[] content (cannot be null)</param>
|
||||
/// <param name="contentType">The ContentType (can be null)</param>
|
||||
/// <returns>ByteArrayContent</returns>
|
||||
internal static ByteArrayContent Create(byte[] content, MediaTypeHeaderValue? contentType)
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a ByteArrayContent object.
|
||||
/// </summary>
|
||||
/// <param name="content">The byte[] content (cannot be null)</param>
|
||||
/// <param name="contentType">The ContentType (can be null)</param>
|
||||
/// <returns>ByteArrayContent</returns>
|
||||
internal static ByteArrayContent Create([NotNull] byte[] content, [CanBeNull] MediaTypeHeaderValue contentType)
|
||||
Guard.NotNull(content);
|
||||
|
||||
var byteContent = new ByteArrayContent(content);
|
||||
if (contentType != null)
|
||||
{
|
||||
Guard.NotNull(content, nameof(content));
|
||||
|
||||
var byteContent = new ByteArrayContent(content);
|
||||
if (contentType != null)
|
||||
{
|
||||
byteContent.Headers.Remove(HttpKnownHeaderNames.ContentType);
|
||||
byteContent.Headers.ContentType = contentType;
|
||||
}
|
||||
|
||||
return byteContent;
|
||||
byteContent.Headers.Remove(HttpKnownHeaderNames.ContentType);
|
||||
byteContent.Headers.ContentType = contentType;
|
||||
}
|
||||
|
||||
return byteContent;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,122 +1,121 @@
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// Licensed to the .NET Foundation under one or more agreements.
|
||||
// The .NET Foundation licenses this file to you under the MIT license.
|
||||
// See the LICENSE file in the project root for more information.
|
||||
|
||||
using System;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
/// <summary>
|
||||
/// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/Common/src/System/Net/HttpKnownHeaderNames.cs
|
||||
/// </summary>
|
||||
internal static class HttpKnownHeaderNames
|
||||
{
|
||||
/// <summary>
|
||||
/// Copied from https://raw.githubusercontent.com/dotnet/corefx/master/src/Common/src/System/Net/HttpKnownHeaderNames.cs
|
||||
/// </summary>
|
||||
internal static class HttpKnownHeaderNames
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted
|
||||
private static readonly string[] RestrictedResponseHeaders =
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted
|
||||
private static readonly string[] RestrictedResponseHeaders =
|
||||
{
|
||||
Accept,
|
||||
Connection,
|
||||
ContentLength,
|
||||
ContentType,
|
||||
Date, // RFC1123Pattern
|
||||
Expect,
|
||||
Host,
|
||||
IfModifiedSince,
|
||||
Range,
|
||||
Referer,
|
||||
TransferEncoding,
|
||||
UserAgent,
|
||||
ProxyConnection
|
||||
};
|
||||
Accept,
|
||||
Connection,
|
||||
ContentLength,
|
||||
ContentType,
|
||||
Date, // RFC1123Pattern
|
||||
Expect,
|
||||
Host,
|
||||
IfModifiedSince,
|
||||
Range,
|
||||
Referer,
|
||||
TransferEncoding,
|
||||
UserAgent,
|
||||
ProxyConnection
|
||||
};
|
||||
|
||||
/// <summary>Tests whether the specified HTTP header can be set for the response.</summary>
|
||||
/// <param name="headerName">The header to test.</param>
|
||||
/// <returns>true if the header is restricted; otherwise, false.</returns>
|
||||
public static bool IsRestrictedResponseHeader(string headerName) => RestrictedResponseHeaders.Contains(headerName, StringComparer.OrdinalIgnoreCase);
|
||||
/// <summary>Tests whether the specified HTTP header can be set for the response.</summary>
|
||||
/// <param name="headerName">The header to test.</param>
|
||||
/// <returns>true if the header is restricted; otherwise, false.</returns>
|
||||
public static bool IsRestrictedResponseHeader(string headerName) => RestrictedResponseHeaders.Contains(headerName, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
public const string Accept = "Accept";
|
||||
public const string AcceptCharset = "Accept-Charset";
|
||||
public const string AcceptEncoding = "Accept-Encoding";
|
||||
public const string AcceptLanguage = "Accept-Language";
|
||||
public const string AcceptPatch = "Accept-Patch";
|
||||
public const string AcceptRanges = "Accept-Ranges";
|
||||
public const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
|
||||
public const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
|
||||
public const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
|
||||
public const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
|
||||
public const string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
|
||||
public const string AccessControlMaxAge = "Access-Control-Max-Age";
|
||||
public const string Age = "Age";
|
||||
public const string Allow = "Allow";
|
||||
public const string AltSvc = "Alt-Svc";
|
||||
public const string Authorization = "Authorization";
|
||||
public const string CacheControl = "Cache-Control";
|
||||
public const string Connection = "Connection";
|
||||
public const string ContentDisposition = "Content-Disposition";
|
||||
public const string ContentEncoding = "Content-Encoding";
|
||||
public const string ContentLanguage = "Content-Language";
|
||||
public const string ContentLength = "Content-Length";
|
||||
public const string ContentLocation = "Content-Location";
|
||||
public const string ContentMD5 = "Content-MD5";
|
||||
public const string ContentRange = "Content-Range";
|
||||
public const string ContentSecurityPolicy = "Content-Security-Policy";
|
||||
public const string ContentType = "Content-Type";
|
||||
public const string Cookie = "Cookie";
|
||||
public const string Cookie2 = "Cookie2";
|
||||
public const string Date = "Date";
|
||||
public const string ETag = "ETag";
|
||||
public const string Expect = "Expect";
|
||||
public const string Expires = "Expires";
|
||||
public const string From = "From";
|
||||
public const string Host = "Host";
|
||||
public const string IfMatch = "If-Match";
|
||||
public const string IfModifiedSince = "If-Modified-Since";
|
||||
public const string IfNoneMatch = "If-None-Match";
|
||||
public const string IfRange = "If-Range";
|
||||
public const string IfUnmodifiedSince = "If-Unmodified-Since";
|
||||
public const string KeepAlive = "Keep-Alive";
|
||||
public const string LastModified = "Last-Modified";
|
||||
public const string Link = "Link";
|
||||
public const string Location = "Location";
|
||||
public const string MaxForwards = "Max-Forwards";
|
||||
public const string Origin = "Origin";
|
||||
public const string P3P = "P3P";
|
||||
public const string Pragma = "Pragma";
|
||||
public const string ProxyAuthenticate = "Proxy-Authenticate";
|
||||
public const string ProxyAuthorization = "Proxy-Authorization";
|
||||
public const string ProxyConnection = "Proxy-Connection";
|
||||
public const string PublicKeyPins = "Public-Key-Pins";
|
||||
public const string Range = "Range";
|
||||
public const string Referer = "Referer"; // NB: The spelling-mistake "Referer" for "Referrer" must be matched.
|
||||
public const string RetryAfter = "Retry-After";
|
||||
public const string SecWebSocketAccept = "Sec-WebSocket-Accept";
|
||||
public const string SecWebSocketExtensions = "Sec-WebSocket-Extensions";
|
||||
public const string SecWebSocketKey = "Sec-WebSocket-Key";
|
||||
public const string SecWebSocketProtocol = "Sec-WebSocket-Protocol";
|
||||
public const string SecWebSocketVersion = "Sec-WebSocket-Version";
|
||||
public const string Server = "Server";
|
||||
public const string SetCookie = "Set-Cookie";
|
||||
public const string SetCookie2 = "Set-Cookie2";
|
||||
public const string StrictTransportSecurity = "Strict-Transport-Security";
|
||||
public const string TE = "TE";
|
||||
public const string TSV = "TSV";
|
||||
public const string Trailer = "Trailer";
|
||||
public const string TransferEncoding = "Transfer-Encoding";
|
||||
public const string Upgrade = "Upgrade";
|
||||
public const string UpgradeInsecureRequests = "Upgrade-Insecure-Requests";
|
||||
public const string UserAgent = "User-Agent";
|
||||
public const string Vary = "Vary";
|
||||
public const string Via = "Via";
|
||||
public const string WWWAuthenticate = "WWW-Authenticate";
|
||||
public const string Warning = "Warning";
|
||||
public const string XAspNetVersion = "X-AspNet-Version";
|
||||
public const string XContentDuration = "X-Content-Duration";
|
||||
public const string XContentTypeOptions = "X-Content-Type-Options";
|
||||
public const string XFrameOptions = "X-Frame-Options";
|
||||
public const string XMSEdgeRef = "X-MSEdge-Ref";
|
||||
public const string XPoweredBy = "X-Powered-By";
|
||||
public const string XRequestID = "X-Request-ID";
|
||||
public const string XUACompatible = "X-UA-Compatible";
|
||||
}
|
||||
public const string Accept = "Accept";
|
||||
public const string AcceptCharset = "Accept-Charset";
|
||||
public const string AcceptEncoding = "Accept-Encoding";
|
||||
public const string AcceptLanguage = "Accept-Language";
|
||||
public const string AcceptPatch = "Accept-Patch";
|
||||
public const string AcceptRanges = "Accept-Ranges";
|
||||
public const string AccessControlAllowCredentials = "Access-Control-Allow-Credentials";
|
||||
public const string AccessControlAllowHeaders = "Access-Control-Allow-Headers";
|
||||
public const string AccessControlAllowMethods = "Access-Control-Allow-Methods";
|
||||
public const string AccessControlAllowOrigin = "Access-Control-Allow-Origin";
|
||||
public const string AccessControlExposeHeaders = "Access-Control-Expose-Headers";
|
||||
public const string AccessControlMaxAge = "Access-Control-Max-Age";
|
||||
public const string Age = "Age";
|
||||
public const string Allow = "Allow";
|
||||
public const string AltSvc = "Alt-Svc";
|
||||
public const string Authorization = "Authorization";
|
||||
public const string CacheControl = "Cache-Control";
|
||||
public const string Connection = "Connection";
|
||||
public const string ContentDisposition = "Content-Disposition";
|
||||
public const string ContentEncoding = "Content-Encoding";
|
||||
public const string ContentLanguage = "Content-Language";
|
||||
public const string ContentLength = "Content-Length";
|
||||
public const string ContentLocation = "Content-Location";
|
||||
public const string ContentMD5 = "Content-MD5";
|
||||
public const string ContentRange = "Content-Range";
|
||||
public const string ContentSecurityPolicy = "Content-Security-Policy";
|
||||
public const string ContentType = "Content-Type";
|
||||
public const string Cookie = "Cookie";
|
||||
public const string Cookie2 = "Cookie2";
|
||||
public const string Date = "Date";
|
||||
public const string ETag = "ETag";
|
||||
public const string Expect = "Expect";
|
||||
public const string Expires = "Expires";
|
||||
public const string From = "From";
|
||||
public const string Host = "Host";
|
||||
public const string IfMatch = "If-Match";
|
||||
public const string IfModifiedSince = "If-Modified-Since";
|
||||
public const string IfNoneMatch = "If-None-Match";
|
||||
public const string IfRange = "If-Range";
|
||||
public const string IfUnmodifiedSince = "If-Unmodified-Since";
|
||||
public const string KeepAlive = "Keep-Alive";
|
||||
public const string LastModified = "Last-Modified";
|
||||
public const string Link = "Link";
|
||||
public const string Location = "Location";
|
||||
public const string MaxForwards = "Max-Forwards";
|
||||
public const string Origin = "Origin";
|
||||
public const string P3P = "P3P";
|
||||
public const string Pragma = "Pragma";
|
||||
public const string ProxyAuthenticate = "Proxy-Authenticate";
|
||||
public const string ProxyAuthorization = "Proxy-Authorization";
|
||||
public const string ProxyConnection = "Proxy-Connection";
|
||||
public const string PublicKeyPins = "Public-Key-Pins";
|
||||
public const string Range = "Range";
|
||||
public const string Referer = "Referer"; // NB: The spelling-mistake "Referer" for "Referrer" must be matched.
|
||||
public const string RetryAfter = "Retry-After";
|
||||
public const string SecWebSocketAccept = "Sec-WebSocket-Accept";
|
||||
public const string SecWebSocketExtensions = "Sec-WebSocket-Extensions";
|
||||
public const string SecWebSocketKey = "Sec-WebSocket-Key";
|
||||
public const string SecWebSocketProtocol = "Sec-WebSocket-Protocol";
|
||||
public const string SecWebSocketVersion = "Sec-WebSocket-Version";
|
||||
public const string Server = "Server";
|
||||
public const string SetCookie = "Set-Cookie";
|
||||
public const string SetCookie2 = "Set-Cookie2";
|
||||
public const string StrictTransportSecurity = "Strict-Transport-Security";
|
||||
public const string TE = "TE";
|
||||
public const string TSV = "TSV";
|
||||
public const string Trailer = "Trailer";
|
||||
public const string TransferEncoding = "Transfer-Encoding";
|
||||
public const string Upgrade = "Upgrade";
|
||||
public const string UpgradeInsecureRequests = "Upgrade-Insecure-Requests";
|
||||
public const string UserAgent = "User-Agent";
|
||||
public const string Vary = "Vary";
|
||||
public const string Via = "Via";
|
||||
public const string WWWAuthenticate = "WWW-Authenticate";
|
||||
public const string Warning = "Warning";
|
||||
public const string XAspNetVersion = "X-AspNet-Version";
|
||||
public const string XContentDuration = "X-Content-Duration";
|
||||
public const string XContentTypeOptions = "X-Content-Type-Options";
|
||||
public const string XFrameOptions = "X-Frame-Options";
|
||||
public const string XMSEdgeRef = "X-MSEdge-Ref";
|
||||
public const string XPoweredBy = "X-Powered-By";
|
||||
public const string XRequestID = "X-Request-ID";
|
||||
public const string XUACompatible = "X-UA-Compatible";
|
||||
}
|
||||
@@ -3,89 +3,87 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Types;
|
||||
using Stef.Validation;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal static class HttpRequestMessageHelper
|
||||
{
|
||||
internal static class HttpRequestMessageHelper
|
||||
internal static HttpRequestMessage Create(IRequestMessage requestMessage, string url)
|
||||
{
|
||||
internal static HttpRequestMessage Create([NotNull] IRequestMessage requestMessage, [NotNull] string url)
|
||||
Guard.NotNull(requestMessage);
|
||||
Guard.NotNullOrEmpty(url);
|
||||
|
||||
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
|
||||
|
||||
MediaTypeHeaderValue? contentType = null;
|
||||
if (requestMessage.Headers != null && requestMessage.Headers.ContainsKey(HttpKnownHeaderNames.ContentType))
|
||||
{
|
||||
Guard.NotNull(requestMessage, nameof(requestMessage));
|
||||
Guard.NotNullOrEmpty(url, nameof(url));
|
||||
var value = requestMessage.Headers[HttpKnownHeaderNames.ContentType].FirstOrDefault();
|
||||
MediaTypeHeaderValue.TryParse(value, out contentType);
|
||||
}
|
||||
|
||||
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Bytes:
|
||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes, contentType);
|
||||
break;
|
||||
|
||||
MediaTypeHeaderValue contentType = null;
|
||||
if (requestMessage.Headers != null && requestMessage.Headers.ContainsKey(HttpKnownHeaderNames.ContentType))
|
||||
{
|
||||
var value = requestMessage.Headers[HttpKnownHeaderNames.ContentType].FirstOrDefault();
|
||||
MediaTypeHeaderValue.TryParse(value, out contentType);
|
||||
}
|
||||
case BodyType.Json:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType);
|
||||
break;
|
||||
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Bytes:
|
||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes, contentType);
|
||||
break;
|
||||
case BodyType.String:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType);
|
||||
break;
|
||||
}
|
||||
|
||||
case BodyType.Json:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType);
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType);
|
||||
break;
|
||||
}
|
||||
|
||||
// Overwrite the host header
|
||||
httpRequestMessage.Headers.Host = new Uri(url).Authority;
|
||||
|
||||
// Set other headers if present
|
||||
if (requestMessage.Headers == null || requestMessage.Headers.Count == 0)
|
||||
{
|
||||
return httpRequestMessage;
|
||||
}
|
||||
|
||||
var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host, HttpKnownHeaderNames.ContentLength };
|
||||
if (contentType != null)
|
||||
{
|
||||
// Content-Type should be set on the content
|
||||
excludeHeaders.Add(HttpKnownHeaderNames.ContentType);
|
||||
}
|
||||
|
||||
foreach (var header in requestMessage.Headers.Where(h => !excludeHeaders.Contains(h.Key, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Headers.Contains() with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Content.Headers.Contains(...) with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Content != null && httpRequestMessage.Content.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to add to request headers. If failed - try to add to content headers. If still fails, just ignore this header.
|
||||
try
|
||||
{
|
||||
if (!httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value))
|
||||
{
|
||||
httpRequestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Just continue
|
||||
}
|
||||
}
|
||||
// Overwrite the host header
|
||||
httpRequestMessage.Headers.Host = new Uri(url).Authority;
|
||||
|
||||
// Set other headers if present
|
||||
if (requestMessage.Headers == null || requestMessage.Headers.Count == 0)
|
||||
{
|
||||
return httpRequestMessage;
|
||||
}
|
||||
|
||||
var excludeHeaders = new List<string> { HttpKnownHeaderNames.Host, HttpKnownHeaderNames.ContentLength };
|
||||
if (contentType != null)
|
||||
{
|
||||
// Content-Type should be set on the content
|
||||
excludeHeaders.Add(HttpKnownHeaderNames.ContentType);
|
||||
}
|
||||
|
||||
foreach (var header in requestMessage.Headers.Where(h => !excludeHeaders.Contains(h.Key, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Headers.Contains() with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Content.Headers.Contains(...) with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Content != null && httpRequestMessage.Content.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to add to request headers. If failed - try to add to content headers. If still fails, just ignore this header.
|
||||
try
|
||||
{
|
||||
if (!httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value))
|
||||
{
|
||||
httpRequestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Just continue
|
||||
}
|
||||
}
|
||||
|
||||
return httpRequestMessage;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
/// <summary>
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||
/// </summary>
|
||||
internal static class HttpRequestMethods
|
||||
{
|
||||
/// <summary>
|
||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||
/// </summary>
|
||||
internal static class HttpRequestMethods
|
||||
{
|
||||
public const string CONNECT = "CONNECT";
|
||||
public const string DELETE = "DELETE";
|
||||
public const string GET = "GET";
|
||||
public const string HEAD = "HEAD";
|
||||
public const string OPTIONS = "OPTIONS";
|
||||
public const string PATCH = "PATCH";
|
||||
public const string POST = "POST";
|
||||
public const string PUT = "PUT";
|
||||
public const string TRACE = "TRACE";
|
||||
}
|
||||
public const string CONNECT = "CONNECT";
|
||||
public const string DELETE = "DELETE";
|
||||
public const string GET = "GET";
|
||||
public const string HEAD = "HEAD";
|
||||
public const string OPTIONS = "OPTIONS";
|
||||
public const string PATCH = "PATCH";
|
||||
public const string POST = "POST";
|
||||
public const string PUT = "PUT";
|
||||
public const string TRACE = "TRACE";
|
||||
}
|
||||
@@ -5,60 +5,64 @@ using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal static class HttpResponseMessageHelper
|
||||
{
|
||||
internal static class HttpResponseMessageHelper
|
||||
public static async Task<ResponseMessage> CreateAsync(
|
||||
HttpResponseMessage httpResponseMessage,
|
||||
Uri requiredUri,
|
||||
Uri originalUri,
|
||||
bool deserializeJson,
|
||||
bool decompressGzipAndDeflate)
|
||||
{
|
||||
public static async Task<ResponseMessage> CreateAsync(HttpResponseMessage httpResponseMessage, Uri requiredUri, Uri originalUri, bool deserializeJson, bool decompressGzipAndDeflate)
|
||||
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
|
||||
|
||||
// Set both content and response headers, replacing URLs in values
|
||||
var headers = (httpResponseMessage.Content?.Headers.Union(httpResponseMessage.Headers) ?? Enumerable.Empty<KeyValuePair<string, IEnumerable<string>>>()).ToArray();
|
||||
if (httpResponseMessage.Content != null)
|
||||
{
|
||||
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
|
||||
|
||||
// Set both content and response headers, replacing URLs in values
|
||||
var headers = (httpResponseMessage.Content?.Headers.Union(httpResponseMessage.Headers) ?? Enumerable.Empty<KeyValuePair<string, IEnumerable<string>>>()).ToArray();
|
||||
if (httpResponseMessage.Content != null)
|
||||
var stream = await httpResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
IEnumerable<string>? contentTypeHeader = null;
|
||||
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
var stream = await httpResponseMessage.Content.ReadAsStreamAsync().ConfigureAwait(false);
|
||||
IEnumerable<string> contentTypeHeader = null;
|
||||
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
|
||||
}
|
||||
|
||||
IEnumerable<string> contentEncodingHeader = null;
|
||||
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
contentEncodingHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)).Value;
|
||||
}
|
||||
|
||||
var bodyParserSettings = new BodyParserSettings
|
||||
{
|
||||
Stream = stream,
|
||||
ContentType = contentTypeHeader?.FirstOrDefault(),
|
||||
DeserializeJson = deserializeJson,
|
||||
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
|
||||
DecompressGZipAndDeflate = decompressGzipAndDeflate
|
||||
};
|
||||
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||
contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
|
||||
}
|
||||
|
||||
foreach (var header in headers)
|
||||
IEnumerable<string>? contentEncodingHeader = null;
|
||||
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
// If Location header contains absolute redirect URL, and base URL is one that we proxy to,
|
||||
// we need to replace it to original one.
|
||||
if (string.Equals(header.Key, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase)
|
||||
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out Uri absoluteLocationUri)
|
||||
&& string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
|
||||
responseMessage.AddHeader(header.Key, replacedLocationUri.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage.AddHeader(header.Key, header.Value.ToArray());
|
||||
}
|
||||
contentEncodingHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)).Value;
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
var bodyParserSettings = new BodyParserSettings
|
||||
{
|
||||
Stream = stream,
|
||||
ContentType = contentTypeHeader?.FirstOrDefault(),
|
||||
DeserializeJson = deserializeJson,
|
||||
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
|
||||
DecompressGZipAndDeflate = decompressGzipAndDeflate
|
||||
};
|
||||
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||
}
|
||||
|
||||
foreach (var header in headers)
|
||||
{
|
||||
// If Location header contains absolute redirect URL, and base URL is one that we proxy to,
|
||||
// we need to replace it to original one.
|
||||
if (string.Equals(header.Key, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase)
|
||||
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out Uri absoluteLocationUri)
|
||||
&& string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
|
||||
responseMessage.AddHeader(header.Key, replacedLocationUri.ToString());
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage.AddHeader(header.Key, header.Value.ToArray());
|
||||
}
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
}
|
||||
@@ -1,25 +1,23 @@
|
||||
using System.Net.Http;
|
||||
using System.Net.Http;
|
||||
using System.Net.Http.Headers;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Http
|
||||
{
|
||||
internal static class StringContentHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a StringContent object.
|
||||
/// </summary>
|
||||
/// <param name="content">The string content (cannot be null)</param>
|
||||
/// <param name="contentType">The ContentType (can be null)</param>
|
||||
/// <returns>StringContent</returns>
|
||||
internal static StringContent Create([NotNull] string content, [CanBeNull] MediaTypeHeaderValue contentType)
|
||||
{
|
||||
Guard.NotNull(content, nameof(content));
|
||||
namespace WireMock.Http;
|
||||
|
||||
var stringContent = new StringContent(content);
|
||||
stringContent.Headers.ContentType = contentType;
|
||||
return stringContent;
|
||||
}
|
||||
internal static class StringContentHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Creates a StringContent object.
|
||||
/// </summary>
|
||||
/// <param name="content">The string content (cannot be null)</param>
|
||||
/// <param name="contentType">The ContentType (can be null)</param>
|
||||
/// <returns>StringContent</returns>
|
||||
internal static StringContent Create(string content, MediaTypeHeaderValue? contentType)
|
||||
{
|
||||
Guard.NotNull(content);
|
||||
|
||||
var stringContent = new StringContent(content);
|
||||
stringContent.Headers.ContentType = contentType;
|
||||
return stringContent;
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Models;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
@@ -11,75 +11,73 @@ using WireMock.Transformers.Handlebars;
|
||||
using WireMock.Transformers.Scriban;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Http
|
||||
namespace WireMock.Http;
|
||||
|
||||
internal class WebhookSender
|
||||
{
|
||||
internal class WebhookSender
|
||||
private const string ClientIp = "::1";
|
||||
|
||||
private readonly WireMockServerSettings _settings;
|
||||
|
||||
public WebhookSender(WireMockServerSettings settings)
|
||||
{
|
||||
private const string ClientIp = "::1";
|
||||
_settings = Guard.NotNull(settings);
|
||||
}
|
||||
|
||||
private readonly WireMockServerSettings _settings;
|
||||
public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
|
||||
{
|
||||
Guard.NotNull(client);
|
||||
Guard.NotNull(request);
|
||||
Guard.NotNull(originalRequestMessage);
|
||||
Guard.NotNull(originalResponseMessage);
|
||||
|
||||
public WebhookSender(WireMockServerSettings settings)
|
||||
IBodyData? bodyData;
|
||||
IDictionary<string, WireMockList<string>>? headers;
|
||||
if (request.UseTransformer == true)
|
||||
{
|
||||
_settings = settings ?? throw new ArgumentNullException(nameof(settings));
|
||||
}
|
||||
|
||||
public Task<HttpResponseMessage> SendAsync(HttpClient client, IWebhookRequest request, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage)
|
||||
{
|
||||
Guard.NotNull(client);
|
||||
Guard.NotNull(request);
|
||||
Guard.NotNull(originalRequestMessage);
|
||||
Guard.NotNull(originalResponseMessage);
|
||||
|
||||
IBodyData? bodyData;
|
||||
IDictionary<string, WireMockList<string>>? headers;
|
||||
if (request.UseTransformer == true)
|
||||
ITransformer responseMessageTransformer;
|
||||
switch (request.TransformerType)
|
||||
{
|
||||
ITransformer responseMessageTransformer;
|
||||
switch (request.TransformerType)
|
||||
{
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
|
||||
responseMessageTransformer = new Transformer(factoryHandlebars);
|
||||
break;
|
||||
case TransformerType.Handlebars:
|
||||
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
|
||||
responseMessageTransformer = new Transformer(factoryHandlebars);
|
||||
break;
|
||||
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, request.TransformerType);
|
||||
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
||||
break;
|
||||
case TransformerType.Scriban:
|
||||
case TransformerType.ScribanDotLiquid:
|
||||
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, request.TransformerType);
|
||||
responseMessageTransformer = new Transformer(factoryDotLiquid);
|
||||
break;
|
||||
|
||||
default:
|
||||
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
bodyData = request.BodyData;
|
||||
headers = request.Headers;
|
||||
default:
|
||||
throw new NotImplementedException($"TransformerType '{request.TransformerType}' is not supported.");
|
||||
}
|
||||
|
||||
// Create RequestMessage
|
||||
var requestMessage = new RequestMessage(
|
||||
new UrlDetails(request.Url),
|
||||
request.Method,
|
||||
ClientIp,
|
||||
bodyData,
|
||||
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
|
||||
)
|
||||
{
|
||||
DateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
// Create HttpRequestMessage
|
||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, request.Url);
|
||||
|
||||
// Call the URL
|
||||
return client.SendAsync(httpRequestMessage);
|
||||
(bodyData, headers) = responseMessageTransformer.Transform(originalRequestMessage, originalResponseMessage, request.BodyData, request.Headers, request.TransformerReplaceNodeOptions);
|
||||
}
|
||||
else
|
||||
{
|
||||
bodyData = request.BodyData;
|
||||
headers = request.Headers;
|
||||
}
|
||||
|
||||
// Create RequestMessage
|
||||
var requestMessage = new RequestMessage(
|
||||
new UrlDetails(request.Url),
|
||||
request.Method,
|
||||
ClientIp,
|
||||
bodyData,
|
||||
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
|
||||
)
|
||||
{
|
||||
DateTime = DateTime.UtcNow
|
||||
};
|
||||
|
||||
// Create HttpRequestMessage
|
||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, request.Url);
|
||||
|
||||
// Call the URL
|
||||
return client.SendAsync(httpRequestMessage);
|
||||
}
|
||||
}
|
||||
@@ -2,90 +2,42 @@ using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
namespace WireMock.HttpsCertificate;
|
||||
|
||||
internal static class CertificateLoader
|
||||
{
|
||||
internal static class CertificateLoader
|
||||
private const string ExtensionPem = ".PEM";
|
||||
|
||||
/// <summary>
|
||||
/// Used by the WireMock.Net server
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(
|
||||
string? storeName,
|
||||
string? storeLocation,
|
||||
string? thumbprintOrSubjectName,
|
||||
string? filePath,
|
||||
string? passwordOrKey,
|
||||
string host)
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the WireMock.Net server
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(
|
||||
string storeName,
|
||||
string storeLocation,
|
||||
string thumbprintOrSubjectName,
|
||||
string filePath,
|
||||
string password,
|
||||
string host)
|
||||
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
|
||||
{
|
||||
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
|
||||
{
|
||||
var thumbprintOrSubjectNameOrHost = thumbprintOrSubjectName ?? host;
|
||||
var thumbprintOrSubjectNameOrHost = thumbprintOrSubjectName ?? host;
|
||||
|
||||
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), storeName), (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation));
|
||||
try
|
||||
{
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException($"No Certificate found with in store '{storeName}', location '{storeLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(password))
|
||||
{
|
||||
return new X509Certificate2(filePath, password);
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
return new X509Certificate2(filePath);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath are mandatory. Note that X509CertificatePassword is optional.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for Proxy
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), storeName), (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation));
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
throw new FileNotFoundException($"No Certificate found with in store '{storeName}', location '{storeLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,5 +53,76 @@ namespace WireMock.HttpsCertificate
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath))
|
||||
{
|
||||
if (filePath!.EndsWith(ExtensionPem, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
// PEM logic based on: https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
|
||||
#if NET5_0_OR_GREATER
|
||||
if (!string.IsNullOrEmpty(passwordOrKey))
|
||||
{
|
||||
var certPem = File.ReadAllText(filePath);
|
||||
var cert = X509Certificate2.CreateFromPem(certPem, passwordOrKey);
|
||||
const string defaultPasswordPem = "WireMock.Net";
|
||||
return new X509Certificate2(cert.Export(X509ContentType.Pfx, defaultPasswordPem), defaultPasswordPem);
|
||||
}
|
||||
return X509Certificate2.CreateFromPemFile(filePath);
|
||||
|
||||
#elif NETCOREAPP3_1
|
||||
var cert = new X509Certificate2(filePath);
|
||||
if (!string.IsNullOrEmpty(passwordOrKey))
|
||||
{
|
||||
var key = System.Security.Cryptography.ECDsa.Create()!;
|
||||
key.ImportECPrivateKey(System.Text.Encoding.UTF8.GetBytes(passwordOrKey), out _);
|
||||
return cert.CopyWithPrivateKey(key);
|
||||
}
|
||||
return cert;
|
||||
#else
|
||||
throw new InvalidOperationException("Loading a PEM Certificate is only supported for .NET Core App 3.1, .NET 5.0 and higher.");
|
||||
#endif
|
||||
}
|
||||
|
||||
return !string.IsNullOrEmpty(passwordOrKey) ? new X509Certificate2(filePath, passwordOrKey) : new X509Certificate2(filePath);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath are mandatory. Note that X509CertificatePassword is optional.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for Proxy
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,16 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
namespace WireMock.HttpsCertificate;
|
||||
|
||||
/// <summary>
|
||||
/// Only used for NetStandard 1.3
|
||||
/// </summary>
|
||||
internal static class PublicCertificateHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Only used for NetStandard 1.3
|
||||
/// </summary>
|
||||
internal static class PublicCertificateHelper
|
||||
{
|
||||
// 1] Generate using https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net
|
||||
// 2] Converted to Base64
|
||||
private const string Data = @"MIIQMgIBAzCCD+4GCSqGSIb3DQEHAaCCD98Egg/bMIIP1zCCCogGCSqGSIb3DQEHAaCCCnkEggp1
|
||||
// 1] Generate using https://www.pluralsight.com/blog/software-development/selfcert-create-a-self-signed-certificate-interactively-gui-or-programmatically-in-net
|
||||
// 2] Converted to Base64
|
||||
private const string Data = @"MIIQMgIBAzCCD+4GCSqGSIb3DQEHAaCCD98Egg/bMIIP1zCCCogGCSqGSIb3DQEHAaCCCnkEggp1
|
||||
MIIKcTCCCm0GCyqGSIb3DQEMCgECoIIJfjCCCXowHAYKKoZIhvcNAQwBAzAOBAi1j9x1jTfUewIC
|
||||
B9AEgglYa48lP16+isiGEVT7zwN3XwaPwPOHZcQ7tRA/DA8LZnZbwU7XhtPObF5bZcHn4engX2An
|
||||
ISFpe2S5XJ7BfHmsGOO7Bxj6C2IcZIPTefvAd9vWE0WUAGN11SLhJ3fB/ZRt3Nys7JCJzywQCkYK
|
||||
@@ -85,10 +85,9 @@ TLNGa+UmMnPsnBjlAJ6l9VPsa4uJM2DIQKtZXWq4DkhSAYKF6joIP7nKMDswHzAHBgUrDgMCGgQU
|
||||
wTM1Z+CJZG9xAcf1zAVGl4ggYyYEFGBFyJ8VBwijS2zy1qwN1WYGtcWoAgIH0A==
|
||||
";
|
||||
|
||||
public static X509Certificate2 GetX509Certificate2()
|
||||
{
|
||||
byte[] data = Convert.FromBase64String(Data);
|
||||
return new X509Certificate2(data);
|
||||
}
|
||||
public static X509Certificate2 GetX509Certificate2()
|
||||
{
|
||||
byte[] data = Convert.FromBase64String(Data);
|
||||
return new X509Certificate2(data);
|
||||
}
|
||||
}
|
||||
@@ -20,22 +20,22 @@ public interface IMapping
|
||||
/// <summary>
|
||||
/// Gets the TimeSettings (Start, End and TTL).
|
||||
/// </summary>
|
||||
ITimeSettings TimeSettings { get; }
|
||||
ITimeSettings? TimeSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the unique title.
|
||||
/// </summary>
|
||||
string Title { get; }
|
||||
string? Title { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the description.
|
||||
/// </summary>
|
||||
string Description { get; }
|
||||
string? Description { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The full filename path for this mapping (only defined for static mappings).
|
||||
/// </summary>
|
||||
string Path { get; set; }
|
||||
string? Path { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the priority. (A low value means higher priority.)
|
||||
@@ -117,7 +117,7 @@ public interface IMapping
|
||||
/// </summary>
|
||||
/// <param name="requestMessage">The request message.</param>
|
||||
/// <returns>The <see cref="ResponseMessage"/> including a new (optional) <see cref="IMapping"/>.</returns>
|
||||
Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage);
|
||||
Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage);
|
||||
|
||||
/// <summary>
|
||||
/// Gets the RequestMatchResult based on the RequestMessage.
|
||||
|
||||
@@ -1,38 +1,37 @@
|
||||
using System;
|
||||
using System;
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Logging
|
||||
namespace WireMock.Logging;
|
||||
|
||||
/// <summary>
|
||||
/// LogEntry
|
||||
/// </summary>
|
||||
public class LogEntry : ILogEntry
|
||||
{
|
||||
/// <summary>
|
||||
/// LogEntry
|
||||
/// </summary>
|
||||
public class LogEntry : ILogEntry
|
||||
{
|
||||
/// <inheritdoc cref="ILogEntry.Guid" />
|
||||
public Guid Guid { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.Guid" />
|
||||
public Guid Guid { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.RequestMessage" />
|
||||
public IRequestMessage RequestMessage { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.RequestMessage" />
|
||||
public IRequestMessage RequestMessage { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
|
||||
public IResponseMessage ResponseMessage { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
|
||||
public IResponseMessage ResponseMessage { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
|
||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
|
||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.MappingGuid" />
|
||||
public Guid? MappingGuid { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.MappingGuid" />
|
||||
public Guid? MappingGuid { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.MappingTitle" />
|
||||
public string MappingTitle { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.MappingTitle" />
|
||||
public string? MappingTitle { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.PartialMappingGuid" />
|
||||
public Guid? PartialMappingGuid { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.PartialMappingGuid" />
|
||||
public Guid? PartialMappingGuid { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.PartialMappingTitle" />
|
||||
public string PartialMappingTitle { get; set; }
|
||||
/// <inheritdoc cref="ILogEntry.PartialMappingTitle" />
|
||||
public string? PartialMappingTitle { get; set; }
|
||||
|
||||
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
|
||||
public IRequestMatchResult PartialMatchResult { get; set; }
|
||||
}
|
||||
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
|
||||
public IRequestMatchResult PartialMatchResult { get; set; }
|
||||
}
|
||||
@@ -1,149 +1,147 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock
|
||||
namespace WireMock;
|
||||
|
||||
/// <summary>
|
||||
/// The Mapping.
|
||||
/// </summary>
|
||||
public class Mapping : IMapping
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Guid Guid { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Title { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Description { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Path { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? Scenario { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? ExecutionConditionState { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string? NextState { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? StateTimes { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestMatcher RequestMatcher { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseProvider Provider { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public WireMockServerSettings Settings { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsAdminInterface => Provider is DynamicResponseProvider or DynamicAsyncResponseProvider or ProxyAsyncResponseProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsProxy => Provider is ProxyAsyncResponseProvider;
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool LogMapping => Provider is not (DynamicResponseProvider or DynamicAsyncResponseProvider);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IWebhook[]? Webhooks { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ITimeSettings? TimeSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The Mapping.
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
public class Mapping : IMapping
|
||||
/// <param name="guid">The unique identifier.</param>
|
||||
/// <param name="title">The unique title (can be null).</param>
|
||||
/// <param name="description">The description (can be null).</param>
|
||||
/// <param name="path">The full file path from this mapping title (can be null).</param>
|
||||
/// <param name="settings">The WireMockServerSettings.</param>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
/// <param name="provider">The provider.</param>
|
||||
/// <param name="priority">The priority for this mapping.</param>
|
||||
/// <param name="scenario">The scenario. [Optional]</param>
|
||||
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
||||
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
||||
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
|
||||
/// <param name="webhooks">The Webhooks. [Optional]</param>
|
||||
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
|
||||
public Mapping(
|
||||
Guid guid,
|
||||
string? title,
|
||||
string? description,
|
||||
string? path,
|
||||
WireMockServerSettings settings,
|
||||
IRequestMatcher requestMatcher,
|
||||
IResponseProvider provider,
|
||||
int priority,
|
||||
string? scenario,
|
||||
string? executionConditionState,
|
||||
string? nextState,
|
||||
int? stateTimes,
|
||||
IWebhook[]? webhooks,
|
||||
ITimeSettings? timeSettings)
|
||||
{
|
||||
/// <inheritdoc />
|
||||
public Guid Guid { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Title { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Description { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Path { get; set; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int Priority { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Scenario { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string ExecutionConditionState { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string NextState { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public int? StateTimes { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IRequestMatcher RequestMatcher { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseProvider Provider { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public WireMockServerSettings Settings { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
|
||||
|
||||
/// <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);
|
||||
|
||||
/// <inheritdoc />
|
||||
public IWebhook[] Webhooks { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public ITimeSettings TimeSettings { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||
/// </summary>
|
||||
/// <param name="guid">The unique identifier.</param>
|
||||
/// <param name="title">The unique title (can be null).</param>
|
||||
/// <param name="description">The description (can be null).</param>
|
||||
/// <param name="path">The full file path from this mapping title (can be null).</param>
|
||||
/// <param name="settings">The WireMockServerSettings.</param>
|
||||
/// <param name="requestMatcher">The request matcher.</param>
|
||||
/// <param name="provider">The provider.</param>
|
||||
/// <param name="priority">The priority for this mapping.</param>
|
||||
/// <param name="scenario">The scenario. [Optional]</param>
|
||||
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
||||
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
||||
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
|
||||
/// <param name="webhooks">The Webhooks. [Optional]</param>
|
||||
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
|
||||
public Mapping(
|
||||
Guid guid,
|
||||
string? title,
|
||||
string? description,
|
||||
string? path,
|
||||
WireMockServerSettings settings,
|
||||
IRequestMatcher requestMatcher,
|
||||
IResponseProvider provider,
|
||||
int priority,
|
||||
string? scenario,
|
||||
string? executionConditionState,
|
||||
string? nextState,
|
||||
int? stateTimes,
|
||||
IWebhook[]? webhooks,
|
||||
ITimeSettings? timeSettings)
|
||||
{
|
||||
Guid = guid;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Path = path;
|
||||
Settings = settings;
|
||||
RequestMatcher = requestMatcher;
|
||||
Provider = provider;
|
||||
Priority = priority;
|
||||
Scenario = scenario;
|
||||
ExecutionConditionState = executionConditionState;
|
||||
NextState = nextState;
|
||||
StateTimes = stateTimes;
|
||||
Webhooks = webhooks;
|
||||
TimeSettings = timeSettings;
|
||||
}
|
||||
Guid = guid;
|
||||
Title = title;
|
||||
Description = description;
|
||||
Path = path;
|
||||
Settings = settings;
|
||||
RequestMatcher = requestMatcher;
|
||||
Provider = provider;
|
||||
Priority = priority;
|
||||
Scenario = scenario;
|
||||
ExecutionConditionState = executionConditionState;
|
||||
NextState = nextState;
|
||||
StateTimes = stateTimes;
|
||||
Webhooks = webhooks;
|
||||
TimeSettings = timeSettings;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
public Task<(IResponseMessage Message, IMapping Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
|
||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
|
||||
{
|
||||
return Provider.ProvideResponseAsync(requestMessage, Settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.GetRequestMatchResult" />
|
||||
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string nextState)
|
||||
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
|
||||
{
|
||||
var result = new RequestMatchResult();
|
||||
|
||||
RequestMatcher.GetMatchingScore(requestMessage, result);
|
||||
RequestMatcher.GetMatchingScore(requestMessage, result);
|
||||
|
||||
// Only check state if Scenario is defined
|
||||
if (Scenario != null)
|
||||
{
|
||||
var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
|
||||
matcher.GetMatchingScore(requestMessage, result);
|
||||
//// If ExecutionConditionState is null, this means that request is the start from a scenario. So just return.
|
||||
//if (ExecutionConditionState != null)
|
||||
//{
|
||||
// // ExecutionConditionState is not null, so get score for matching with the nextState.
|
||||
// var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
|
||||
// matcher.GetMatchingScore(requestMessage, result);
|
||||
//}
|
||||
}
|
||||
|
||||
return result;
|
||||
// Only check state if Scenario is defined
|
||||
if (Scenario != null)
|
||||
{
|
||||
var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
|
||||
matcher.GetMatchingScore(requestMessage, result);
|
||||
//// If ExecutionConditionState is null, this means that request is the start from a scenario. So just return.
|
||||
//if (ExecutionConditionState != null)
|
||||
//{
|
||||
// // ExecutionConditionState is not null, so get score for matching with the nextState.
|
||||
// var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
|
||||
// matcher.GetMatchingScore(requestMessage, result);
|
||||
//}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -9,15 +10,22 @@ namespace WireMock.Matchers;
|
||||
/// </summary>
|
||||
public abstract class AbstractJsonPartialMatcher : JsonMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Support Regex
|
||||
/// </summary>
|
||||
public bool Regex { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="AbstractJsonPartialMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The string value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <param name="regex">Support Regex.</param>
|
||||
protected AbstractJsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
Regex = regex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -26,9 +34,11 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher
|
||||
/// <param name="value">The object value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <param name="regex">Support Regex.</param>
|
||||
protected AbstractJsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
Regex = regex;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -38,9 +48,11 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher
|
||||
/// <param name="value">The value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false)
|
||||
/// <param name="regex">Support Regex.</param>
|
||||
protected AbstractJsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException)
|
||||
{
|
||||
Regex = regex;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -51,6 +63,17 @@ public abstract class AbstractJsonPartialMatcher : JsonMatcher
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Regex && value.Type == JTokenType.String && input != null)
|
||||
{
|
||||
var valueAsString = value.ToString();
|
||||
|
||||
var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString());
|
||||
if (valid)
|
||||
{
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
if (input == null || value.Type != input.Type)
|
||||
{
|
||||
return false;
|
||||
|
||||
@@ -18,7 +18,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher([NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
|
||||
public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -28,7 +28,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, [NotNull] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -57,7 +57,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// <inheritdoc cref="RegexMatcher.IsMatch"/>
|
||||
public override double IsMatch(string? input)
|
||||
{
|
||||
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out MediaTypeHeaderValue contentType))
|
||||
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
@@ -1,11 +1,10 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// CSharpCode / CS-Script Matcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IObjectMatcher"/>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
public interface ICSharpCodeMatcher : IObjectMatcher, IStringMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// CSharpCode / CS-Script Matcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IObjectMatcher"/>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
public interface ICSharpCodeMatcher : IObjectMatcher, IStringMatcher
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -1,14 +1,13 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// IIgnoreCaseMatcher
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IMatcher"/>
|
||||
public interface IIgnoreCaseMatcher : IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// IIgnoreCaseMatcher
|
||||
/// Ignore the case from the pattern.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IMatcher"/>
|
||||
public interface IIgnoreCaseMatcher : IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Ignore the case from the pattern.
|
||||
/// </summary>
|
||||
bool IgnoreCase { get; }
|
||||
}
|
||||
bool IgnoreCase { get; }
|
||||
}
|
||||
@@ -1,23 +1,22 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// IMatcher
|
||||
/// </summary>
|
||||
public interface IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// IMatcher
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
public interface IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the name.
|
||||
/// </summary>
|
||||
string Name { get; }
|
||||
string Name { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the match behaviour.
|
||||
/// </summary>
|
||||
MatchBehaviour MatchBehaviour { get; }
|
||||
/// <summary>
|
||||
/// Gets the match behaviour.
|
||||
/// </summary>
|
||||
MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Should this matcher throw an exception?
|
||||
/// </summary>
|
||||
bool ThrowException { get; }
|
||||
}
|
||||
/// <summary>
|
||||
/// Should this matcher throw an exception?
|
||||
/// </summary>
|
||||
bool ThrowException { get; }
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// IObjectMatcher
|
||||
/// </summary>
|
||||
public interface IObjectMatcher : IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// IObjectMatcher
|
||||
/// Determines whether the specified input is match.
|
||||
/// </summary>
|
||||
public interface IObjectMatcher : IMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Determines whether the specified input is match.
|
||||
/// </summary>
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
|
||||
double IsMatch(object? input);
|
||||
}
|
||||
/// <param name="input">The input.</param>
|
||||
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
|
||||
double IsMatch(object? input);
|
||||
}
|
||||
@@ -1,15 +1,14 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// IValueMatcher
|
||||
/// </summary>
|
||||
/// <seealso cref="IObjectMatcher" />
|
||||
public interface IValueMatcher : IObjectMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// IValueMatcher
|
||||
/// Gets the value (can be a string or an object).
|
||||
/// </summary>
|
||||
/// <seealso cref="IObjectMatcher" />
|
||||
public interface IValueMatcher : IObjectMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets the value (can be a string or an object).
|
||||
/// </summary>
|
||||
/// <returns>Value</returns>
|
||||
object Value { get; }
|
||||
}
|
||||
/// <returns>Value</returns>
|
||||
object Value { get; }
|
||||
}
|
||||
@@ -6,115 +6,114 @@ using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// http://jmespath.org/
|
||||
/// </summary>
|
||||
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
{
|
||||
private readonly AnyOf<string, StringPattern>[] _patterns;
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.ThrowException"/>
|
||||
public bool ThrowException { get; }
|
||||
|
||||
/// <summary>
|
||||
/// http://jmespath.org/
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns.ToAnyOfPatterns())
|
||||
{
|
||||
private readonly AnyOf<string, StringPattern>[] _patterns;
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.ThrowException"/>
|
||||
public bool ThrowException { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns.ToAnyOfPatterns())
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf<string, StringPattern>[] patterns) :
|
||||
this(MatchBehaviour.AcceptOnMatch, throwException, matchOperator, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(
|
||||
MatchBehaviour matchBehaviour,
|
||||
bool throwException = false,
|
||||
MatchOperator matchOperator = MatchOperator.Or,
|
||||
params AnyOf<string, StringPattern>[] patterns)
|
||||
{
|
||||
_patterns = Guard.NotNull(patterns);
|
||||
MatchBehaviour = matchBehaviour;
|
||||
ThrowException = throwException;
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
if (input != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var results = _patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))).ToArray();
|
||||
match = MatchScores.ToScore(results, MatchOperator);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
if (ThrowException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
public double IsMatch(object? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
// When input is null or byte[], return Mismatch.
|
||||
if (input != null && !(input is byte[]))
|
||||
{
|
||||
string inputAsString = JsonConvert.SerializeObject(input);
|
||||
return IsMatch(inputAsString);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public string Name => "JmesPathMatcher";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(bool throwException = false, MatchOperator matchOperator = MatchOperator.Or, params AnyOf<string, StringPattern>[] patterns) :
|
||||
this(MatchBehaviour.AcceptOnMatch, throwException, matchOperator, patterns)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
public JmesPathMatcher(
|
||||
MatchBehaviour matchBehaviour,
|
||||
bool throwException = false,
|
||||
MatchOperator matchOperator = MatchOperator.Or,
|
||||
params AnyOf<string, StringPattern>[] patterns)
|
||||
{
|
||||
_patterns = Guard.NotNull(patterns);
|
||||
MatchBehaviour = matchBehaviour;
|
||||
ThrowException = throwException;
|
||||
MatchOperator = matchOperator;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
if (input != null)
|
||||
{
|
||||
try
|
||||
{
|
||||
var results = _patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))).ToArray();
|
||||
match = MatchScores.ToScore(results, MatchOperator);
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
if (ThrowException)
|
||||
{
|
||||
throw;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
public double IsMatch(object? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
// When input is null or byte[], return Mismatch.
|
||||
if (input != null && !(input is byte[]))
|
||||
{
|
||||
string inputAsString = JsonConvert.SerializeObject(input);
|
||||
return IsMatch(inputAsString);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
return _patterns;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public string Name => "JmesPathMatcher";
|
||||
}
|
||||
@@ -13,12 +13,12 @@ namespace WireMock.Matchers;
|
||||
/// </summary>
|
||||
public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher
|
||||
{
|
||||
/// <inheritdoc cref="IValueMatcher.Value"/>
|
||||
public object Value { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public virtual string Name => "JsonMatcher";
|
||||
|
||||
/// <inheritdoc cref="IValueMatcher.Value"/>
|
||||
public object Value { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
@@ -68,9 +68,7 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher
|
||||
|
||||
Value = value;
|
||||
_valueAsJToken = ConvertValueToJToken(value);
|
||||
_jTokenConverter = ignoreCase
|
||||
? (Func<JToken, JToken>)Rename
|
||||
: jToken => jToken;
|
||||
_jTokenConverter = ignoreCase ? Rename : jToken => jToken;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
@@ -121,7 +119,7 @@ public class JsonMatcher : IValueMatcher, IIgnoreCaseMatcher
|
||||
return tokenValue;
|
||||
|
||||
case string stringValue:
|
||||
return JsonUtils.Parse(stringValue)!;
|
||||
return JsonUtils.Parse(stringValue);
|
||||
|
||||
case IEnumerable enumerableValue:
|
||||
return JArray.FromObject(enumerableValue);
|
||||
|
||||
@@ -9,20 +9,20 @@ public class JsonPartialMatcher : AbstractJsonPartialMatcher
|
||||
public override string Name => nameof(JsonPartialMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
public JsonPartialMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
public JsonPartialMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException)
|
||||
public JsonPartialMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
@@ -11,20 +9,20 @@ public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher
|
||||
public override string Name => nameof(JsonPartialWildcardMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
public JsonPartialWildcardMatcher(string value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
public JsonPartialWildcardMatcher(object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException)
|
||||
public JsonPartialWildcardMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool throwException = false, bool regex = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException, regex)
|
||||
{
|
||||
}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using System.Linq.Dynamic.Core;
|
||||
using AnyOfTypes;
|
||||
@@ -68,7 +69,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||
public double IsMatch(string input)
|
||||
public double IsMatch(string? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
@@ -94,7 +95,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
public double IsMatch(object input)
|
||||
public double IsMatch(object? input)
|
||||
{
|
||||
double match = MatchScores.Mismatch;
|
||||
|
||||
@@ -105,9 +106,12 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
value = valueAsJObject;
|
||||
break;
|
||||
|
||||
default:
|
||||
value = JObject.FromObject(input);
|
||||
case { } valueAsObject:
|
||||
value = JObject.FromObject(valueAsObject);
|
||||
break;
|
||||
|
||||
default:
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
// Convert a single object to a Queryable JObject-list with 1 entry.
|
||||
|
||||
@@ -1,18 +1,17 @@
|
||||
namespace WireMock.Matchers
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
/// MatchBehaviour
|
||||
/// </summary>
|
||||
public enum MatchBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// MatchBehaviour
|
||||
/// Accept on match (default)
|
||||
/// </summary>
|
||||
public enum MatchBehaviour
|
||||
{
|
||||
/// <summary>
|
||||
/// Accept on match (default)
|
||||
/// </summary>
|
||||
AcceptOnMatch,
|
||||
AcceptOnMatch,
|
||||
|
||||
/// <summary>
|
||||
/// Reject on match
|
||||
/// </summary>
|
||||
RejectOnMatch
|
||||
}
|
||||
/// <summary>
|
||||
/// Reject on match
|
||||
/// </summary>
|
||||
RejectOnMatch
|
||||
}
|
||||
@@ -1,27 +1,26 @@
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
internal static class MatchBehaviourHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the specified match behaviour and match value to a new match value.
|
||||
///
|
||||
/// if AcceptOnMatch --> return match (default)
|
||||
/// if RejectOnMatch and match = 0.0 --> return 1.0
|
||||
/// if RejectOnMatch and match = 0.? --> return 0.0
|
||||
/// if RejectOnMatch and match = 1.0 --> return 0.0
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="match">The match.</param>
|
||||
/// <returns>match value</returns>
|
||||
internal static double Convert(MatchBehaviour matchBehaviour, double match)
|
||||
{
|
||||
if (matchBehaviour == MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
return match;
|
||||
}
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
return match <= MatchScores.Tolerance ? MatchScores.Perfect : MatchScores.Mismatch;
|
||||
internal static class MatchBehaviourHelper
|
||||
{
|
||||
/// <summary>
|
||||
/// Converts the specified match behaviour and match value to a new match value.
|
||||
///
|
||||
/// if AcceptOnMatch --> return match (default)
|
||||
/// if RejectOnMatch and match = 0.0 --> return 1.0
|
||||
/// if RejectOnMatch and match = 0.? --> return 0.0
|
||||
/// if RejectOnMatch and match = 1.0 --> return 0.0
|
||||
/// </summary>
|
||||
///
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="match">The match.</param>
|
||||
/// <returns>match value</returns>
|
||||
internal static double Convert(MatchBehaviour matchBehaviour, double match)
|
||||
{
|
||||
if (matchBehaviour == MatchBehaviour.AcceptOnMatch)
|
||||
{
|
||||
return match;
|
||||
}
|
||||
|
||||
return match <= MatchScores.Tolerance ? MatchScores.Perfect : MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
@@ -1,18 +1,17 @@
|
||||
namespace WireMock.Matchers.Request
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// CompositeMatcherType
|
||||
/// </summary>
|
||||
public enum CompositeMatcherType
|
||||
{
|
||||
/// <summary>
|
||||
/// CompositeMatcherType
|
||||
/// And
|
||||
/// </summary>
|
||||
public enum CompositeMatcherType
|
||||
{
|
||||
/// <summary>
|
||||
/// And
|
||||
/// </summary>
|
||||
And = 0,
|
||||
And = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Or
|
||||
/// </summary>
|
||||
Or = 1
|
||||
}
|
||||
/// <summary>
|
||||
/// Or
|
||||
/// </summary>
|
||||
Or = 1
|
||||
}
|
||||
@@ -1,57 +1,56 @@
|
||||
using System;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// RequestMatchResult
|
||||
/// </summary>
|
||||
public class RequestMatchResult : IRequestMatchResult
|
||||
{
|
||||
/// <inheritdoc cref="IRequestMatchResult.TotalScore" />
|
||||
public double TotalScore => MatchDetails.Sum(md => md.Score);
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.TotalNumber" />
|
||||
public int TotalNumber => MatchDetails.Count;
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.IsPerfectMatch" />
|
||||
public bool IsPerfectMatch => Math.Abs(TotalScore - TotalNumber) < MatchScores.Tolerance;
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.AverageTotalScore" />
|
||||
public double AverageTotalScore => TotalNumber == 0 ? 0.0 : TotalScore / TotalNumber;
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.MatchDetails" />
|
||||
public IList<MatchDetail> MatchDetails { get; } = new List<MatchDetail>();
|
||||
|
||||
/// <summary>
|
||||
/// RequestMatchResult
|
||||
/// Adds the score.
|
||||
/// </summary>
|
||||
public class RequestMatchResult : IRequestMatchResult
|
||||
/// <param name="matcherType">The matcher Type.</param>
|
||||
/// <param name="score">The score.</param>
|
||||
/// <returns>The score.</returns>
|
||||
public double AddScore(Type matcherType, double score)
|
||||
{
|
||||
/// <inheritdoc cref="IRequestMatchResult.TotalScore" />
|
||||
public double TotalScore => MatchDetails.Sum(md => md.Score);
|
||||
MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score });
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.TotalNumber" />
|
||||
public int TotalNumber => MatchDetails.Count;
|
||||
return score;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.IsPerfectMatch" />
|
||||
public bool IsPerfectMatch => Math.Abs(TotalScore - TotalNumber) < MatchScores.Tolerance;
|
||||
/// <summary>
|
||||
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="obj" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. Greater than zero This instance follows <paramref name="obj" /> in the sort order.
|
||||
/// </returns>
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
var compareObj = (RequestMatchResult)obj;
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.AverageTotalScore" />
|
||||
public double AverageTotalScore => TotalNumber == 0 ? 0.0 : TotalScore / TotalNumber;
|
||||
int averageTotalScoreResult = compareObj.AverageTotalScore.CompareTo(AverageTotalScore);
|
||||
|
||||
/// <inheritdoc cref="IRequestMatchResult.MatchDetails" />
|
||||
public IList<MatchDetail> MatchDetails { get; } = new List<MatchDetail>();
|
||||
|
||||
/// <summary>
|
||||
/// Adds the score.
|
||||
/// </summary>
|
||||
/// <param name="matcherType">The matcher Type.</param>
|
||||
/// <param name="score">The score.</param>
|
||||
/// <returns>The score.</returns>
|
||||
public double AddScore(Type matcherType, double score)
|
||||
{
|
||||
MatchDetails.Add(new MatchDetail { MatcherType = matcherType, Score = score });
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the current instance with another object of the same type and returns an integer that indicates whether the current instance precedes, follows, or occurs in the same position in the sort order as the other object.
|
||||
/// </summary>
|
||||
/// <param name="obj">An object to compare with this instance.</param>
|
||||
/// <returns>
|
||||
/// A value that indicates the relative order of the objects being compared. The return value has these meanings: Value Meaning Less than zero This instance precedes <paramref name="obj" /> in the sort order. Zero This instance occurs in the same position in the sort order as <paramref name="obj" />. Greater than zero This instance follows <paramref name="obj" /> in the sort order.
|
||||
/// </returns>
|
||||
public int CompareTo(object obj)
|
||||
{
|
||||
var compareObj = (RequestMatchResult)obj;
|
||||
|
||||
int averageTotalScoreResult = compareObj.AverageTotalScore.CompareTo(AverageTotalScore);
|
||||
|
||||
// In case the score is equal, prefer the one with the most matchers.
|
||||
return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult;
|
||||
}
|
||||
// In case the score is equal, prefer the one with the most matchers.
|
||||
return averageTotalScoreResult == 0 ? compareObj.TotalNumber.CompareTo(TotalNumber) : averageTotalScoreResult;
|
||||
}
|
||||
}
|
||||
@@ -3,50 +3,49 @@ using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// The composite request matcher.
|
||||
/// </summary>
|
||||
public abstract class RequestMessageCompositeMatcher : IRequestMatcher
|
||||
{
|
||||
private readonly CompositeMatcherType _type;
|
||||
|
||||
/// <summary>
|
||||
/// The composite request matcher.
|
||||
/// Gets the request matchers.
|
||||
/// </summary>
|
||||
public abstract class RequestMessageCompositeMatcher : IRequestMatcher
|
||||
/// <value>
|
||||
/// The request matchers.
|
||||
/// </value>
|
||||
private IEnumerable<IRequestMatcher> RequestMatchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCompositeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="requestMatchers">The request matchers.</param>
|
||||
/// <param name="type">The CompositeMatcherType type (Defaults to 'And')</param>
|
||||
protected RequestMessageCompositeMatcher([NotNull] IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
||||
{
|
||||
private readonly CompositeMatcherType _type;
|
||||
Guard.NotNull(requestMatchers, nameof(requestMatchers));
|
||||
|
||||
/// <summary>
|
||||
/// Gets the request matchers.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// The request matchers.
|
||||
/// </value>
|
||||
private IEnumerable<IRequestMatcher> RequestMatchers { get; }
|
||||
_type = type;
|
||||
RequestMatchers = requestMatchers;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCompositeMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="requestMatchers">The request matchers.</param>
|
||||
/// <param name="type">The CompositeMatcherType type (Defaults to 'And')</param>
|
||||
protected RequestMessageCompositeMatcher([NotNull] IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
if (!RequestMatchers.Any())
|
||||
{
|
||||
Guard.NotNull(requestMatchers, nameof(requestMatchers));
|
||||
|
||||
_type = type;
|
||||
RequestMatchers = requestMatchers;
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
if (_type == CompositeMatcherType.And)
|
||||
{
|
||||
if (!RequestMatchers.Any())
|
||||
{
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
if (_type == CompositeMatcherType.And)
|
||||
{
|
||||
return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
|
||||
}
|
||||
|
||||
return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
|
||||
return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
|
||||
}
|
||||
|
||||
return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
|
||||
}
|
||||
}
|
||||
@@ -4,126 +4,125 @@ using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
/// <summary>
|
||||
/// The request cookie matcher.
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IRequestMatcher"/>
|
||||
public class RequestMessageCookieMatcher : IRequestMatcher
|
||||
{
|
||||
private readonly MatchBehaviour _matchBehaviour;
|
||||
private readonly bool _ignoreCase;
|
||||
|
||||
/// <summary>
|
||||
/// The request cookie matcher.
|
||||
/// The functions
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IRequestMatcher"/>
|
||||
public class RequestMessageCookieMatcher : IRequestMatcher
|
||||
public Func<IDictionary<string, string>, bool>[] Funcs { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The name
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
|
||||
/// <value>
|
||||
/// The matchers.
|
||||
/// </value>
|
||||
public IStringMatcher[] Matchers { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string pattern, bool ignoreCase)
|
||||
{
|
||||
private readonly MatchBehaviour _matchBehaviour;
|
||||
private readonly bool _ignoreCase;
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(pattern, nameof(pattern));
|
||||
|
||||
/// <summary>
|
||||
/// The functions
|
||||
/// </summary>
|
||||
public Func<IDictionary<string, string>, bool>[] Funcs { get; }
|
||||
_matchBehaviour = matchBehaviour;
|
||||
_ignoreCase = ignoreCase;
|
||||
Name = name;
|
||||
Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, pattern, ignoreCase) };
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The name
|
||||
/// </summary>
|
||||
public string Name { get; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params string[] patterns) :
|
||||
this(matchBehaviour, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray())
|
||||
{
|
||||
Guard.NotNull(patterns, nameof(patterns));
|
||||
}
|
||||
|
||||
/// <value>
|
||||
/// The matchers.
|
||||
/// </value>
|
||||
public IStringMatcher[] Matchers { get; }
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(matchers, nameof(matchers));
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, [NotNull] string pattern, bool ignoreCase)
|
||||
_matchBehaviour = matchBehaviour;
|
||||
Name = name;
|
||||
Matchers = matchers;
|
||||
_ignoreCase = ignoreCase;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="funcs">The funcs.</param>
|
||||
public RequestMessageCookieMatcher([NotNull] params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
{
|
||||
Guard.NotNull(funcs, nameof(funcs));
|
||||
|
||||
Funcs = funcs;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private double IsMatch(IRequestMessage requestMessage)
|
||||
{
|
||||
if (requestMessage.Cookies == null)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(pattern, nameof(pattern));
|
||||
|
||||
_matchBehaviour = matchBehaviour;
|
||||
_ignoreCase = ignoreCase;
|
||||
Name = name;
|
||||
Matchers = new IStringMatcher[] { new WildcardMatcher(matchBehaviour, pattern, ignoreCase) };
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params string[] patterns) :
|
||||
this(matchBehaviour, name, ignoreCase, patterns.Select(pattern => new WildcardMatcher(matchBehaviour, pattern, ignoreCase)).Cast<IStringMatcher>().ToArray())
|
||||
// Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value
|
||||
var cookies = !_ignoreCase ? requestMessage.Cookies : new Dictionary<string, string>(requestMessage.Cookies, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
Guard.NotNull(patterns, nameof(patterns));
|
||||
return MatchScores.ToScore(Funcs.Any(f => f(cookies)));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="matchers">The matchers.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
public RequestMessageCookieMatcher(MatchBehaviour matchBehaviour, [NotNull] string name, bool ignoreCase, [NotNull] params IStringMatcher[] matchers)
|
||||
if (Matchers == null)
|
||||
{
|
||||
Guard.NotNull(name, nameof(name));
|
||||
Guard.NotNull(matchers, nameof(matchers));
|
||||
|
||||
_matchBehaviour = matchBehaviour;
|
||||
Name = name;
|
||||
Matchers = matchers;
|
||||
_ignoreCase = ignoreCase;
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageCookieMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="funcs">The funcs.</param>
|
||||
public RequestMessageCookieMatcher([NotNull] params Func<IDictionary<string, string>, bool>[] funcs)
|
||||
if (!cookies.ContainsKey(Name))
|
||||
{
|
||||
Guard.NotNull(funcs, nameof(funcs));
|
||||
|
||||
Funcs = funcs;
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch(requestMessage);
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private double IsMatch(IRequestMessage requestMessage)
|
||||
{
|
||||
if (requestMessage.Cookies == null)
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
// Check if we want to use IgnoreCase to compare the Cookie-Name and Cookie-Value
|
||||
var cookies = !_ignoreCase ? requestMessage.Cookies : new Dictionary<string, string>(requestMessage.Cookies, StringComparer.OrdinalIgnoreCase);
|
||||
|
||||
if (Funcs != null)
|
||||
{
|
||||
return MatchScores.ToScore(Funcs.Any(f => f(cookies)));
|
||||
}
|
||||
|
||||
if (Matchers == null)
|
||||
{
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
if (!cookies.ContainsKey(Name))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
string value = cookies[Name];
|
||||
return Matchers.Max(m => m.IsMatch(value));
|
||||
}
|
||||
string value = cookies[Name];
|
||||
return Matchers.Max(m => m.IsMatch(value));
|
||||
}
|
||||
}
|
||||
@@ -23,7 +23,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
/// <summary>
|
||||
/// The name
|
||||
/// </summary>
|
||||
public string? Name { get; }
|
||||
public string Name { get; }
|
||||
|
||||
/// <value>
|
||||
/// The matchers.
|
||||
@@ -94,6 +94,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
public RequestMessageHeaderMatcher(params Func<IDictionary<string, string[]>, bool>[] funcs)
|
||||
{
|
||||
Funcs = Guard.NotNull(funcs);
|
||||
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -121,7 +122,7 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
|
||||
if (Matchers != null)
|
||||
{
|
||||
if (!headers.ContainsKey(Name!))
|
||||
if (!headers.ContainsKey(Name))
|
||||
{
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
}
|
||||
@@ -129,12 +130,12 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
|
||||
var results = new List<double>();
|
||||
foreach (var matcher in Matchers)
|
||||
{
|
||||
var resultsPerMatcher = headers[Name!].Select(v => matcher.IsMatch(v)).ToArray();
|
||||
var resultsPerMatcher = headers[Name].Select(v => matcher.IsMatch(v)).ToArray();
|
||||
|
||||
results.Add(MatchScores.ToScore(resultsPerMatcher, MatchOperator.And));
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.ToScore(results, MatchOperator));
|
||||
return MatchScores.ToScore(results, MatchOperator);
|
||||
}
|
||||
|
||||
return MatchBehaviourHelper.Convert(_matchBehaviour, MatchScores.Mismatch);
|
||||
|
||||
@@ -92,7 +92,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
||||
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
|
||||
}
|
||||
|
||||
WireMockList<string> valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key, IgnoreCase ?? false);
|
||||
var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key!, IgnoreCase ?? false);
|
||||
if (valuesPresentInRequestMessage == null)
|
||||
{
|
||||
// Key is not present at all, just return Mismatch
|
||||
@@ -102,7 +102,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
||||
if (Matchers != null && Matchers.Any())
|
||||
{
|
||||
// Return the score based on Matchers and valuesPresentInRequestMessage
|
||||
return CalculateScore(valuesPresentInRequestMessage);
|
||||
return CalculateScore(Matchers, valuesPresentInRequestMessage);
|
||||
}
|
||||
|
||||
if (Matchers == null || !Matchers.Any())
|
||||
@@ -114,14 +114,14 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
private double CalculateScore(WireMockList<string> valuesPresentInRequestMessage)
|
||||
private double CalculateScore(IReadOnlyList<IStringMatcher> matchers, WireMockList<string> valuesPresentInRequestMessage)
|
||||
{
|
||||
var total = new List<double>();
|
||||
|
||||
// If the total patterns in all matchers > values in message, use the matcher as base
|
||||
if (Matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count)
|
||||
if (matchers.Sum(m => m.GetPatterns().Length) > valuesPresentInRequestMessage.Count)
|
||||
{
|
||||
foreach (var matcher in Matchers)
|
||||
foreach (var matcher in matchers)
|
||||
{
|
||||
double score = 0d;
|
||||
foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
|
||||
@@ -136,7 +136,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
||||
{
|
||||
foreach (string valuePresentInRequestMessage in valuesPresentInRequestMessage)
|
||||
{
|
||||
double score = Matchers.Max(m => m.IsMatch(valuePresentInRequestMessage));
|
||||
double score = matchers.Max(m => m.IsMatch(valuePresentInRequestMessage));
|
||||
total.Add(score);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,46 +1,41 @@
|
||||
using JetBrains.Annotations;
|
||||
namespace WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Matchers.Request
|
||||
/// <summary>
|
||||
/// The scenario and state matcher.
|
||||
/// </summary>
|
||||
internal class RequestMessageScenarioAndStateMatcher : IRequestMatcher
|
||||
{
|
||||
/// <summary>
|
||||
/// The scenario and state matcher.
|
||||
/// Execution state condition for the current mapping.
|
||||
/// </summary>
|
||||
internal class RequestMessageScenarioAndStateMatcher : IRequestMatcher
|
||||
private readonly string? _executionConditionState;
|
||||
|
||||
/// <summary>
|
||||
/// The next state which will be signaled after the current mapping execution.
|
||||
/// In case the value is null state will not be changed.
|
||||
/// </summary>
|
||||
private readonly string? _nextState;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageScenarioAndStateMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="nextState">The next state.</param>
|
||||
/// <param name="executionConditionState">Execution state condition for the current mapping.</param>
|
||||
public RequestMessageScenarioAndStateMatcher(string? nextState, string? executionConditionState)
|
||||
{
|
||||
/// <summary>
|
||||
/// Execution state condition for the current mapping.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
private readonly string _executionConditionState;
|
||||
_nextState = nextState;
|
||||
_executionConditionState = executionConditionState;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// The next state which will be signaled after the current mapping execution.
|
||||
/// In case the value is null state will not be changed.
|
||||
/// </summary>
|
||||
[CanBeNull]
|
||||
private readonly string _nextState;
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch();
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="RequestMessageScenarioAndStateMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="nextState">The next state.</param>
|
||||
/// <param name="executionConditionState">Execution state condition for the current mapping.</param>
|
||||
public RequestMessageScenarioAndStateMatcher([CanBeNull] string nextState, [CanBeNull] string executionConditionState)
|
||||
{
|
||||
_nextState = nextState;
|
||||
_executionConditionState = executionConditionState;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
|
||||
{
|
||||
double score = IsMatch();
|
||||
return requestMatchResult.AddScore(GetType(), score);
|
||||
}
|
||||
|
||||
private double IsMatch()
|
||||
{
|
||||
return Equals(_executionConditionState, _nextState) ? MatchScores.Perfect : MatchScores.Mismatch;
|
||||
}
|
||||
private double IsMatch()
|
||||
{
|
||||
return Equals(_executionConditionState, _nextState) ? MatchScores.Perfect : MatchScores.Mismatch;
|
||||
}
|
||||
}
|
||||
@@ -3,45 +3,44 @@ using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal partial class AspNetCoreSelfHost
|
||||
{
|
||||
internal partial class AspNetCoreSelfHost
|
||||
public void AddCors(IServiceCollection services)
|
||||
{
|
||||
public void AddCors(IServiceCollection services)
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
||||
{
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
||||
{
|
||||
/* https://stackoverflow.com/questions/31942037/how-to-enable-cors-in-asp-net-core */
|
||||
/* Enable Cors */
|
||||
services.AddCors(corsOptions => corsOptions
|
||||
.AddPolicy(CorsPolicyName,
|
||||
corsPolicyBuilder =>
|
||||
/* https://stackoverflow.com/questions/31942037/how-to-enable-cors-in-asp-net-core */
|
||||
/* Enable Cors */
|
||||
services.AddCors(corsOptions => corsOptions
|
||||
.AddPolicy(CorsPolicyName,
|
||||
corsPolicyBuilder =>
|
||||
{
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyHeader))
|
||||
{
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyHeader))
|
||||
{
|
||||
corsPolicyBuilder.AllowAnyHeader();
|
||||
}
|
||||
corsPolicyBuilder.AllowAnyHeader();
|
||||
}
|
||||
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyMethod))
|
||||
{
|
||||
corsPolicyBuilder.AllowAnyMethod();
|
||||
}
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyMethod))
|
||||
{
|
||||
corsPolicyBuilder.AllowAnyMethod();
|
||||
}
|
||||
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyOrigin))
|
||||
{
|
||||
corsPolicyBuilder.AllowAnyOrigin();
|
||||
}
|
||||
}));
|
||||
}
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions.Value.HasFlag(CorsPolicyOptions.AllowAnyOrigin))
|
||||
{
|
||||
corsPolicyBuilder.AllowAnyOrigin();
|
||||
}
|
||||
}));
|
||||
}
|
||||
}
|
||||
|
||||
public void UseCors(IApplicationBuilder appBuilder)
|
||||
public void UseCors(IApplicationBuilder appBuilder)
|
||||
{
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
||||
{
|
||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
||||
{
|
||||
/* Use Cors */
|
||||
appBuilder.UseCors(CorsPolicyName);
|
||||
}
|
||||
/* Use Cors */
|
||||
appBuilder.UseCors(CorsPolicyName);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -5,7 +5,6 @@ using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.HttpsCertificate;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
#if USE_ASPNETCORE && NETSTANDARD1_3
|
||||
#if USE_ASPNETCORE && NETSTANDARD1_3
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
@@ -6,58 +6,58 @@ using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.HttpsCertificate;
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
internal partial class AspNetCoreSelfHost
|
||||
{
|
||||
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
|
||||
{
|
||||
options.Limits.MaxRequestBufferSize = null;
|
||||
options.Limits.MaxRequestHeaderCount = 100;
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
namespace WireMock.Owin;
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
internal partial class AspNetCoreSelfHost
|
||||
{
|
||||
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
|
||||
{
|
||||
options.Limits.MaxRequestBufferSize = null;
|
||||
options.Limits.MaxRequestHeaderCount = 100;
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
{
|
||||
foreach (var urlDetail in urlDetails)
|
||||
{
|
||||
foreach (var urlDetail in urlDetails)
|
||||
if (urlDetail.IsHttps)
|
||||
{
|
||||
if (urlDetail.IsHttps)
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
options.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
}
|
||||
options.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class IWebHostBuilderExtensions
|
||||
internal static class IWebHostBuilderExtensions
|
||||
{
|
||||
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder;
|
||||
|
||||
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
|
||||
{
|
||||
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder;
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
|
||||
return builder.ConfigureServices(services =>
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
return builder.ConfigureServices(services =>
|
||||
{
|
||||
services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
|
||||
});
|
||||
}
|
||||
services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
#endif
|
||||
@@ -5,7 +5,6 @@ using System.IO;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.AspNetCore.Builder;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
@@ -30,16 +29,16 @@ namespace WireMock.Owin
|
||||
|
||||
public bool IsStarted { get; private set; }
|
||||
|
||||
public List<string> Urls { get; } = new List<string>();
|
||||
public List<string> Urls { get; } = new();
|
||||
|
||||
public List<int> Ports { get; } = new List<int>();
|
||||
public List<int> Ports { get; } = new();
|
||||
|
||||
public Exception RunningException => _runningException;
|
||||
|
||||
public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions wireMockMiddlewareOptions, [NotNull] HostUrlOptions urlOptions)
|
||||
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
|
||||
{
|
||||
Guard.NotNull(wireMockMiddlewareOptions, nameof(wireMockMiddlewareOptions));
|
||||
Guard.NotNull(urlOptions, nameof(urlOptions));
|
||||
Guard.NotNull(wireMockMiddlewareOptions);
|
||||
Guard.NotNull(urlOptions);
|
||||
|
||||
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
|
||||
|
||||
@@ -119,7 +118,7 @@ namespace WireMock.Owin
|
||||
{
|
||||
Urls.Add(address.Replace("0.0.0.0", "localhost").Replace("[::]", "localhost"));
|
||||
|
||||
PortUtils.TryExtract(address, out bool isHttps, out string protocol, out string host, out int port);
|
||||
PortUtils.TryExtract(address, out _, out _, out _, out int port);
|
||||
Ports.Add(port);
|
||||
}
|
||||
|
||||
@@ -133,7 +132,7 @@ namespace WireMock.Owin
|
||||
#elif NETSTANDARD2_1
|
||||
_logger.Info("Server using netstandard2.1");
|
||||
#elif NETCOREAPP3_1
|
||||
_logger.Info("Server using .NET Core 3.1");
|
||||
_logger.Info("Server using .NET Core App 3.1");
|
||||
#elif NET5_0
|
||||
_logger.Info("Server using .NET 5.0");
|
||||
#elif NET6_0
|
||||
|
||||
@@ -1,15 +1,14 @@
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal struct HostUrlDetails
|
||||
{
|
||||
internal class HostUrlDetails
|
||||
{
|
||||
public bool IsHttps { get; set; }
|
||||
public bool IsHttps { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
public string Url { get; set; }
|
||||
|
||||
public string Protocol { get; set; }
|
||||
public string Protocol { get; set; }
|
||||
|
||||
public string Host { get; set; }
|
||||
public string Host { get; set; }
|
||||
|
||||
public int Port { get; set; }
|
||||
}
|
||||
public int Port { get; set; }
|
||||
}
|
||||
@@ -1,46 +1,47 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class HostUrlOptions
|
||||
{
|
||||
internal class HostUrlOptions
|
||||
private const string LOCALHOST = "localhost";
|
||||
|
||||
public ICollection<string>? Urls { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
public ICollection<HostUrlDetails> GetDetails()
|
||||
{
|
||||
private const string LOCALHOST = "localhost";
|
||||
|
||||
public ICollection<string> Urls { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
public ICollection<HostUrlDetails> GetDetails()
|
||||
var list = new List<HostUrlDetails>();
|
||||
if (Urls == null)
|
||||
{
|
||||
var list = new List<HostUrlDetails>();
|
||||
if (Urls == null)
|
||||
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
|
||||
string protocol = UseSSL ? "https" : "http";
|
||||
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string url in Urls)
|
||||
{
|
||||
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
|
||||
string protocol = UseSSL ? "https" : "http";
|
||||
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string url in Urls)
|
||||
if (PortUtils.TryExtract(url, out bool isHttps, out var protocol, out var host, out int port))
|
||||
{
|
||||
PortUtils.TryExtract(url, out bool isHttps, out string protocol, out string host, out int port);
|
||||
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
}
|
||||
|
||||
private int FindFreeTcpPort()
|
||||
{
|
||||
return list;
|
||||
}
|
||||
|
||||
private static int FindFreeTcpPort()
|
||||
{
|
||||
#if USE_ASPNETCORE || NETSTANDARD2_0 || NETSTANDARD2_1
|
||||
return 0;
|
||||
return 0;
|
||||
#else
|
||||
return PortUtils.FindFreeTcpPort();
|
||||
return PortUtils.FindFreeTcpPort();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal interface IMappingMatcher
|
||||
{
|
||||
internal interface IMappingMatcher
|
||||
{
|
||||
(MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request);
|
||||
}
|
||||
(MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request);
|
||||
}
|
||||
@@ -1,36 +1,35 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading.Tasks;
|
||||
using System;
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
interface IOwinSelfHost
|
||||
{
|
||||
interface IOwinSelfHost
|
||||
{
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this server is started.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this server is started; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
bool IsStarted { get; }
|
||||
/// <summary>
|
||||
/// Gets a value indicating whether this server is started.
|
||||
/// </summary>
|
||||
/// <value>
|
||||
/// <c>true</c> if this server is started; otherwise, <c>false</c>.
|
||||
/// </value>
|
||||
bool IsStarted { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the urls.
|
||||
/// </summary>
|
||||
List<string> Urls { get; }
|
||||
/// <summary>
|
||||
/// Gets the urls.
|
||||
/// </summary>
|
||||
List<string> Urls { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Gets the ports.
|
||||
/// </summary>
|
||||
List<int> Ports { get; }
|
||||
/// <summary>
|
||||
/// Gets the ports.
|
||||
/// </summary>
|
||||
List<int> Ports { get; }
|
||||
|
||||
/// <summary>
|
||||
/// The exception occurred when the host is running
|
||||
/// </summary>
|
||||
Exception RunningException { get; }
|
||||
/// <summary>
|
||||
/// The exception occurred when the host is running.
|
||||
/// </summary>
|
||||
Exception? RunningException { get; }
|
||||
|
||||
Task StartAsync();
|
||||
Task StartAsync();
|
||||
|
||||
Task StopAsync();
|
||||
}
|
||||
Task StopAsync();
|
||||
}
|
||||
@@ -12,62 +12,61 @@ using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
#endif
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal interface IWireMockMiddlewareOptions
|
||||
{
|
||||
internal interface IWireMockMiddlewareOptions
|
||||
{
|
||||
IWireMockLogger Logger { get; set; }
|
||||
IWireMockLogger Logger { get; set; }
|
||||
|
||||
TimeSpan? RequestProcessingDelay { get; set; }
|
||||
TimeSpan? RequestProcessingDelay { get; set; }
|
||||
|
||||
IStringMatcher? AuthenticationMatcher { get; set; }
|
||||
IStringMatcher? AuthenticationMatcher { get; set; }
|
||||
|
||||
bool? AllowPartialMapping { get; set; }
|
||||
bool? AllowPartialMapping { get; set; }
|
||||
|
||||
ConcurrentDictionary<Guid, IMapping> Mappings { get; }
|
||||
ConcurrentDictionary<Guid, IMapping> Mappings { get; }
|
||||
|
||||
ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
|
||||
ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
|
||||
|
||||
ConcurrentObservableCollection<LogEntry> LogEntries { get; }
|
||||
ConcurrentObservableCollection<LogEntry> LogEntries { get; }
|
||||
|
||||
int? RequestLogExpirationDuration { get; set; }
|
||||
int? RequestLogExpirationDuration { get; set; }
|
||||
|
||||
int? MaxRequestLogCount { get; set; }
|
||||
int? MaxRequestLogCount { get; set; }
|
||||
|
||||
Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
|
||||
Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
|
||||
|
||||
Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
|
||||
Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||
|
||||
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||
#endif
|
||||
|
||||
IFileSystemHandler? FileSystemHandler { get; set; }
|
||||
IFileSystemHandler? FileSystemHandler { get; set; }
|
||||
|
||||
bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
bool? AllowBodyForAllHttpMethods { get; set; }
|
||||
|
||||
bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||
bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||
|
||||
bool? DisableJsonBodyParsing { get; set; }
|
||||
bool? DisableJsonBodyParsing { get; set; }
|
||||
|
||||
bool? DisableRequestBodyDecompressing { get; set; }
|
||||
bool? DisableRequestBodyDecompressing { get; set; }
|
||||
|
||||
bool? HandleRequestsSynchronously { get; set; }
|
||||
bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
string? X509StoreName { get; set; }
|
||||
string? X509StoreName { get; set; }
|
||||
|
||||
string? X509StoreLocation { get; set; }
|
||||
string? X509StoreLocation { get; set; }
|
||||
|
||||
string? X509ThumbprintOrSubjectName { get; set; }
|
||||
string? X509ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
string? X509CertificateFilePath { get; set; }
|
||||
string? X509CertificateFilePath { get; set; }
|
||||
|
||||
string? X509CertificatePassword { get; set; }
|
||||
string? X509CertificatePassword { get; set; }
|
||||
|
||||
bool CustomCertificateDefined { get; }
|
||||
bool CustomCertificateDefined { get; }
|
||||
|
||||
bool? SaveUnmatchedRequests { get; set; }
|
||||
}
|
||||
bool? SaveUnmatchedRequests { get; set; }
|
||||
}
|
||||
@@ -27,8 +27,8 @@ namespace WireMock.Owin.Mappers
|
||||
|
||||
string method = request.Method;
|
||||
|
||||
Dictionary<string, string[]> headers = null;
|
||||
IEnumerable<string> contentEncodingHeader = null;
|
||||
var headers = new Dictionary<string, string[]>();
|
||||
IEnumerable<string>? contentEncodingHeader = null;
|
||||
if (request.Headers.Any())
|
||||
{
|
||||
headers = new Dictionary<string, string[]>();
|
||||
@@ -43,7 +43,7 @@ namespace WireMock.Owin.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
IDictionary<string, string> cookies = null;
|
||||
var cookies = new Dictionary<string, string>();
|
||||
if (request.Cookies.Any())
|
||||
{
|
||||
cookies = new Dictionary<string, string>();
|
||||
@@ -53,7 +53,7 @@ namespace WireMock.Owin.Mappers
|
||||
}
|
||||
}
|
||||
|
||||
IBodyData body = null;
|
||||
IBodyData? body = null;
|
||||
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
|
||||
{
|
||||
var bodyParserSettings = new BodyParserSettings
|
||||
@@ -75,13 +75,24 @@ namespace WireMock.Owin.Mappers
|
||||
{
|
||||
#if !USE_ASPNETCORE
|
||||
var urlDetails = UrlUtils.Parse(request.Uri, request.PathBase);
|
||||
string clientIP = request.RemoteIpAddress;
|
||||
var clientIP = request.RemoteIpAddress;
|
||||
#else
|
||||
var urlDetails = UrlUtils.Parse(new Uri(request.GetEncodedUrl()), request.PathBase);
|
||||
|
||||
var connection = request.HttpContext.Connection;
|
||||
string clientIP = connection.RemoteIpAddress.IsIPv4MappedToIPv6
|
||||
? connection.RemoteIpAddress.MapToIPv4().ToString()
|
||||
: connection.RemoteIpAddress.ToString();
|
||||
string clientIP;
|
||||
if (connection.RemoteIpAddress is null)
|
||||
{
|
||||
clientIP = string.Empty;
|
||||
}
|
||||
else if (connection.RemoteIpAddress.IsIPv4MappedToIPv6)
|
||||
{
|
||||
clientIP = connection.RemoteIpAddress.MapToIPv4().ToString();
|
||||
}
|
||||
else
|
||||
{
|
||||
clientIP = connection.RemoteIpAddress.ToString();
|
||||
}
|
||||
#endif
|
||||
return (urlDetails, clientIP);
|
||||
}
|
||||
|
||||
@@ -71,7 +71,6 @@ namespace WireMock.Owin.Mappers
|
||||
{
|
||||
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
|
||||
}
|
||||
|
||||
break;
|
||||
|
||||
default:
|
||||
@@ -80,11 +79,10 @@ namespace WireMock.Owin.Mappers
|
||||
}
|
||||
|
||||
var statusCodeType = responseMessage.StatusCode?.GetType();
|
||||
|
||||
switch (statusCodeType)
|
||||
{
|
||||
case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
|
||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode);
|
||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
|
||||
break;
|
||||
|
||||
case Type typeAsString when typeAsString == typeof(string):
|
||||
@@ -138,7 +136,7 @@ namespace WireMock.Owin.Mappers
|
||||
return responseMessage.BodyData.BodyAsBytes;
|
||||
|
||||
case BodyType.File:
|
||||
return _options.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||
return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||
}
|
||||
|
||||
return null;
|
||||
|
||||
@@ -4,72 +4,71 @@ using System.Linq;
|
||||
using WireMock.Extensions;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class MappingMatcher : IMappingMatcher
|
||||
{
|
||||
internal class MappingMatcher : IMappingMatcher
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
|
||||
public MappingMatcher(IWireMockMiddlewareOptions options)
|
||||
{
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
Guard.NotNull(options, nameof(options));
|
||||
|
||||
public MappingMatcher(IWireMockMiddlewareOptions options)
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public (MappingMatcherResult? Match, MappingMatcherResult? Partial) FindBestMatch(RequestMessage request)
|
||||
{
|
||||
var possibleMappings = new List<MappingMatcherResult>();
|
||||
|
||||
foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
|
||||
{
|
||||
Guard.NotNull(options, nameof(options));
|
||||
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public (MappingMatcherResult Match, MappingMatcherResult Partial) FindBestMatch(RequestMessage request)
|
||||
{
|
||||
var mappings = new List<MappingMatcherResult>();
|
||||
|
||||
foreach (var mapping in _options.Mappings.Values.Where(m => m.TimeSettings.IsValid()))
|
||||
try
|
||||
{
|
||||
try
|
||||
var nextState = GetNextState(mapping);
|
||||
|
||||
possibleMappings.Add(new MappingMatcherResult
|
||||
{
|
||||
string nextState = GetNextState(mapping);
|
||||
|
||||
mappings.Add(new MappingMatcherResult
|
||||
{
|
||||
Mapping = mapping,
|
||||
RequestMatchResult = mapping.GetRequestMatchResult(request, nextState)
|
||||
});
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}");
|
||||
}
|
||||
Mapping = mapping,
|
||||
RequestMatchResult = mapping.GetRequestMatchResult(request, nextState)
|
||||
});
|
||||
}
|
||||
|
||||
var partialMappings = mappings
|
||||
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
|
||||
.OrderBy(m => m.RequestMatchResult)
|
||||
.ThenBy(m => m.Mapping.Priority)
|
||||
.ToList();
|
||||
var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
|
||||
|
||||
if (_options.AllowPartialMapping == true)
|
||||
catch (Exception ex)
|
||||
{
|
||||
return (partialMatch, partialMatch);
|
||||
_options.Logger.Error($"Getting a Request MatchResult for Mapping '{mapping.Guid}' failed. This mapping will not be evaluated. Exception: {ex}");
|
||||
}
|
||||
|
||||
var match = mappings
|
||||
.Where(m => m.RequestMatchResult.IsPerfectMatch)
|
||||
.OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult)
|
||||
.FirstOrDefault();
|
||||
|
||||
return (match, partialMatch);
|
||||
}
|
||||
|
||||
private string GetNextState(IMapping mapping)
|
||||
var partialMappings = possibleMappings
|
||||
.Where(pm => (pm.Mapping.IsAdminInterface && pm.RequestMatchResult.IsPerfectMatch) || !pm.Mapping.IsAdminInterface)
|
||||
.OrderBy(m => m.RequestMatchResult)
|
||||
.ThenBy(m => m.Mapping.Priority)
|
||||
.ToList();
|
||||
var partialMatch = partialMappings.FirstOrDefault(pm => pm.RequestMatchResult.AverageTotalScore > 0.0);
|
||||
|
||||
if (_options.AllowPartialMapping == true)
|
||||
{
|
||||
// If the mapping does not have a scenario or _options.Scenarios does not contain this scenario from the mapping,
|
||||
// just return null to indicate that there is no next state.
|
||||
if (mapping.Scenario == null || !_options.Scenarios.ContainsKey(mapping.Scenario))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Else just return the next state
|
||||
return _options.Scenarios[mapping.Scenario].NextState;
|
||||
return (partialMatch, partialMatch);
|
||||
}
|
||||
|
||||
var match = possibleMappings
|
||||
.Where(m => m.RequestMatchResult.IsPerfectMatch)
|
||||
.OrderBy(m => m.Mapping.Priority).ThenBy(m => m.RequestMatchResult)
|
||||
.FirstOrDefault();
|
||||
|
||||
return (match, partialMatch);
|
||||
}
|
||||
|
||||
private string? GetNextState(IMapping mapping)
|
||||
{
|
||||
// If the mapping does not have a scenario or _options.Scenarios does not contain this scenario from the mapping,
|
||||
// just return null to indicate that there is no next state.
|
||||
if (mapping.Scenario == null || !_options.Scenarios.ContainsKey(mapping.Scenario))
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
// Else just return the next state
|
||||
return _options.Scenarios[mapping.Scenario].NextState;
|
||||
}
|
||||
}
|
||||
@@ -1,11 +1,10 @@
|
||||
using WireMock.Matchers.Request;
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
internal class MappingMatcherResult
|
||||
{
|
||||
public IMapping Mapping { get; set; }
|
||||
namespace WireMock.Owin;
|
||||
|
||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
||||
}
|
||||
internal class MappingMatcherResult
|
||||
{
|
||||
public IMapping Mapping { get; set; }
|
||||
|
||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
||||
}
|
||||
@@ -1,110 +1,109 @@
|
||||
#if !USE_ASPNETCORE
|
||||
using JetBrains.Annotations;
|
||||
using Microsoft.Owin.Hosting;
|
||||
using Owin;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Owin.Mappers;
|
||||
using Stef.Validation;
|
||||
|
||||
namespace WireMock.Owin
|
||||
namespace WireMock.Owin;
|
||||
|
||||
internal class OwinSelfHost : IOwinSelfHost
|
||||
{
|
||||
internal class OwinSelfHost : IOwinSelfHost
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly CancellationTokenSource _cts = new();
|
||||
private readonly IWireMockLogger _logger;
|
||||
|
||||
private Exception? _runningException;
|
||||
|
||||
public OwinSelfHost(IWireMockMiddlewareOptions options, HostUrlOptions urlOptions)
|
||||
{
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private readonly IWireMockLogger _logger;
|
||||
Guard.NotNull(options, nameof(options));
|
||||
Guard.NotNull(urlOptions, nameof(urlOptions));
|
||||
|
||||
private Exception _runningException;
|
||||
_options = options;
|
||||
_logger = options.Logger ?? new WireMockConsoleLogger();
|
||||
|
||||
public OwinSelfHost([NotNull] IWireMockMiddlewareOptions options, [NotNull] HostUrlOptions urlOptions)
|
||||
foreach (var detail in urlOptions.GetDetails())
|
||||
{
|
||||
Guard.NotNull(options, nameof(options));
|
||||
Guard.NotNull(urlOptions, nameof(urlOptions));
|
||||
|
||||
_options = options;
|
||||
_logger = options.Logger ?? new WireMockConsoleLogger();
|
||||
|
||||
foreach (var detail in urlOptions.GetDetails())
|
||||
{
|
||||
Urls.Add(detail.Url);
|
||||
Ports.Add(detail.Port);
|
||||
}
|
||||
Urls.Add(detail.Url);
|
||||
Ports.Add(detail.Port);
|
||||
}
|
||||
}
|
||||
|
||||
public bool IsStarted { get; private set; }
|
||||
public bool IsStarted { get; private set; }
|
||||
|
||||
public List<string> Urls { get; } = new List<string>();
|
||||
public List<string> Urls { get; } = new();
|
||||
|
||||
public List<int> Ports { get; } = new List<int>();
|
||||
public List<int> Ports { get; } = new();
|
||||
|
||||
public Exception RunningException => _runningException;
|
||||
public Exception? RunningException => _runningException;
|
||||
|
||||
[PublicAPI]
|
||||
public Task StartAsync()
|
||||
{
|
||||
return Task.Run(StartServers, _cts.Token);
|
||||
}
|
||||
[PublicAPI]
|
||||
public Task StartAsync()
|
||||
{
|
||||
return Task.Run(StartServers, _cts.Token);
|
||||
}
|
||||
|
||||
[PublicAPI]
|
||||
public Task StopAsync()
|
||||
{
|
||||
_cts.Cancel();
|
||||
[PublicAPI]
|
||||
public Task StopAsync()
|
||||
{
|
||||
_cts.Cancel();
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
|
||||
private void StartServers()
|
||||
{
|
||||
private void StartServers()
|
||||
{
|
||||
#if NET46
|
||||
_logger.Info("Server using .net 4.6.1 or higher");
|
||||
_logger.Info("Server using .net 4.6.1 or higher");
|
||||
#else
|
||||
_logger.Info("Server using .net 4.5.x");
|
||||
_logger.Info("Server using .net 4.5.x");
|
||||
#endif
|
||||
var servers = new List<IDisposable>();
|
||||
var servers = new List<IDisposable>();
|
||||
|
||||
try
|
||||
try
|
||||
{
|
||||
var requestMapper = new OwinRequestMapper();
|
||||
var responseMapper = new OwinResponseMapper(_options);
|
||||
var matcher = new MappingMatcher(_options);
|
||||
|
||||
Action<IAppBuilder> startup = app =>
|
||||
{
|
||||
var requestMapper = new OwinRequestMapper();
|
||||
var responseMapper = new OwinResponseMapper(_options);
|
||||
var matcher = new MappingMatcher(_options);
|
||||
app.Use<GlobalExceptionMiddleware>(_options, responseMapper);
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(app);
|
||||
app.Use<WireMockMiddleware>(_options, requestMapper, responseMapper, matcher);
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(app);
|
||||
};
|
||||
|
||||
Action<IAppBuilder> startup = app =>
|
||||
{
|
||||
app.Use<GlobalExceptionMiddleware>(_options, responseMapper);
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(app);
|
||||
app.Use<WireMockMiddleware>(_options, requestMapper, responseMapper, matcher);
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(app);
|
||||
};
|
||||
|
||||
foreach (var url in Urls)
|
||||
{
|
||||
servers.Add(WebApp.Start(url, startup));
|
||||
}
|
||||
|
||||
IsStarted = true;
|
||||
|
||||
// WaitHandle is signaled when the token is cancelled,
|
||||
// which will be more efficient than Thread.Sleep in while loop
|
||||
_cts.Token.WaitHandle.WaitOne();
|
||||
}
|
||||
catch (Exception e)
|
||||
foreach (var url in Urls)
|
||||
{
|
||||
// Expose exception of starting host, otherwise it's hard to be troubleshooting if keeping quiet
|
||||
// For example, WebApp.Start will fail with System.MissingMemberException if Microsoft.Owin.Host.HttpListener.dll is being located
|
||||
// https://stackoverflow.com/questions/25090211/owin-httplistener-not-located/31369857
|
||||
_runningException = e;
|
||||
_logger.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsStarted = false;
|
||||
// Dispose all servers in finally block to make sure clean up allocated resource on error happening
|
||||
servers.ForEach(s => s.Dispose());
|
||||
servers.Add(WebApp.Start(url, startup));
|
||||
}
|
||||
|
||||
IsStarted = true;
|
||||
|
||||
// WaitHandle is signaled when the token is cancelled,
|
||||
// which will be more efficient than Thread.Sleep in while loop
|
||||
_cts.Token.WaitHandle.WaitOne();
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
// Expose exception of starting host, otherwise it's hard to be troubleshooting if keeping quiet
|
||||
// For example, WebApp.Start will fail with System.MissingMemberException if Microsoft.Owin.Host.HttpListener.dll is being located
|
||||
// https://stackoverflow.com/questions/25090211/owin-httplistener-not-located/31369857
|
||||
_runningException = e;
|
||||
_logger.Error(e.ToString());
|
||||
}
|
||||
finally
|
||||
{
|
||||
IsStarted = false;
|
||||
// Dispose all servers in finally block to make sure clean up allocated resource on error happening
|
||||
servers.ForEach(s => s.Dispose());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using Stef.Validation;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
@@ -74,10 +75,16 @@ namespace WireMock.Owin
|
||||
var logRequest = false;
|
||||
IResponseMessage? response = null;
|
||||
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
|
||||
|
||||
try
|
||||
{
|
||||
foreach (var mapping in _options.Mappings.Values.Where(m => m?.Scenario != null))
|
||||
foreach (var mapping in _options.Mappings.Values)
|
||||
{
|
||||
if (mapping.Scenario is null)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
// Set scenario start
|
||||
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
||||
{
|
||||
@@ -107,7 +114,7 @@ namespace WireMock.Owin
|
||||
if (!present || _options.AuthenticationMatcher.IsMatch(authorization.ToString()) < MatchScores.Perfect)
|
||||
{
|
||||
_options.Logger.Error("HttpStatusCode set to 401");
|
||||
response = ResponseMessageBuilder.Create(null, 401);
|
||||
response = ResponseMessageBuilder.Create(null, HttpStatusCode.Unauthorized);
|
||||
return;
|
||||
}
|
||||
}
|
||||
@@ -194,7 +201,7 @@ namespace WireMock.Owin
|
||||
|
||||
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
|
||||
{
|
||||
for (int index = 0; index < mapping.Webhooks.Length; index++)
|
||||
for (int index = 0; index < mapping.Webhooks?.Length; index++)
|
||||
{
|
||||
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
|
||||
var webhookSender = new WebhookSender(mapping.Settings);
|
||||
@@ -212,7 +219,7 @@ namespace WireMock.Owin
|
||||
|
||||
private void UpdateScenarioState(IMapping mapping)
|
||||
{
|
||||
var scenario = _options.Scenarios[mapping.Scenario];
|
||||
var scenario = _options.Scenarios[mapping.Scenario!];
|
||||
|
||||
// Increase the number of times this state has been executed
|
||||
scenario.Counter++;
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user