mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-10 19:27:09 +02:00
Compare commits
24 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
88ff2a72db | ||
|
|
d5026e83b5 | ||
|
|
b6b17d80cc | ||
|
|
c8ad9f49e4 | ||
|
|
0a4aca9ae9 | ||
|
|
e5ed6036ee | ||
|
|
7b534635b9 | ||
|
|
1562958172 | ||
|
|
35d42a5c0d | ||
|
|
429d6830ae | ||
|
|
38634ac65a | ||
|
|
ef5f988786 | ||
|
|
1e44f52ad6 | ||
|
|
7fd1d30d0e | ||
|
|
49b29d74dc | ||
|
|
80931e9fb5 | ||
|
|
cce344ff83 | ||
|
|
0972d2cb8f | ||
|
|
a39b7fc633 | ||
|
|
31298d281d | ||
|
|
b4c32dd66b | ||
|
|
57115f1a3d | ||
|
|
306c69f478 | ||
|
|
fb8fec0376 |
2
.github/FUNDING.yml
vendored
2
.github/FUNDING.yml
vendored
@@ -1,6 +1,6 @@
|
|||||||
# These are supported funding model platforms
|
# These are supported funding model platforms
|
||||||
|
|
||||||
github: # [StefH]
|
github: [StefH]
|
||||||
patreon: # Replace with a single Patreon username
|
patreon: # Replace with a single Patreon username
|
||||||
open_collective: # wiremocknet
|
open_collective: # wiremocknet
|
||||||
ko_fi: # Replace with a single Ko-fi username
|
ko_fi: # Replace with a single Ko-fi username
|
||||||
|
|||||||
17
CHANGELOG.md
17
CHANGELOG.md
@@ -1,3 +1,20 @@
|
|||||||
|
# 1.5.11 (24 November 2022)
|
||||||
|
- [#836](https://github.com/WireMock-Net/WireMock.Net/pull/836) - Add Settings.QueryParameterMultipleValueSupport [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#848](https://github.com/WireMock-Net/WireMock.Net/pull/848) - Use try-catch when adding or removing logEntry [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#846](https://github.com/WireMock-Net/WireMock.Net/issues/846) - Exception ArgumentOutOfRangeException [bug]
|
||||||
|
|
||||||
|
# 1.5.10 (06 November 2022)
|
||||||
|
- [#843](https://github.com/WireMock-Net/WireMock.Net/pull/843) - Webhook Templating: Use the transformed URL to create the HttpRequestMessage contributed by [ggradnig](https://github.com/ggradnig)
|
||||||
|
- [#845](https://github.com/WireMock-Net/WireMock.Net/pull/845) - Add WireMockNullLogger as valid commandline logger option [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
|
# 1.5.9 (29 October 2022)
|
||||||
|
- [#828](https://github.com/WireMock-Net/WireMock.Net/pull/828) - Add setting to skip saving the string-response in the logging when using WithBody(Func...) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#832](https://github.com/WireMock-Net/WireMock.Net/pull/832) - Fixes for WireMock.Net.FluentAssertions (callcount behaviour) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#834](https://github.com/WireMock-Net/WireMock.Net/pull/834) - Support deleting / resetting a single scenario [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#837](https://github.com/WireMock-Net/WireMock.Net/pull/837) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.7 to 2.1.25 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
|
- [#838](https://github.com/WireMock-Net/WireMock.Net/pull/838) - Add option to ProxySettings to append guid to mapping file contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#826](https://github.com/WireMock-Net/WireMock.Net/issues/826) - Dynamic Body not to be cached when a Func is used to created the body [feature]
|
||||||
|
|
||||||
# 1.5.8 (16 October 2022)
|
# 1.5.8 (16 October 2022)
|
||||||
- [#816](https://github.com/WireMock-Net/WireMock.Net/pull/816) - Some fixes to WireMock.Net.Assertions [feature] contributed by [StefH](https://github.com/StefH)
|
- [#816](https://github.com/WireMock-Net/WireMock.Net/pull/816) - Some fixes to WireMock.Net.Assertions [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#817](https://github.com/WireMock-Net/WireMock.Net/pull/817) - ExactMatcher : IgnoreCase [feature] contributed by [StefH](https://github.com/StefH)
|
- [#817](https://github.com/WireMock-Net/WireMock.Net/pull/817) - ExactMatcher : IgnoreCase [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.5.8</VersionPrefix>
|
<VersionPrefix>1.5.11</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
@@ -20,6 +20,13 @@
|
|||||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<!-- https://github.com/coverlet-coverage/coverlet/issues/1391 -->
|
||||||
|
<PropertyGroup Condition="$(MSBuildProjectName.Contains('.Tests'))">
|
||||||
|
<CollectCoverage>true</CollectCoverage>
|
||||||
|
<ExcludeByAttribute>GeneratedCodeAttribute</ExcludeByAttribute>
|
||||||
|
<CoverletOutputFormat>opencover</CoverletOutputFormat>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="../../resources/WireMock.Net-Logo.png" Pack="true" PackagePath="" />
|
<None Include="../../resources/WireMock.Net-Logo.png" Pack="true" PackagePath="" />
|
||||||
<!--<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>-->
|
<!--<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>-->
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=1.5.8
|
SET version=1.5.11
|
||||||
|
|
||||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||||
|
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
# 1.5.8 (16 October 2022)
|
# 1.5.11 (24 November 2022)
|
||||||
- #816 Some fixes to WireMock.Net.Assertions [feature]
|
- #836 Add Settings.QueryParameterMultipleValueSupport [feature]
|
||||||
- #817 ExactMatcher : IgnoreCase [feature]
|
- #848 Use try-catch when adding or removing logEntry [bug]
|
||||||
- #824 WebHook - Transform Url [feature]
|
- #846 Exception ArgumentOutOfRangeException [bug]
|
||||||
- #814 WithHeader cannot handle multiple requests with the same header key values [bug]
|
|
||||||
- #815 Why does UsingMethod check _callscount? [bug]
|
|
||||||
- #822 Webhook with generic url, body and custom header values [feature]
|
|
||||||
|
|
||||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||||
@@ -25,6 +25,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.gitignore = .gitignore
|
.gitignore = .gitignore
|
||||||
CHANGELOG.md = CHANGELOG.md
|
CHANGELOG.md = CHANGELOG.md
|
||||||
Directory.Build.props = Directory.Build.props
|
Directory.Build.props = Directory.Build.props
|
||||||
|
.github\FUNDING.yml = .github\FUNDING.yml
|
||||||
Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
|
Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
|
||||||
nuget.config = nuget.config
|
nuget.config = nuget.config
|
||||||
PackageReleaseNotes.template = PackageReleaseNotes.template
|
PackageReleaseNotes.template = PackageReleaseNotes.template
|
||||||
@@ -105,6 +106,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\W
|
|||||||
EndProject
|
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}"
|
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
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueExample", "examples\WireMockAzureQueueExample\WireMockAzureQueueExample.csproj", "{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}"
|
||||||
|
EndProject
|
||||||
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueProxy", "examples\WireMockAzureQueueProxy\WireMockAzureQueueProxy.csproj", "{ADB557D8-D66B-4387-912B-3F73E290B478}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -251,6 +256,14 @@ Global
|
|||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.Build.0 = 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.ActiveCfg = Release|Any CPU
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
|
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{ADB557D8-D66B-4387-912B-3F73E290B478}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{ADB557D8-D66B-4387-912B-3F73E290B478}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{ADB557D8-D66B-4387-912B-3F73E290B478}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{ADB557D8-D66B-4387-912B-3F73E290B478}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -293,6 +306,8 @@ Global
|
|||||||
{670C7562-C154-442E-A249-7D26849BCD13} = {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}
|
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{ADB557D8-D66B-4387-912B-3F73E290B478} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||||
|
|||||||
@@ -1,10 +1,18 @@
|
|||||||
<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">
|
<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/=AD/@EntryIndexedValue">AD</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=CONNECT/@EntryIndexedValue">CONNECT</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/=CS/@EntryIndexedValue">CS</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=DELETE/@EntryIndexedValue">DELETE</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/=EC/@EntryIndexedValue">EC</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=GET/@EntryIndexedValue">GET</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=HEAD/@EntryIndexedValue">HEAD</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/=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/=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/=MD/@EntryIndexedValue">MD5</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=OPTIONS/@EntryIndexedValue">OPTIONS</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PATCH/@EntryIndexedValue">PATCH</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=POST/@EntryIndexedValue">POST</s:String>
|
||||||
|
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=PUT/@EntryIndexedValue">PUT</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/=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/=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/=TE/@EntryIndexedValue">TE</s:String>
|
||||||
|
|||||||
@@ -44,12 +44,10 @@ jobs:
|
|||||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||||
arguments: '--configuration Debug --framework net6.0'
|
arguments: '--configuration Debug --framework net6.0'
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: CmdLine@2
|
||||||
displayName: 'Execute Unit tests'
|
|
||||||
inputs:
|
inputs:
|
||||||
command: 'test'
|
script: 'dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --no-build --configuration Debug --framework net6.0'
|
||||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
displayName: 'Execute Unit Tests with Coverage'
|
||||||
arguments: '--no-build --configuration Debug --framework net6.0 --collect:"XPlat Code Coverage" --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover'
|
|
||||||
|
|
||||||
- task: SonarCloudAnalyze@1
|
- task: SonarCloudAnalyze@1
|
||||||
displayName: 'SonarCloud: Run Code Analysis'
|
displayName: 'SonarCloud: Run Code Analysis'
|
||||||
@@ -76,7 +74,7 @@ jobs:
|
|||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Publish coverage file
|
displayName: Publish coverage file
|
||||||
inputs:
|
inputs:
|
||||||
PathtoPublish: '/home/vsts/work/1/s/test/WireMock.Net.Tests/coverage.net6.0.opencover.xml'
|
PathtoPublish: './test/WireMock.Net.Tests/coverage.net6.0.opencover.xml'
|
||||||
|
|
||||||
- job: Windows_Build_Test
|
- job: Windows_Build_Test
|
||||||
|
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
<?xml version="1.0" encoding="utf-8"?>
|
<?xml version="1.0" encoding="utf-8"?>
|
||||||
<configuration>
|
<configuration>
|
||||||
<startup>
|
<startup>
|
||||||
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
|
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.8"/>
|
||||||
</startup>
|
</startup>
|
||||||
<runtime>
|
<runtime>
|
||||||
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
|
||||||
<dependentAssembly>
|
<dependentAssembly>
|
||||||
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
|
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral"/>
|
||||||
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0" />
|
<bindingRedirect oldVersion="0.0.0.0-13.0.0.0" newVersion="13.0.0.0"/>
|
||||||
</dependentAssembly>
|
</dependentAssembly>
|
||||||
</assemblyBinding>
|
</assemblyBinding>
|
||||||
</runtime>
|
</runtime>
|
||||||
|
|||||||
@@ -8,9 +8,10 @@
|
|||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<RootNamespace>WireMock.Net.Service</RootNamespace>
|
<RootNamespace>WireMock.Net.Service</RootNamespace>
|
||||||
<AssemblyName>WireMock.Net.Service</AssemblyName>
|
<AssemblyName>WireMock.Net.Service</AssemblyName>
|
||||||
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
|
<TargetFrameworkVersion>v4.8</TargetFrameworkVersion>
|
||||||
<FileAlignment>512</FileAlignment>
|
<FileAlignment>512</FileAlignment>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
|
<TargetFrameworkProfile />
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
|
||||||
<PlatformTarget>AnyCPU</PlatformTarget>
|
<PlatformTarget>AnyCPU</PlatformTarget>
|
||||||
|
|||||||
@@ -11,6 +11,6 @@
|
|||||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||||
<package id="Owin" version="1.0" targetFramework="net452" />
|
<package id="Owin" version="1.0" targetFramework="net452" />
|
||||||
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
|
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
|
||||||
<package id="System.Net.Http" version="4.3.4" targetFramework="net452" />
|
<package id="System.Net.Http" version="4.3.4" targetFramework="net452" requireReinstallation="true" />
|
||||||
<package id="XPath2" version="1.1.3" targetFramework="net452" />
|
<package id="XPath2" version="1.1.3" targetFramework="net452" />
|
||||||
</packages>
|
</packages>
|
||||||
@@ -24,7 +24,7 @@
|
|||||||
<package id="Microsoft.AspNetCore.Routing.Abstractions" version="2.1.1" targetFramework="net461" />
|
<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.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" 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.Core" version="2.1.25" targetFramework="net461" />
|
||||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Https" version="2.1.3" 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.Abstractions" version="2.1.3" targetFramework="net461" />
|
||||||
<package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" version="2.1.3" targetFramework="net461" />
|
<package id="Microsoft.AspNetCore.Server.Kestrel.Transport.Sockets" version="2.1.3" targetFramework="net461" />
|
||||||
|
|||||||
@@ -0,0 +1,173 @@
|
|||||||
|
{
|
||||||
|
"$schema": "https://schema.management.azure.com/schemas/2018-05-01/subscriptionDeploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"metadata": {
|
||||||
|
"_dependencyType": "compute.function.linux.appService"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"resourceGroupName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "linux-app-service",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Name of the resource group for the resource. It is recommended to put resources under same resource group for better tracking."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceGroupLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "westeurope",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Location of the resource group. Resource groups could have different location than resources, however by default we use API versions from latest hybrid profile which support all locations for resource types we support."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceName": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "WireMockNetWebApplicationNET6Linux",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Name of the main resource to be created by this template."
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resourceLocation": {
|
||||||
|
"type": "string",
|
||||||
|
"defaultValue": "[parameters('resourceGroupLocation')]",
|
||||||
|
"metadata": {
|
||||||
|
"description": "Location of the resource. By default use resource group's location, unless the resource provider is not supported there."
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/resourceGroups",
|
||||||
|
"name": "[parameters('resourceGroupName')]",
|
||||||
|
"location": "[parameters('resourceGroupLocation')]",
|
||||||
|
"apiVersion": "2019-10-01"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"type": "Microsoft.Resources/deployments",
|
||||||
|
"name": "[concat(parameters('resourceGroupName'), 'Deployment', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
|
||||||
|
"resourceGroup": "[parameters('resourceGroupName')]",
|
||||||
|
"apiVersion": "2019-10-01",
|
||||||
|
"dependsOn": [
|
||||||
|
"[parameters('resourceGroupName')]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"mode": "Incremental",
|
||||||
|
"expressionEvaluationOptions": {
|
||||||
|
"scope": "inner"
|
||||||
|
},
|
||||||
|
"parameters": {
|
||||||
|
"resourceGroupName": {
|
||||||
|
"value": "[parameters('resourceGroupName')]"
|
||||||
|
},
|
||||||
|
"resourceGroupLocation": {
|
||||||
|
"value": "[parameters('resourceGroupLocation')]"
|
||||||
|
},
|
||||||
|
"resourceName": {
|
||||||
|
"value": "[parameters('resourceName')]"
|
||||||
|
},
|
||||||
|
"resourceLocation": {
|
||||||
|
"value": "[parameters('resourceLocation')]"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"template": {
|
||||||
|
"$schema": "http://schema.management.azure.com/schemas/2015-01-01/deploymentTemplate.json#",
|
||||||
|
"contentVersion": "1.0.0.0",
|
||||||
|
"parameters": {
|
||||||
|
"resourceGroupName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"resourceGroupLocation": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"resourceName": {
|
||||||
|
"type": "string"
|
||||||
|
},
|
||||||
|
"resourceLocation": {
|
||||||
|
"type": "string"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"variables": {
|
||||||
|
"storage_name": "[toLower(concat('storage', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId))))]",
|
||||||
|
"appServicePlan_name": "[concat('Plan', uniqueString(concat(parameters('resourceName'), subscription().subscriptionId)))]",
|
||||||
|
"storage_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Storage/storageAccounts/', variables('storage_name'))]",
|
||||||
|
"appServicePlan_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/serverFarms/', variables('appServicePlan_name'))]",
|
||||||
|
"function_ResourceId": "[concat('/subscriptions/', subscription().subscriptionId, '/resourceGroups/', parameters('resourceGroupName'), '/providers/Microsoft.Web/sites/', parameters('resourceName'))]"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"location": "[parameters('resourceLocation')]",
|
||||||
|
"name": "[parameters('resourceName')]",
|
||||||
|
"type": "Microsoft.Web/sites",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"tags": {
|
||||||
|
"[concat('hidden-related:', variables('appServicePlan_ResourceId'))]": "empty"
|
||||||
|
},
|
||||||
|
"dependsOn": [
|
||||||
|
"[variables('appServicePlan_ResourceId')]",
|
||||||
|
"[variables('storage_ResourceId')]"
|
||||||
|
],
|
||||||
|
"kind": "functionapp",
|
||||||
|
"properties": {
|
||||||
|
"name": "[parameters('resourceName')]",
|
||||||
|
"kind": "functionapp",
|
||||||
|
"httpsOnly": true,
|
||||||
|
"reserved": false,
|
||||||
|
"serverFarmId": "[variables('appServicePlan_ResourceId')]",
|
||||||
|
"siteConfig": {
|
||||||
|
"alwaysOn": true,
|
||||||
|
"linuxFxVersion": "dotnet|3.1"
|
||||||
|
}
|
||||||
|
},
|
||||||
|
"identity": {
|
||||||
|
"type": "SystemAssigned"
|
||||||
|
},
|
||||||
|
"resources": [
|
||||||
|
{
|
||||||
|
"name": "appsettings",
|
||||||
|
"type": "config",
|
||||||
|
"apiVersion": "2015-08-01",
|
||||||
|
"dependsOn": [
|
||||||
|
"[variables('function_ResourceId')]"
|
||||||
|
],
|
||||||
|
"properties": {
|
||||||
|
"AzureWebJobsStorage": "[concat('DefaultEndpointsProtocol=https;AccountName=', variables('storage_name'), ';AccountKey=', listKeys(variables('storage_ResourceId'), '2017-10-01').keys[0].value, ';EndpointSuffix=', 'core.windows.net')]",
|
||||||
|
"FUNCTIONS_EXTENSION_VERSION": "~3",
|
||||||
|
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "[parameters('resourceGroupLocation')]",
|
||||||
|
"name": "[variables('storage_name')]",
|
||||||
|
"type": "Microsoft.Storage/storageAccounts",
|
||||||
|
"apiVersion": "2017-10-01",
|
||||||
|
"tags": {
|
||||||
|
"[concat('hidden-related:', concat('/providers/Microsoft.Web/sites/', parameters('resourceName')))]": "empty"
|
||||||
|
},
|
||||||
|
"properties": {
|
||||||
|
"supportsHttpsTrafficOnly": true
|
||||||
|
},
|
||||||
|
"sku": {
|
||||||
|
"name": "Standard_LRS"
|
||||||
|
},
|
||||||
|
"kind": "Storage"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"location": "[parameters('resourceGroupLocation')]",
|
||||||
|
"name": "[variables('appServicePlan_name')]",
|
||||||
|
"type": "Microsoft.Web/serverFarms",
|
||||||
|
"apiVersion": "2015-02-01",
|
||||||
|
"kind": "linux",
|
||||||
|
"properties": {
|
||||||
|
"name": "[variables('appServicePlan_name')]",
|
||||||
|
"sku": "Standard",
|
||||||
|
"workerSizeId": "0",
|
||||||
|
"reserved": true
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6</TargetFramework>
|
<TargetFramework>net6</TargetFramework>
|
||||||
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
|
<!--<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>-->
|
||||||
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
|
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
|
||||||
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
|
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
|
||||||
<RootNamespace>WireMock.Net.WebApplication</RootNamespace>
|
<RootNamespace>WireMock.Net.WebApplication</RootNamespace>
|
||||||
@@ -10,10 +10,6 @@
|
|||||||
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
|
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<Content Remove="Properties\1.launchSettings.json" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
|||||||
@@ -15,15 +15,7 @@
|
|||||||
"WireMockServerSettings": {
|
"WireMockServerSettings": {
|
||||||
"StartAdminInterface": true,
|
"StartAdminInterface": true,
|
||||||
"Urls": [
|
"Urls": [
|
||||||
"https://localhost:8081/"
|
"http://localhost"
|
||||||
],
|
]
|
||||||
"AllowPartialMapping": false,
|
|
||||||
"HandleRequestsSynchronously": true,
|
|
||||||
"ThrowExceptionWhenMatcherFails": true,
|
|
||||||
"ProxyAndRecordSettings": {
|
|
||||||
"Url": "http://postman-echo.com/post",
|
|
||||||
"SaveMapping": true,
|
|
||||||
"SaveMappingToFile": true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
264
examples/WireMockAzureQueueExample/.gitignore
vendored
Normal file
264
examples/WireMockAzureQueueExample/.gitignore
vendored
Normal file
@@ -0,0 +1,264 @@
|
|||||||
|
## Ignore Visual Studio temporary files, build results, and
|
||||||
|
## files generated by popular Visual Studio add-ons.
|
||||||
|
|
||||||
|
# Azure Functions localsettings file
|
||||||
|
local.settings.json
|
||||||
|
|
||||||
|
# User-specific files
|
||||||
|
*.suo
|
||||||
|
*.user
|
||||||
|
*.userosscache
|
||||||
|
*.sln.docstates
|
||||||
|
|
||||||
|
# User-specific files (MonoDevelop/Xamarin Studio)
|
||||||
|
*.userprefs
|
||||||
|
|
||||||
|
# Build results
|
||||||
|
[Dd]ebug/
|
||||||
|
[Dd]ebugPublic/
|
||||||
|
[Rr]elease/
|
||||||
|
[Rr]eleases/
|
||||||
|
x64/
|
||||||
|
x86/
|
||||||
|
bld/
|
||||||
|
[Bb]in/
|
||||||
|
[Oo]bj/
|
||||||
|
[Ll]og/
|
||||||
|
|
||||||
|
# Visual Studio 2015 cache/options directory
|
||||||
|
.vs/
|
||||||
|
# Uncomment if you have tasks that create the project's static files in wwwroot
|
||||||
|
#wwwroot/
|
||||||
|
|
||||||
|
# MSTest test Results
|
||||||
|
[Tt]est[Rr]esult*/
|
||||||
|
[Bb]uild[Ll]og.*
|
||||||
|
|
||||||
|
# NUNIT
|
||||||
|
*.VisualState.xml
|
||||||
|
TestResult.xml
|
||||||
|
|
||||||
|
# Build Results of an ATL Project
|
||||||
|
[Dd]ebugPS/
|
||||||
|
[Rr]eleasePS/
|
||||||
|
dlldata.c
|
||||||
|
|
||||||
|
# DNX
|
||||||
|
project.lock.json
|
||||||
|
project.fragment.lock.json
|
||||||
|
artifacts/
|
||||||
|
|
||||||
|
*_i.c
|
||||||
|
*_p.c
|
||||||
|
*_i.h
|
||||||
|
*.ilk
|
||||||
|
*.meta
|
||||||
|
*.obj
|
||||||
|
*.pch
|
||||||
|
*.pdb
|
||||||
|
*.pgc
|
||||||
|
*.pgd
|
||||||
|
*.rsp
|
||||||
|
*.sbr
|
||||||
|
*.tlb
|
||||||
|
*.tli
|
||||||
|
*.tlh
|
||||||
|
*.tmp
|
||||||
|
*.tmp_proj
|
||||||
|
*.log
|
||||||
|
*.vspscc
|
||||||
|
*.vssscc
|
||||||
|
.builds
|
||||||
|
*.pidb
|
||||||
|
*.svclog
|
||||||
|
*.scc
|
||||||
|
|
||||||
|
# Chutzpah Test files
|
||||||
|
_Chutzpah*
|
||||||
|
|
||||||
|
# Visual C++ cache files
|
||||||
|
ipch/
|
||||||
|
*.aps
|
||||||
|
*.ncb
|
||||||
|
*.opendb
|
||||||
|
*.opensdf
|
||||||
|
*.sdf
|
||||||
|
*.cachefile
|
||||||
|
*.VC.db
|
||||||
|
*.VC.VC.opendb
|
||||||
|
|
||||||
|
# Visual Studio profiler
|
||||||
|
*.psess
|
||||||
|
*.vsp
|
||||||
|
*.vspx
|
||||||
|
*.sap
|
||||||
|
|
||||||
|
# TFS 2012 Local Workspace
|
||||||
|
$tf/
|
||||||
|
|
||||||
|
# Guidance Automation Toolkit
|
||||||
|
*.gpState
|
||||||
|
|
||||||
|
# ReSharper is a .NET coding add-in
|
||||||
|
_ReSharper*/
|
||||||
|
*.[Rr]e[Ss]harper
|
||||||
|
*.DotSettings.user
|
||||||
|
|
||||||
|
# JustCode is a .NET coding add-in
|
||||||
|
.JustCode
|
||||||
|
|
||||||
|
# TeamCity is a build add-in
|
||||||
|
_TeamCity*
|
||||||
|
|
||||||
|
# DotCover is a Code Coverage Tool
|
||||||
|
*.dotCover
|
||||||
|
|
||||||
|
# NCrunch
|
||||||
|
_NCrunch_*
|
||||||
|
.*crunch*.local.xml
|
||||||
|
nCrunchTemp_*
|
||||||
|
|
||||||
|
# MightyMoose
|
||||||
|
*.mm.*
|
||||||
|
AutoTest.Net/
|
||||||
|
|
||||||
|
# Web workbench (sass)
|
||||||
|
.sass-cache/
|
||||||
|
|
||||||
|
# Installshield output folder
|
||||||
|
[Ee]xpress/
|
||||||
|
|
||||||
|
# DocProject is a documentation generator add-in
|
||||||
|
DocProject/buildhelp/
|
||||||
|
DocProject/Help/*.HxT
|
||||||
|
DocProject/Help/*.HxC
|
||||||
|
DocProject/Help/*.hhc
|
||||||
|
DocProject/Help/*.hhk
|
||||||
|
DocProject/Help/*.hhp
|
||||||
|
DocProject/Help/Html2
|
||||||
|
DocProject/Help/html
|
||||||
|
|
||||||
|
# Click-Once directory
|
||||||
|
publish/
|
||||||
|
|
||||||
|
# Publish Web Output
|
||||||
|
*.[Pp]ublish.xml
|
||||||
|
*.azurePubxml
|
||||||
|
# TODO: Comment the next line if you want to checkin your web deploy settings
|
||||||
|
# but database connection strings (with potential passwords) will be unencrypted
|
||||||
|
#*.pubxml
|
||||||
|
*.publishproj
|
||||||
|
|
||||||
|
# Microsoft Azure Web App publish settings. Comment the next line if you want to
|
||||||
|
# checkin your Azure Web App publish settings, but sensitive information contained
|
||||||
|
# in these scripts will be unencrypted
|
||||||
|
PublishScripts/
|
||||||
|
|
||||||
|
# NuGet Packages
|
||||||
|
*.nupkg
|
||||||
|
# The packages folder can be ignored because of Package Restore
|
||||||
|
**/packages/*
|
||||||
|
# except build/, which is used as an MSBuild target.
|
||||||
|
!**/packages/build/
|
||||||
|
# Uncomment if necessary however generally it will be regenerated when needed
|
||||||
|
#!**/packages/repositories.config
|
||||||
|
# NuGet v3's project.json files produces more ignoreable files
|
||||||
|
*.nuget.props
|
||||||
|
*.nuget.targets
|
||||||
|
|
||||||
|
# Microsoft Azure Build Output
|
||||||
|
csx/
|
||||||
|
*.build.csdef
|
||||||
|
|
||||||
|
# Microsoft Azure Emulator
|
||||||
|
ecf/
|
||||||
|
rcf/
|
||||||
|
|
||||||
|
# Windows Store app package directories and files
|
||||||
|
AppPackages/
|
||||||
|
BundleArtifacts/
|
||||||
|
Package.StoreAssociation.xml
|
||||||
|
_pkginfo.txt
|
||||||
|
|
||||||
|
# Visual Studio cache files
|
||||||
|
# files ending in .cache can be ignored
|
||||||
|
*.[Cc]ache
|
||||||
|
# but keep track of directories ending in .cache
|
||||||
|
!*.[Cc]ache/
|
||||||
|
|
||||||
|
# Others
|
||||||
|
ClientBin/
|
||||||
|
~$*
|
||||||
|
*~
|
||||||
|
*.dbmdl
|
||||||
|
*.dbproj.schemaview
|
||||||
|
*.jfm
|
||||||
|
*.pfx
|
||||||
|
*.publishsettings
|
||||||
|
node_modules/
|
||||||
|
orleans.codegen.cs
|
||||||
|
|
||||||
|
# Since there are multiple workflows, uncomment next line to ignore bower_components
|
||||||
|
# (https://github.com/github/gitignore/pull/1529#issuecomment-104372622)
|
||||||
|
#bower_components/
|
||||||
|
|
||||||
|
# RIA/Silverlight projects
|
||||||
|
Generated_Code/
|
||||||
|
|
||||||
|
# Backup & report files from converting an old project file
|
||||||
|
# to a newer Visual Studio version. Backup files are not needed,
|
||||||
|
# because we have git ;-)
|
||||||
|
_UpgradeReport_Files/
|
||||||
|
Backup*/
|
||||||
|
UpgradeLog*.XML
|
||||||
|
UpgradeLog*.htm
|
||||||
|
|
||||||
|
# SQL Server files
|
||||||
|
*.mdf
|
||||||
|
*.ldf
|
||||||
|
|
||||||
|
# Business Intelligence projects
|
||||||
|
*.rdl.data
|
||||||
|
*.bim.layout
|
||||||
|
*.bim_*.settings
|
||||||
|
|
||||||
|
# Microsoft Fakes
|
||||||
|
FakesAssemblies/
|
||||||
|
|
||||||
|
# GhostDoc plugin setting file
|
||||||
|
*.GhostDoc.xml
|
||||||
|
|
||||||
|
# Node.js Tools for Visual Studio
|
||||||
|
.ntvs_analysis.dat
|
||||||
|
|
||||||
|
# Visual Studio 6 build log
|
||||||
|
*.plg
|
||||||
|
|
||||||
|
# Visual Studio 6 workspace options file
|
||||||
|
*.opt
|
||||||
|
|
||||||
|
# Visual Studio LightSwitch build output
|
||||||
|
**/*.HTMLClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/GeneratedArtifacts
|
||||||
|
**/*.DesktopClient/ModelManifest.xml
|
||||||
|
**/*.Server/GeneratedArtifacts
|
||||||
|
**/*.Server/ModelManifest.xml
|
||||||
|
_Pvt_Extensions
|
||||||
|
|
||||||
|
# Paket dependency manager
|
||||||
|
.paket/paket.exe
|
||||||
|
paket-files/
|
||||||
|
|
||||||
|
# FAKE - F# Make
|
||||||
|
.fake/
|
||||||
|
|
||||||
|
# JetBrains Rider
|
||||||
|
.idea/
|
||||||
|
*.sln.iml
|
||||||
|
|
||||||
|
# CodeRush
|
||||||
|
.cr/
|
||||||
|
|
||||||
|
# Python Tools for Visual Studio (PTVS)
|
||||||
|
__pycache__/
|
||||||
|
*.pyc
|
||||||
13
examples/WireMockAzureQueueExample/Function1.cs
Normal file
13
examples/WireMockAzureQueueExample/Function1.cs
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
using Microsoft.Azure.WebJobs;
|
||||||
|
using Microsoft.Extensions.Logging;
|
||||||
|
|
||||||
|
namespace WireMockAzureQueueExample;
|
||||||
|
|
||||||
|
public class Function1
|
||||||
|
{
|
||||||
|
[FunctionName("Function1")]
|
||||||
|
public void Run([QueueTrigger("myqueue-items", Connection = "ConnectionStringToWireMock")]string myQueueItem, ILogger log)
|
||||||
|
{
|
||||||
|
log.LogWarning($"C# Queue trigger function processed: {myQueueItem}");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,9 @@
|
|||||||
|
{
|
||||||
|
"profiles": {
|
||||||
|
"WireMockAzureQueueExample": {
|
||||||
|
"commandName": "Project",
|
||||||
|
"commandLineArgs": "--port 7290",
|
||||||
|
"launchBrowser": false
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,14 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"appInsights1": {
|
||||||
|
"type": "appInsights"
|
||||||
|
},
|
||||||
|
"secrets1": {
|
||||||
|
"type": "secrets"
|
||||||
|
},
|
||||||
|
"storage1": {
|
||||||
|
"type": "storage",
|
||||||
|
"connectionId": "AzureWebJobsStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
{
|
||||||
|
"dependencies": {
|
||||||
|
"appInsights1": {
|
||||||
|
"type": "appInsights.sdk"
|
||||||
|
},
|
||||||
|
"secrets1": {
|
||||||
|
"type": "secrets.user"
|
||||||
|
},
|
||||||
|
"storage1": {
|
||||||
|
"secretStore": null,
|
||||||
|
"resourceId": null,
|
||||||
|
"type": "storage.emulator",
|
||||||
|
"connectionId": "AzureWebJobsStorage"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,25 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
<PropertyGroup>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
||||||
|
<UserSecretsId>bb7d8355-68c4-4f81-8c2d-6cdd80cd7602</UserSecretsId>
|
||||||
|
</PropertyGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
||||||
|
<PackageReference Include="Azure.Storage.Files.Shares" Version="12.12.1" />
|
||||||
|
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
|
||||||
|
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.5" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.0.0" />
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
||||||
|
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
|
||||||
|
</ItemGroup>
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="host.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
<None Update="local.settings.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
</Project>
|
||||||
11
examples/WireMockAzureQueueExample/host.json
Normal file
11
examples/WireMockAzureQueueExample/host.json
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
{
|
||||||
|
"version": "2.0",
|
||||||
|
"logging": {
|
||||||
|
"applicationInsights": {
|
||||||
|
"samplingSettings": {
|
||||||
|
"isEnabled": true,
|
||||||
|
"excludedTypes": "Request"
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
7
examples/WireMockAzureQueueExample/local.settings.json
Normal file
7
examples/WireMockAzureQueueExample/local.settings.json
Normal file
@@ -0,0 +1,7 @@
|
|||||||
|
{
|
||||||
|
"IsEncrypted": false,
|
||||||
|
"Values": {
|
||||||
|
"AzureWebJobsStorage": "UseDevelopmentStorage=true",
|
||||||
|
"FUNCTIONS_WORKER_RUNTIME": "dotnet"
|
||||||
|
}
|
||||||
|
}
|
||||||
40
examples/WireMockAzureQueueProxy/Program.cs
Normal file
40
examples/WireMockAzureQueueProxy/Program.cs
Normal file
@@ -0,0 +1,40 @@
|
|||||||
|
using Newtonsoft.Json;
|
||||||
|
using WireMock.Logging;
|
||||||
|
using WireMock.Server;
|
||||||
|
using WireMock.Settings;
|
||||||
|
|
||||||
|
namespace WireMockAzureQueueProxy;
|
||||||
|
|
||||||
|
static class Program
|
||||||
|
{
|
||||||
|
static void Main(params string[] args)
|
||||||
|
{
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Logger = new WireMockConsoleLogger(),
|
||||||
|
Urls = new[] { "http://localhost:20001/" },
|
||||||
|
StartAdminInterface = false,
|
||||||
|
ReadStaticMappings = true,
|
||||||
|
WatchStaticMappings = true,
|
||||||
|
WatchStaticMappingsInSubdirectories = true,
|
||||||
|
//ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||||
|
//{
|
||||||
|
// Url = "http://127.0.0.1:10001",
|
||||||
|
// SaveMapping = true,
|
||||||
|
// SaveMappingToFile = true,
|
||||||
|
// AppendGuidToSavedMappingFile = true
|
||||||
|
//}
|
||||||
|
});
|
||||||
|
|
||||||
|
System.Console.WriteLine("Press any key to stop the server");
|
||||||
|
System.Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
|
||||||
|
System.Console.WriteLine("Displaying all requests");
|
||||||
|
var allRequests = server.LogEntries;
|
||||||
|
System.Console.WriteLine(JsonConvert.SerializeObject(allRequests, Formatting.Indented));
|
||||||
|
|
||||||
|
System.Console.WriteLine("Press any key to quit");
|
||||||
|
System.Console.ReadKey();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net6.0</TargetFramework>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<None Update="__admin\mappings\*.json">
|
||||||
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
|
</None>
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -0,0 +1,44 @@
|
|||||||
|
{
|
||||||
|
"Guid": "b4a2ff02-fb7f-4496-8c04-9aafc4f5f8f7",
|
||||||
|
"Title": "Proxy Mapping for DELETE /devstoreaccount1/myqueue-items/messages/41b2aadc-d6ea-4c3c-ae20-2ae72eb08d88",
|
||||||
|
"Description": "Proxy Mapping for DELETE /devstoreaccount1/myqueue-items/messages/41b2aadc-d6ea-4c3c-ae20-2ae72eb08d88",
|
||||||
|
"Request": {
|
||||||
|
"Path": {
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "/devstoreaccount1/myqueue-items/messages/41b2aadc-d6ea-4c3c-ae20-2ae72eb08d88",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Methods": [
|
||||||
|
"DELETE"
|
||||||
|
],
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "popreceipt",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "*",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 204,
|
||||||
|
"Headers": {
|
||||||
|
"Server": "Azurite-Queue/3.19.0",
|
||||||
|
"x-ms-client-request-id": "{{request.headers.x-ms-client-request-id}}",
|
||||||
|
"x-ms-request-id": "{{Random Type=\"Guid\"}}",
|
||||||
|
"x-ms-version": "2021-10-04",
|
||||||
|
"Date": "{{DateTime.Now \"ddd, dd MMM yyy HH’:’mm’:’ss ‘GMT’\"}}",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Keep-Alive": "timeout=5"
|
||||||
|
},
|
||||||
|
"UseTransformer": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,60 @@
|
|||||||
|
{
|
||||||
|
"Scenario": "AzureQueue Get Messages",
|
||||||
|
"WhenStateIs": "No more messages",
|
||||||
|
"SetStateTo": "No more messages",
|
||||||
|
"Guid": "4c871968-29ee-472b-a548-170444d4cc3e",
|
||||||
|
"Title": "Proxy Mapping for GET NO MSG /devstoreaccount1/myqueue-items/messages",
|
||||||
|
"Description": "Proxy Mapping for GET NO MSG /devstoreaccount1/myqueue-items/messages",
|
||||||
|
"Request": {
|
||||||
|
"Path": {
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "/devstoreaccount1/myqueue-items/messages",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Methods": [
|
||||||
|
"GET"
|
||||||
|
],
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "numofmessages",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "ExactMatcher",
|
||||||
|
"Pattern": "16",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "visibilitytimeout",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "ExactMatcher",
|
||||||
|
"Pattern": "600",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200,
|
||||||
|
"Body": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><QueueMessagesList/>",
|
||||||
|
"Headers": {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
"Server": "Azurite-Queue/3.19.0",
|
||||||
|
"x-ms-client-request-id": "{{request.headers.x-ms-client-request-id}}",
|
||||||
|
"x-ms-request-id": "{{Random Type=\"Guid\"}}",
|
||||||
|
"x-ms-version": "2021-10-04",
|
||||||
|
"Date": "{{DateTime.Now \"ddd, dd MMM yyy HH’:’mm’:’ss ‘GMT’\"}}",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Keep-Alive": "timeout=5",
|
||||||
|
"Transfer-Encoding": "chunked"
|
||||||
|
},
|
||||||
|
"UseTransformer": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,59 @@
|
|||||||
|
{
|
||||||
|
"Scenario": "AzureQueue Get Messages",
|
||||||
|
"SetStateTo": "No more messages",
|
||||||
|
"Guid": "da9c6799-fbf8-41b6-8933-0df50f821ebb",
|
||||||
|
"Title": "Proxy Mapping for GET /devstoreaccount1/myqueue-items/messages",
|
||||||
|
"Description": "Proxy Mapping for GET /devstoreaccount1/myqueue-items/messages",
|
||||||
|
"Request": {
|
||||||
|
"Path": {
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "/devstoreaccount1/myqueue-items/messages",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Methods": [
|
||||||
|
"GET"
|
||||||
|
],
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "numofmessages",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "*",
|
||||||
|
"IgnoreCase": true
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"Name": "visibilitytimeout",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "*",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200,
|
||||||
|
"Body": "<?xml version=\"1.0\" encoding=\"UTF-8\" standalone=\"yes\"?><QueueMessagesList><QueueMessage><MessageId>41b2aadc-d6ea-4c3c-ae20-2ae72eb08d88</MessageId><InsertionTime>Sat, 29 Oct 2022 07:11:40 GMT</InsertionTime><ExpirationTime>Sat, 31 Dec 2022 07:11:40 GMT</ExpirationTime><PopReceipt>MjlPY3QyMDIyMDc6MTE6NDAyMjU2</PopReceipt><TimeNextVisible>Sat, 29 Oct 2022 07:21:40 GMT</TimeNextVisible><DequeueCount>1</DequeueCount><MessageText>c3RlZg==</MessageText></QueueMessage></QueueMessagesList>",
|
||||||
|
"Headers": {
|
||||||
|
"Content-Type": "application/xml",
|
||||||
|
"Server": "Azurite-Queue/3.19.0",
|
||||||
|
"x-ms-client-request-id": "{{request.headers.x-ms-client-request-id}}",
|
||||||
|
"x-ms-request-id": "{{Random Type=\"Guid\"}}",
|
||||||
|
"x-ms-version": "2021-10-04",
|
||||||
|
"Date": "{{DateTime.Now \"ddd, dd MMM yyy HH’:’mm’:’ss ‘GMT’\"}}",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Keep-Alive": "timeout=5",
|
||||||
|
"Transfer-Encoding": "chunked"
|
||||||
|
},
|
||||||
|
"UseTransformer": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
{
|
||||||
|
"Guid": "17c7a389-98e1-4383-975d-54c82d1e3860",
|
||||||
|
"Title": "Proxy Mapping for HEAD /devstoreaccount1/myqueue-items",
|
||||||
|
"Description": "Proxy Mapping for HEAD /devstoreaccount1/myqueue-items",
|
||||||
|
"Request": {
|
||||||
|
"Path": {
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "WildcardMatcher",
|
||||||
|
"Pattern": "/devstoreaccount1/myqueue-items",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Methods": [
|
||||||
|
"HEAD"
|
||||||
|
],
|
||||||
|
"Params": [
|
||||||
|
{
|
||||||
|
"Name": "comp",
|
||||||
|
"Matchers": [
|
||||||
|
{
|
||||||
|
"Name": "ExactMatcher",
|
||||||
|
"Pattern": "metadata",
|
||||||
|
"IgnoreCase": false
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
]
|
||||||
|
},
|
||||||
|
"Response": {
|
||||||
|
"StatusCode": 200,
|
||||||
|
"Body": "",
|
||||||
|
"Headers": {
|
||||||
|
"Server": "Azurite-Queue/3.19.0",
|
||||||
|
"x-ms-client-request-id": "{{request.headers.x-ms-client-request-id}}",
|
||||||
|
"x-ms-approximate-messages-count": "0",
|
||||||
|
"x-ms-request-id": "{{Random Type=\"Guid\"}}",
|
||||||
|
"x-ms-version": "2021-10-04",
|
||||||
|
"Date": "{{DateTime.Now \"ddd, dd MMM yyy HH’:’mm’:’ss ‘GMT’\"}}",
|
||||||
|
"Connection": "keep-alive",
|
||||||
|
"Keep-Alive": "timeout=5"
|
||||||
|
},
|
||||||
|
"UseTransformer": true
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
namespace WireMock.Admin.Settings
|
namespace WireMock.Admin.Settings;
|
||||||
|
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class ProxyAndRecordSettingsModel
|
||||||
{
|
{
|
||||||
[FluentBuilder.AutoGenerateBuilder]
|
|
||||||
public class ProxyAndRecordSettingsModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The clientCertificate thumbprint or subject name fragment to use.
|
/// The clientCertificate thumbprint or subject name fragment to use.
|
||||||
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
/// Example thumbprint : "D2DBF135A8D06ACCD0E1FAD9BFB28678DF7A9818". Example subject name: "www.google.com""
|
||||||
@@ -63,5 +63,9 @@ namespace WireMock.Admin.Settings
|
|||||||
/// Default value is false.
|
/// Default value is false.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseDefinedRequestMatchers { get; set; }
|
public bool UseDefinedRequestMatchers { get; set; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Append an unique GUID to the filename from the saved mapping file.
|
||||||
|
/// </summary>
|
||||||
|
public bool AppendGuidToSavedMappingFile { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,15 @@
|
|||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Admin.Settings
|
namespace WireMock.Admin.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Settings
|
||||||
|
/// </summary>
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class SettingsModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Settings
|
|
||||||
/// </summary>
|
|
||||||
[FluentBuilder.AutoGenerateBuilder]
|
|
||||||
public class SettingsModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the global delay in milliseconds.
|
/// Gets or sets the global delay in milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -78,5 +79,21 @@ namespace WireMock.Admin.Settings
|
|||||||
/// The proxy and record settings.
|
/// The proxy and record settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public ProxyAndRecordSettingsModel? ProxyAndRecordSettings { get; set; }
|
public ProxyAndRecordSettingsModel? ProxyAndRecordSettings { get; set; }
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines on which scheme (http/https) to host. (This overrides the <c>UseSSL</c> value).
|
||||||
|
/// </summary>
|
||||||
|
public HostingScheme? HostingScheme { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||||
|
/// </summary>
|
||||||
|
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See <seealso cref="QueryParameterMultipleValueSupport"/>.
|
||||||
|
///
|
||||||
|
/// Default value = "All".
|
||||||
|
/// </summary>
|
||||||
|
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
namespace WireMock.Http;
|
namespace WireMock.Constants;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
/// https://developer.mozilla.org/en-US/docs/Web/HTTP/Methods
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class HttpRequestMethods
|
public static class HttpRequestMethod
|
||||||
{
|
{
|
||||||
public const string CONNECT = "CONNECT";
|
public const string CONNECT = "CONNECT";
|
||||||
public const string DELETE = "DELETE";
|
public const string DELETE = "DELETE";
|
||||||
@@ -28,7 +28,7 @@ public interface IRequestMessage
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ProxyUrl (if a proxy is used).
|
/// The ProxyUrl (if a proxy is used).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string ProxyUrl { get; set; }
|
string? ProxyUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the DateTime.
|
/// Gets the DateTime.
|
||||||
|
|||||||
@@ -1,6 +1,4 @@
|
|||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Util;
|
namespace WireMock.Util;
|
||||||
@@ -59,4 +57,9 @@ public interface IBodyData
|
|||||||
/// The body encoding.
|
/// The body encoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Encoding? Encoding { get; set; }
|
Encoding? Encoding { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines if this BodyData is the result of a dynamically created response-string. (
|
||||||
|
/// </summary>
|
||||||
|
public string? IsFuncUsed { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers.Request;
|
|
||||||
|
|
||||||
namespace WireMock.Server
|
namespace WireMock.Server
|
||||||
{
|
{
|
||||||
@@ -144,6 +142,11 @@ namespace WireMock.Server
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
void ResetScenarios();
|
void ResetScenarios();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Resets a specific Scenario by the name.
|
||||||
|
/// </summary>
|
||||||
|
bool ResetScenario(string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the LogEntries.
|
/// Resets the LogEntries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -0,0 +1,28 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
[Flags]
|
||||||
|
public enum QueryParameterMultipleValueSupport
|
||||||
|
{
|
||||||
|
// Support none
|
||||||
|
None = 0x0,
|
||||||
|
|
||||||
|
// Support "&" as multi-value-separator --> "key=value&key=anotherValue"
|
||||||
|
Ampersand = 0x1,
|
||||||
|
|
||||||
|
// Support ";" as multi-value-separator --> "key=value;key=anotherValue"
|
||||||
|
SemiColon = 0x2,
|
||||||
|
|
||||||
|
// Support "," as multi-value-separator --> "key=1,2"
|
||||||
|
Comma = 0x4,
|
||||||
|
|
||||||
|
// Support "&" and ";" as multi-value-separator --> "key=value&key=anotherValue" and also "key=value;key=anotherValue"
|
||||||
|
AmpersandAndSemiColon = Ampersand | SemiColon,
|
||||||
|
|
||||||
|
// Support "&" and ";" as multi-value-separator
|
||||||
|
NoComma = AmpersandAndSemiColon,
|
||||||
|
|
||||||
|
// Support all multi-value-separators ("&" and ";" and ",")
|
||||||
|
All = Ampersand | SemiColon | Comma
|
||||||
|
}
|
||||||
@@ -4,6 +4,7 @@ using System.Collections.Generic;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using FluentAssertions;
|
using FluentAssertions;
|
||||||
using FluentAssertions.Execution;
|
using FluentAssertions.Execution;
|
||||||
|
using WireMock.Constants;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
@@ -12,9 +13,10 @@ namespace WireMock.FluentAssertions;
|
|||||||
|
|
||||||
public class WireMockAssertions
|
public class WireMockAssertions
|
||||||
{
|
{
|
||||||
|
private const string Any = "*";
|
||||||
private readonly int? _callsCount;
|
private readonly int? _callsCount;
|
||||||
private IReadOnlyList<IRequestMessage> _requestMessages;
|
private IReadOnlyList<IRequestMessage> _requestMessages;
|
||||||
private IReadOnlyList<KeyValuePair<string, WireMockList<string>>> _headers;
|
private readonly IReadOnlyList<KeyValuePair<string, WireMockList<string>>> _headers;
|
||||||
|
|
||||||
public WireMockAssertions(IWireMockServer subject, int? callsCount)
|
public WireMockAssertions(IWireMockServer subject, int? callsCount)
|
||||||
{
|
{
|
||||||
@@ -27,12 +29,13 @@ public class WireMockAssertions
|
|||||||
public AndWhichConstraint<WireMockAssertions, string> AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
|
public AndWhichConstraint<WireMockAssertions, string> AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
|
||||||
{
|
{
|
||||||
Func<IRequestMessage, bool> predicate = request => string.Equals(request.AbsoluteUrl, absoluteUrl, StringComparison.OrdinalIgnoreCase);
|
Func<IRequestMessage, bool> predicate = request => string.Equals(request.AbsoluteUrl, absoluteUrl, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var (filter, condition) = BuildFilterAndCondition(predicate);
|
var (filter, condition) = BuildFilterAndCondition(predicate);
|
||||||
|
|
||||||
Execute.Assertion
|
Execute.Assertion
|
||||||
.BecauseOf(because, becauseArgs)
|
.BecauseOf(because, becauseArgs)
|
||||||
.Given(() => _requestMessages)
|
.Given(() => _requestMessages)
|
||||||
.ForCondition(requests => requests.Any())
|
.ForCondition(requests => _callsCount == 0 || requests.Any())
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but no calls were made.",
|
"Expected {context:wiremockserver} to have been called at address matching the absolute url {0}{reason}, but no calls were made.",
|
||||||
absoluteUrl
|
absoluteUrl
|
||||||
@@ -53,15 +56,17 @@ public class WireMockAssertions
|
|||||||
public AndWhichConstraint<WireMockAssertions, string> AtUrl(string url, string because = "", params object[] becauseArgs)
|
public AndWhichConstraint<WireMockAssertions, string> AtUrl(string url, string because = "", params object[] becauseArgs)
|
||||||
{
|
{
|
||||||
Func<IRequestMessage, bool> predicate = request => string.Equals(request.Url, url, StringComparison.OrdinalIgnoreCase);
|
Func<IRequestMessage, bool> predicate = request => string.Equals(request.Url, url, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var (filter, condition) = BuildFilterAndCondition(predicate);
|
var (filter, condition) = BuildFilterAndCondition(predicate);
|
||||||
|
|
||||||
Execute.Assertion
|
Execute.Assertion
|
||||||
.BecauseOf(because, becauseArgs)
|
.BecauseOf(because, becauseArgs)
|
||||||
.Given(() => _requestMessages)
|
.Given(() => _requestMessages)
|
||||||
.ForCondition(requests => requests.Any())
|
.ForCondition(requests => _callsCount == 0 || requests.Any())
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
|
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
|
||||||
url)
|
url
|
||||||
|
)
|
||||||
.Then
|
.Then
|
||||||
.ForCondition(condition)
|
.ForCondition(condition)
|
||||||
.FailWith(
|
.FailWith(
|
||||||
@@ -79,12 +84,13 @@ public class WireMockAssertions
|
|||||||
public AndWhichConstraint<WireMockAssertions, string> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs)
|
public AndWhichConstraint<WireMockAssertions, string> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs)
|
||||||
{
|
{
|
||||||
Func<IRequestMessage, bool> predicate = request => string.Equals(request.ProxyUrl, proxyUrl, StringComparison.OrdinalIgnoreCase);
|
Func<IRequestMessage, bool> predicate = request => string.Equals(request.ProxyUrl, proxyUrl, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var (filter, condition) = BuildFilterAndCondition(predicate);
|
var (filter, condition) = BuildFilterAndCondition(predicate);
|
||||||
|
|
||||||
Execute.Assertion
|
Execute.Assertion
|
||||||
.BecauseOf(because, becauseArgs)
|
.BecauseOf(because, becauseArgs)
|
||||||
.Given(() => _requestMessages)
|
.Given(() => _requestMessages)
|
||||||
.ForCondition(requests => requests.Any())
|
.ForCondition(requests => _callsCount == 0 || requests.Any())
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but no calls were made.",
|
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but no calls were made.",
|
||||||
proxyUrl
|
proxyUrl
|
||||||
@@ -94,8 +100,7 @@ public class WireMockAssertions
|
|||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
|
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
|
||||||
_ => proxyUrl,
|
_ => proxyUrl,
|
||||||
requests => requests
|
requests => requests.Select(request => request.ProxyUrl)
|
||||||
.Select(request => request.ProxyUrl)
|
|
||||||
);
|
);
|
||||||
|
|
||||||
_requestMessages = filter(_requestMessages).ToList();
|
_requestMessages = filter(_requestMessages).ToList();
|
||||||
@@ -107,23 +112,23 @@ public class WireMockAssertions
|
|||||||
public AndWhichConstraint<WireMockAssertions, string> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
|
public AndWhichConstraint<WireMockAssertions, string> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
|
||||||
{
|
{
|
||||||
Func<IRequestMessage, bool> predicate = request => string.Equals(request.ClientIP, clientIP, StringComparison.OrdinalIgnoreCase);
|
Func<IRequestMessage, bool> predicate = request => string.Equals(request.ClientIP, clientIP, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var (filter, condition) = BuildFilterAndCondition(predicate);
|
var (filter, condition) = BuildFilterAndCondition(predicate);
|
||||||
|
|
||||||
Execute.Assertion
|
Execute.Assertion
|
||||||
.BecauseOf(because, becauseArgs)
|
.BecauseOf(because, becauseArgs)
|
||||||
.Given(() => _requestMessages)
|
.Given(() => _requestMessages)
|
||||||
.ForCondition(requests => requests.Any())
|
.ForCondition(requests => _callsCount == 0 || requests.Any())
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
|
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
|
||||||
clientIP)
|
clientIP
|
||||||
.Then
|
|
||||||
.ForCondition(requests =>
|
|
||||||
(_callsCount == null && requests.Any(req => req.ClientIP == clientIP)) ||
|
|
||||||
(_callsCount == requests.Count(req => req.ClientIP == clientIP))
|
|
||||||
)
|
)
|
||||||
|
.Then
|
||||||
|
.ForCondition(condition)
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
|
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
|
||||||
_ => clientIP, requests => requests.Select(request => request.ClientIP));
|
_ => clientIP, requests => requests.Select(request => request.ClientIP)
|
||||||
|
);
|
||||||
|
|
||||||
_requestMessages = filter(_requestMessages).ToList();
|
_requestMessages = filter(_requestMessages).ToList();
|
||||||
|
|
||||||
@@ -165,50 +170,57 @@ public class WireMockAssertions
|
|||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingConnect(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingConnect(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("CONNECT", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.CONNECT, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingDelete(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingDelete(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("DELETE", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.DELETE, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingGet(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingGet(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("GET", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.GET, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingHead(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingHead(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("HEAD", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.HEAD, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingOptions(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingOptions(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("OPTIONS", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.OPTIONS, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingPost(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingPost(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("POST", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.POST, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingPatch(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingPatch(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("PATCH", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.PATCH, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingPut(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingPut(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("PUT", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.PUT, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingTrace(string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingTrace(string because = "", params object[] becauseArgs)
|
||||||
=> UsingMethod("TRACE", because, becauseArgs);
|
=> UsingMethod(HttpRequestMethod.TRACE, because, becauseArgs);
|
||||||
|
|
||||||
|
[CustomAssertion]
|
||||||
|
public AndConstraint<WireMockAssertions> UsingAnyMethod(string because = "", params object[] becauseArgs)
|
||||||
|
=> UsingMethod(Any, because, becauseArgs);
|
||||||
|
|
||||||
[CustomAssertion]
|
[CustomAssertion]
|
||||||
public AndConstraint<WireMockAssertions> UsingMethod(string method, string because = "", params object[] becauseArgs)
|
public AndConstraint<WireMockAssertions> UsingMethod(string method, string because = "", params object[] becauseArgs)
|
||||||
{
|
{
|
||||||
Func<IRequestMessage, bool> predicate = request => string.Equals(request.Method, method, StringComparison.OrdinalIgnoreCase);
|
var any = method == Any;
|
||||||
|
Func<IRequestMessage, bool> predicate = request => (any && !string.IsNullOrEmpty(request.Method)) ||
|
||||||
|
string.Equals(request.Method, method, StringComparison.OrdinalIgnoreCase);
|
||||||
|
|
||||||
var (filter, condition) = BuildFilterAndCondition(predicate);
|
var (filter, condition) = BuildFilterAndCondition(predicate);
|
||||||
|
|
||||||
Execute.Assertion
|
Execute.Assertion
|
||||||
.BecauseOf(because, becauseArgs)
|
.BecauseOf(because, becauseArgs)
|
||||||
.Given(() => _requestMessages)
|
.Given(() => _requestMessages)
|
||||||
.ForCondition(requests => requests.Any())
|
.ForCondition(requests => _callsCount == 0 || requests.Any())
|
||||||
.FailWith(
|
.FailWith(
|
||||||
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but no calls were made.",
|
"Expected {context:wiremockserver} to have been called using method {0}{reason}, but no calls were made.",
|
||||||
method
|
method
|
||||||
@@ -230,12 +242,6 @@ public class WireMockAssertions
|
|||||||
{
|
{
|
||||||
Func<IReadOnlyList<IRequestMessage>, IReadOnlyList<IRequestMessage>> filter = requests => requests.Where(predicate).ToList();
|
Func<IReadOnlyList<IRequestMessage>, IReadOnlyList<IRequestMessage>> filter = requests => requests.Where(predicate).ToList();
|
||||||
|
|
||||||
return
|
return (filter, requests => (_callsCount is null && filter(requests).Any()) || _callsCount == filter(requests).Count);
|
||||||
(
|
|
||||||
filter,
|
|
||||||
requests =>
|
|
||||||
(_callsCount == null && filter(_requestMessages).Any()) ||
|
|
||||||
(_callsCount == filter(_requestMessages).Count())
|
|
||||||
);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
#if NET46 || NETSTANDARD2_0
|
#if NET46 || NETSTANDARD2_0
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Extensions
|
namespace WireMock.Net.OpenApiParser.Extensions;
|
||||||
|
|
||||||
|
internal static class DictionaryExtensions
|
||||||
{
|
{
|
||||||
internal static class DictionaryExtensions
|
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue>? dictionary, TKey key, TValue value)
|
||||||
{
|
|
||||||
public static bool TryAdd<TKey, TValue>(this Dictionary<TKey, TValue> dictionary, TKey key, TValue value)
|
|
||||||
{
|
{
|
||||||
if (dictionary is null || dictionary.ContainsKey(key))
|
if (dictionary is null || dictionary.ContainsKey(key))
|
||||||
{
|
{
|
||||||
@@ -16,6 +16,5 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
using Microsoft.OpenApi.Any;
|
using Microsoft.OpenApi.Any;
|
||||||
using Microsoft.OpenApi.Interfaces;
|
using Microsoft.OpenApi.Interfaces;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using WireMock.Net.OpenApiParser.Types;
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Extensions
|
namespace WireMock.Net.OpenApiParser.Extensions;
|
||||||
|
|
||||||
|
internal static class OpenApiSchemaExtensions
|
||||||
{
|
{
|
||||||
internal static class OpenApiSchemaExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://stackoverflow.com/questions/48111459/how-to-define-a-property-that-can-be-string-or-null-in-openapi-swagger
|
/// https://stackoverflow.com/questions/48111459/how-to-define-a-property-that-can-be-string-or-null-in-openapi-swagger
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -23,7 +23,7 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchemaType GetSchemaType(this OpenApiSchema schema)
|
public static SchemaType GetSchemaType(this OpenApiSchema? schema)
|
||||||
{
|
{
|
||||||
switch (schema?.Type)
|
switch (schema?.Type)
|
||||||
{
|
{
|
||||||
@@ -53,7 +53,7 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public static SchemaFormat GetSchemaFormat(this OpenApiSchema schema)
|
public static SchemaFormat GetSchemaFormat(this OpenApiSchema? schema)
|
||||||
{
|
{
|
||||||
switch (schema?.Format)
|
switch (schema?.Format)
|
||||||
{
|
{
|
||||||
@@ -88,5 +88,4 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
return SchemaFormat.Undefined;
|
return SchemaFormat.Undefined;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,21 +1,19 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Runtime.InteropServices.ComTypes;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.OpenApi.Readers;
|
using Microsoft.OpenApi.Readers;
|
||||||
using SharpYaml.Model;
|
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Net.OpenApiParser.Settings;
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Extensions
|
namespace WireMock.Net.OpenApiParser.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Some extension methods for <see cref="IWireMockServer"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class WireMockServerExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Some extension methods for <see cref="IWireMockServer"/>.
|
|
||||||
/// </summary>
|
|
||||||
public static class WireMockServerExtensions
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register the mappings via an OpenAPI (swagger) V2 or V3 file.
|
/// Register the mappings via an OpenAPI (swagger) V2 or V3 file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -25,7 +23,7 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiFile(this IWireMockServer server, string path, out OpenApiDiagnostic diagnostic)
|
public static IWireMockServer WithMappingFromOpenApiFile(this IWireMockServer server, string path, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return WithMappingFromOpenApiFile(server, path, null, out diagnostic);
|
return WithMappingFromOpenApiFile(server, path, new WireMockOpenApiParserSettings(), out diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -55,7 +53,7 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiStream(this IWireMockServer server, Stream stream, out OpenApiDiagnostic diagnostic)
|
public static IWireMockServer WithMappingFromOpenApiStream(this IWireMockServer server, Stream stream, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return WithMappingFromOpenApiStream(server, stream, null, out diagnostic);
|
return WithMappingFromOpenApiStream(server, stream, new WireMockOpenApiParserSettings(), out diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -68,9 +66,9 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiStream(this IWireMockServer server, Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
public static IWireMockServer WithMappingFromOpenApiStream(this IWireMockServer server, Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
Guard.NotNull(server, nameof(server));
|
Guard.NotNull(server);
|
||||||
Guard.NotNull(stream, nameof(stream));
|
Guard.NotNull(stream);
|
||||||
Guard.NotNull(settings, nameof(settings));
|
Guard.NotNull(settings);
|
||||||
|
|
||||||
var mappings = new WireMockOpenApiParser().FromStream(stream, settings, out diagnostic);
|
var mappings = new WireMockOpenApiParser().FromStream(stream, settings, out diagnostic);
|
||||||
|
|
||||||
@@ -84,14 +82,13 @@ namespace WireMock.Net.OpenApiParser.Extensions
|
|||||||
/// <param name="document">The OpenAPI document to use as mappings.</param>
|
/// <param name="document">The OpenAPI document to use as mappings.</param>
|
||||||
/// <param name="settings">Additional settings [optional]</param>
|
/// <param name="settings">Additional settings [optional]</param>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiDocument(this IWireMockServer server, OpenApiDocument document, WireMockOpenApiParserSettings settings = null)
|
public static IWireMockServer WithMappingFromOpenApiDocument(this IWireMockServer server, OpenApiDocument document, WireMockOpenApiParserSettings settings)
|
||||||
{
|
{
|
||||||
Guard.NotNull(server, nameof(server));
|
Guard.NotNull(server);
|
||||||
Guard.NotNull(document, nameof(document));
|
Guard.NotNull(document);
|
||||||
|
|
||||||
var mappings = new WireMockOpenApiParser().FromDocument(document, settings);
|
var mappings = new WireMockOpenApiParser().FromDocument(document, settings);
|
||||||
|
|
||||||
return server.WithMapping(mappings.ToArray());
|
return server.WithMapping(mappings.ToArray());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.OpenApi.Readers;
|
using Microsoft.OpenApi.Readers;
|
||||||
@@ -35,7 +35,7 @@ namespace WireMock.Net.OpenApiParser
|
|||||||
/// <param name="document">The source OpenApiDocument</param>
|
/// <param name="document">The source OpenApiDocument</param>
|
||||||
/// <param name="settings">Additional settings [optional]</param>
|
/// <param name="settings">Additional settings [optional]</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <returns>MappingModel</returns>
|
||||||
IEnumerable<MappingModel> FromDocument(OpenApiDocument document, WireMockOpenApiParserSettings settings = null);
|
IEnumerable<MappingModel> FromDocument(OpenApiDocument document, WireMockOpenApiParserSettings? settings = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from a <seealso cref="Stream"/>.
|
/// Generate <see cref="IEnumerable{MappingModel}"/> from a <seealso cref="Stream"/>.
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using Microsoft.OpenApi;
|
using Microsoft.OpenApi;
|
||||||
@@ -15,10 +16,10 @@ using WireMock.Net.OpenApiParser.Settings;
|
|||||||
using WireMock.Net.OpenApiParser.Types;
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
using WireMock.Net.OpenApiParser.Utils;
|
using WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Mappers
|
namespace WireMock.Net.OpenApiParser.Mappers;
|
||||||
|
|
||||||
|
internal class OpenApiPathsMapper
|
||||||
{
|
{
|
||||||
internal class OpenApiPathsMapper
|
|
||||||
{
|
|
||||||
private const string HeaderContentType = "Content-Type";
|
private const string HeaderContentType = "Content-Type";
|
||||||
|
|
||||||
private readonly WireMockOpenApiParserSettings _settings;
|
private readonly WireMockOpenApiParserSettings _settings;
|
||||||
@@ -26,7 +27,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
|
|
||||||
public OpenApiPathsMapper(WireMockOpenApiParserSettings settings)
|
public OpenApiPathsMapper(WireMockOpenApiParserSettings settings)
|
||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings, nameof(settings));
|
_settings = Guard.NotNull(settings);
|
||||||
_exampleValueGenerator = new ExampleValueGenerator(settings);
|
_exampleValueGenerator = new ExampleValueGenerator(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -53,7 +54,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
|
|
||||||
var response = operation.Responses.FirstOrDefault();
|
var response = operation.Responses.FirstOrDefault();
|
||||||
|
|
||||||
TryGetContent(response.Value?.Content, out OpenApiMediaType responseContent, out string responseContentType);
|
TryGetContent(response.Value?.Content, out OpenApiMediaType? responseContent, out string? responseContentType);
|
||||||
var responseSchema = response.Value?.Content?.FirstOrDefault().Value?.Schema;
|
var responseSchema = response.Value?.Content?.FirstOrDefault().Value?.Schema;
|
||||||
var responseExample = responseContent?.Example;
|
var responseExample = responseContent?.Example;
|
||||||
var responseSchemaExample = responseContent?.Schema?.Example;
|
var responseSchemaExample = responseContent?.Schema?.Example;
|
||||||
@@ -66,10 +67,10 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
if (operation.RequestBody != null && operation.RequestBody.Content != null && operation.RequestBody.Required)
|
if (operation.RequestBody != null && operation.RequestBody.Content != null && operation.RequestBody.Required)
|
||||||
{
|
{
|
||||||
var request = operation.RequestBody.Content;
|
var request = operation.RequestBody.Content;
|
||||||
TryGetContent(request, out OpenApiMediaType requestContent, out string requestContentType);
|
TryGetContent(request, out OpenApiMediaType? requestContent, out _);
|
||||||
|
|
||||||
var requestBodySchema = operation.RequestBody.Content.First().Value?.Schema;
|
var requestBodySchema = operation.RequestBody.Content.First().Value?.Schema;
|
||||||
var requestBodyExample = requestContent.Example;
|
var requestBodyExample = requestContent!.Example;
|
||||||
var requestBodySchemaExample = requestContent.Schema?.Example;
|
var requestBodySchemaExample = requestContent.Schema?.Example;
|
||||||
|
|
||||||
var requestBodyMapped = requestBodyExample != null ? MapOpenApiAnyToJToken(requestBodyExample) :
|
var requestBodyMapped = requestBodyExample != null ? MapOpenApiAnyToJToken(requestBodyExample) :
|
||||||
@@ -104,7 +105,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private BodyModel MapRequestBody(object requestBody)
|
private BodyModel? MapRequestBody(object? requestBody)
|
||||||
{
|
{
|
||||||
if (requestBody == null)
|
if (requestBody == null)
|
||||||
{
|
{
|
||||||
@@ -122,7 +123,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetContent(IDictionary<string, OpenApiMediaType> contents, out OpenApiMediaType openApiMediaType, out string contentType)
|
private bool TryGetContent(IDictionary<string, OpenApiMediaType>? contents, [NotNullWhen(true)] out OpenApiMediaType? openApiMediaType, [NotNullWhen(true)] out string? contentType)
|
||||||
{
|
{
|
||||||
openApiMediaType = null;
|
openApiMediaType = null;
|
||||||
contentType = null;
|
contentType = null;
|
||||||
@@ -147,7 +148,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
private object MapSchemaToObject(OpenApiSchema schema, string name = null)
|
private object? MapSchemaToObject(OpenApiSchema? schema, string? name = null)
|
||||||
{
|
{
|
||||||
if (schema == null)
|
if (schema == null)
|
||||||
{
|
{
|
||||||
@@ -203,6 +204,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
{
|
{
|
||||||
propertyAsJObject.Add(MapPropertyAsJObject(schemaProperty.Value, schemaProperty.Key));
|
propertyAsJObject.Add(MapPropertyAsJObject(schemaProperty.Value, schemaProperty.Key));
|
||||||
}
|
}
|
||||||
|
|
||||||
if (schema.AllOf.Count > 0)
|
if (schema.AllOf.Count > 0)
|
||||||
{
|
{
|
||||||
foreach (var property in schema.AllOf)
|
foreach (var property in schema.AllOf)
|
||||||
@@ -214,7 +216,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return name != null ? new JProperty(name, propertyAsJObject) : (JToken)propertyAsJObject;
|
return name != null ? new JProperty(name, propertyAsJObject) : propertyAsJObject;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return null;
|
return null;
|
||||||
@@ -243,19 +245,15 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
{
|
{
|
||||||
return jp;
|
return jp;
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return new JProperty(key, mapped);
|
return new JProperty(key, mapped);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
// bool propertyIsNullable = openApiSchema.Nullable || (openApiSchema.TryGetXNullable(out bool x) && x);
|
// bool propertyIsNullable = openApiSchema.Nullable || (openApiSchema.TryGetXNullable(out bool x) && x);
|
||||||
return new JProperty(key, _exampleValueGenerator.GetExampleValue(openApiSchema));
|
return new JProperty(key, _exampleValueGenerator.GetExampleValue(openApiSchema));
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter> parameters)
|
private string MapPathWithParameters(string path, IEnumerable<OpenApiParameter>? parameters)
|
||||||
{
|
{
|
||||||
if (parameters == null)
|
if (parameters == null)
|
||||||
{
|
{
|
||||||
@@ -272,7 +270,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MapBasePath(IList<OpenApiServer> servers)
|
private string MapBasePath(IList<OpenApiServer>? servers)
|
||||||
{
|
{
|
||||||
if (servers == null || servers.Count == 0)
|
if (servers == null || servers.Count == 0)
|
||||||
{
|
{
|
||||||
@@ -288,7 +286,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return string.Empty;
|
return string.Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
private JToken MapOpenApiAnyToJToken(IOpenApiAny any)
|
private JToken? MapOpenApiAnyToJToken(IOpenApiAny? any)
|
||||||
{
|
{
|
||||||
if (any == null)
|
if (any == null)
|
||||||
{
|
{
|
||||||
@@ -303,17 +301,15 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
{
|
{
|
||||||
return JArray.Parse(outputString.ToString());
|
return JArray.Parse(outputString.ToString());
|
||||||
}
|
}
|
||||||
else
|
|
||||||
{
|
|
||||||
return JObject.Parse(outputString.ToString());
|
return JObject.Parse(outputString.ToString());
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, object> MapHeaders(string responseContentType, IDictionary<string, OpenApiHeader> headers)
|
private IDictionary<string, object?>? MapHeaders(string responseContentType, IDictionary<string, OpenApiHeader> headers)
|
||||||
{
|
{
|
||||||
var mappedHeaders = headers.ToDictionary(
|
var mappedHeaders = headers.ToDictionary(
|
||||||
item => item.Key,
|
item => item.Key,
|
||||||
item => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern
|
_ => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(responseContentType))
|
if (!string.IsNullOrEmpty(responseContentType))
|
||||||
@@ -324,7 +320,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return mappedHeaders.Keys.Any() ? mappedHeaders : null;
|
return mappedHeaders.Keys.Any() ? mappedHeaders : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IList<ParamModel> MapQueryParameters(IEnumerable<OpenApiParameter> queryParameters)
|
private IList<ParamModel>? MapQueryParameters(IEnumerable<OpenApiParameter> queryParameters)
|
||||||
{
|
{
|
||||||
var list = queryParameters
|
var list = queryParameters
|
||||||
.Where(req => req.Required)
|
.Where(req => req.Required)
|
||||||
@@ -342,7 +338,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return list.Any() ? list : null;
|
return list.Any() ? list : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IList<HeaderModel> MapRequestHeaders(IEnumerable<OpenApiParameter> headers)
|
private IList<HeaderModel>? MapRequestHeaders(IEnumerable<OpenApiParameter> headers)
|
||||||
{
|
{
|
||||||
var list = headers
|
var list = headers
|
||||||
.Where(req => req.Required)
|
.Where(req => req.Required)
|
||||||
@@ -360,7 +356,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
return list.Any() ? list : null;
|
return list.Any() ? list : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MatcherModel GetExampleMatcherModel(OpenApiSchema schema, ExampleValueType type)
|
private MatcherModel GetExampleMatcherModel(OpenApiSchema? schema, ExampleValueType type)
|
||||||
{
|
{
|
||||||
return type switch
|
return type switch
|
||||||
{
|
{
|
||||||
@@ -370,7 +366,7 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetExampleValueAsStringForSchemaType(OpenApiSchema schema)
|
private string GetExampleValueAsStringForSchemaType(OpenApiSchema? schema)
|
||||||
{
|
{
|
||||||
var value = _exampleValueGenerator.GetExampleValue(schema);
|
var value = _exampleValueGenerator.GetExampleValue(schema);
|
||||||
|
|
||||||
@@ -381,5 +377,4 @@ namespace WireMock.Net.OpenApiParser.Mappers
|
|||||||
_ => value.ToString(),
|
_ => value.ToString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,28 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Settings
|
namespace WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A interface defining the example values to use for the different types.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWireMockOpenApiParserExampleValues
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// A interface defining the example values to use for the different types.
|
|
||||||
/// </summary>
|
|
||||||
public interface IWireMockOpenApiParserExampleValues
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An example value for a Boolean.
|
/// An example value for a Boolean.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool Boolean { get; set; }
|
bool Boolean { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An example value for an Integer.
|
/// An example value for an Integer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int Integer { get; set; }
|
int Integer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An example value for a Float.
|
/// An example value for a Float.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
float Float { get; set; }
|
float Float { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// An example value for a Double.
|
/// An example value for a Double.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -53,6 +56,5 @@ namespace WireMock.Net.OpenApiParser.Settings
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// OpenApi Schema to generate dynamic examples more accurate
|
/// OpenApi Schema to generate dynamic examples more accurate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
OpenApiSchema Schema { get; set; }
|
OpenApiSchema? Schema { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,34 +1,42 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using RandomDataGenerator.FieldOptions;
|
using RandomDataGenerator.FieldOptions;
|
||||||
using RandomDataGenerator.Randomizers;
|
using RandomDataGenerator.Randomizers;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Settings
|
namespace WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class defining the random example values to use for the different types.
|
||||||
|
/// </summary>
|
||||||
|
public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// A class defining the random example values to use for the different types.
|
|
||||||
/// </summary>
|
|
||||||
public class WireMockOpenApiParserDynamicExampleValues : IWireMockOpenApiParserExampleValues
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual bool Boolean { get { return RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true; } set { } }
|
public virtual bool Boolean { get => RandomizerFactory.GetRandomizer(new FieldOptionsBoolean()).Generate() ?? true; set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual int Integer { get { return RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42; } set { } }
|
public virtual int Integer { get => RandomizerFactory.GetRandomizer(new FieldOptionsInteger()).Generate() ?? 42; set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual float Float { get { return RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f; } set { } }
|
public virtual float Float { get => RandomizerFactory.GetRandomizer(new FieldOptionsFloat()).Generate() ?? 4.2f; set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual double Double { get { return RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d; } set { } }
|
public virtual double Double { get => RandomizerFactory.GetRandomizer(new FieldOptionsDouble()).Generate() ?? 4.2d; set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } set { } }
|
public virtual Func<DateTime> Date { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow.Date; } set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } set { } }
|
public virtual Func<DateTime> DateTime { get { return () => RandomizerFactory.GetRandomizer(new FieldOptionsDateTime()).Generate() ?? System.DateTime.UtcNow; } set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual byte[] Bytes { get { return RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate(); } set { } }
|
public virtual byte[] Bytes { get => RandomizerFactory.GetRandomizer(new FieldOptionsBytes()).Generate(); set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual object Object { get; set; } = "example-object";
|
public virtual object Object { get; set; } = "example-object";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual string String { get { return RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string"; } set { } }
|
public virtual string String { get => RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex { Pattern = @"^[0-9]{2}[A-Z]{5}[0-9]{2}" }).Generate() ?? "example-string"; set { } }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual OpenApiSchema Schema { get; set; }
|
public virtual OpenApiSchema? Schema { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,32 +1,40 @@
|
|||||||
using System;
|
using System;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Settings
|
namespace WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A class defining the example values to use for the different types.
|
||||||
|
/// </summary>
|
||||||
|
public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// A class defining the example values to use for the different types.
|
|
||||||
/// </summary>
|
|
||||||
public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleValues
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual bool Boolean { get; set; } = true;
|
public virtual bool Boolean { get; set; } = true;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual int Integer { get; set; } = 42;
|
public virtual int Integer { get; set; } = 42;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual float Float { get; set; } = 4.2f;
|
public virtual float Float { get; set; } = 4.2f;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual double Double { get; set; } = 4.2d;
|
public virtual double Double { get; set; } = 4.2d;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date;
|
public virtual Func<DateTime> Date { get; set; } = () => System.DateTime.UtcNow.Date;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow;
|
public virtual Func<DateTime> DateTime { get; set; } = () => System.DateTime.UtcNow;
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual byte[] Bytes { get; set; } = { 48, 49, 50 };
|
public virtual byte[] Bytes { get; set; } = { 48, 49, 50 };
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual object Object { get; set; } = "example-object";
|
public virtual object Object { get; set; } = "example-object";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual string String { get; set; } = "example-string";
|
public virtual string String { get; set; } = "example-string";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual OpenApiSchema Schema { get; set; } = new OpenApiSchema();
|
public virtual OpenApiSchema? Schema { get; set; } = new OpenApiSchema();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,12 +1,12 @@
|
|||||||
using WireMock.Net.OpenApiParser.Types;
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Settings
|
namespace WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The WireMockOpenApiParser Settings
|
||||||
|
/// </summary>
|
||||||
|
public class WireMockOpenApiParserSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The WireMockOpenApiParser Settings
|
|
||||||
/// </summary>
|
|
||||||
public class WireMockOpenApiParserSettings
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The number of array items to generate (default is 3).
|
/// The number of array items to generate (default is 3).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -34,7 +34,7 @@ namespace WireMock.Net.OpenApiParser.Settings
|
|||||||
/// - <see cref="WireMockOpenApiParserExampleValues"/>
|
/// - <see cref="WireMockOpenApiParserExampleValues"/>
|
||||||
/// - <see cref="WireMockOpenApiParserDynamicExampleValues"/>
|
/// - <see cref="WireMockOpenApiParserDynamicExampleValues"/>
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IWireMockOpenApiParserExampleValues ExampleValues { get; set; }
|
public IWireMockOpenApiParserExampleValues? ExampleValues { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is a Header match case insensitive? (default is true).
|
/// Is a Header match case insensitive? (default is true).
|
||||||
@@ -60,5 +60,4 @@ namespace WireMock.Net.OpenApiParser.Settings
|
|||||||
/// Are examples generated dynamically? (default is false).
|
/// Are examples generated dynamically? (default is false).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool DynamicExamples { get; set; } = false;
|
public bool DynamicExamples { get; set; } = false;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
namespace WireMock.Net.OpenApiParser.Types
|
namespace WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The example value to use
|
||||||
|
/// </summary>
|
||||||
|
public enum ExampleValueType
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// The example value to use
|
|
||||||
/// </summary>
|
|
||||||
public enum ExampleValueType
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// 1. Use a generated example value based on the SchemaType (default).
|
/// 1. Use a generated example value based on the SchemaType (default).
|
||||||
/// 2. If there is no example value defined in the schema,
|
/// 2. If there is no example value defined in the schema,
|
||||||
@@ -16,5 +16,4 @@ namespace WireMock.Net.OpenApiParser.Types
|
|||||||
/// Just use a Wildcard (*) character.
|
/// Just use a Wildcard (*) character.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Wildcard
|
Wildcard
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace WireMock.Net.OpenApiParser.Types
|
namespace WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
|
internal enum SchemaFormat
|
||||||
{
|
{
|
||||||
internal enum SchemaFormat
|
|
||||||
{
|
|
||||||
Float,
|
Float,
|
||||||
|
|
||||||
Double,
|
Double,
|
||||||
@@ -21,5 +21,4 @@
|
|||||||
Binary,
|
Binary,
|
||||||
|
|
||||||
Undefined
|
Undefined
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace WireMock.Net.OpenApiParser.Types
|
namespace WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
|
internal enum SchemaType
|
||||||
{
|
{
|
||||||
internal enum SchemaType
|
|
||||||
{
|
|
||||||
Object,
|
Object,
|
||||||
|
|
||||||
Array,
|
Array,
|
||||||
@@ -17,5 +17,4 @@
|
|||||||
File,
|
File,
|
||||||
|
|
||||||
Unknown
|
Unknown
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Utils
|
namespace WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
|
internal static class DateTimeUtils
|
||||||
{
|
{
|
||||||
internal static class DateTimeUtils
|
|
||||||
{
|
|
||||||
public static string ToRfc3339DateTime(DateTime dateTime)
|
public static string ToRfc3339DateTime(DateTime dateTime)
|
||||||
{
|
{
|
||||||
return dateTime.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo);
|
return dateTime.ToString("yyyy-MM-dd'T'HH:mm:ss.fffzzz", DateTimeFormatInfo.InvariantInfo);
|
||||||
@@ -14,5 +14,4 @@ namespace WireMock.Net.OpenApiParser.Utils
|
|||||||
{
|
{
|
||||||
return dateTime.ToString("yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo);
|
return dateTime.ToString("yyyy-MM-dd", DateTimeFormatInfo.InvariantInfo);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -7,15 +7,15 @@ using WireMock.Net.OpenApiParser.Extensions;
|
|||||||
using WireMock.Net.OpenApiParser.Settings;
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
using WireMock.Net.OpenApiParser.Types;
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Utils
|
namespace WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
|
internal class ExampleValueGenerator
|
||||||
{
|
{
|
||||||
internal class ExampleValueGenerator
|
|
||||||
{
|
|
||||||
private readonly WireMockOpenApiParserSettings _settings;
|
private readonly WireMockOpenApiParserSettings _settings;
|
||||||
|
|
||||||
public ExampleValueGenerator(WireMockOpenApiParserSettings settings)
|
public ExampleValueGenerator(WireMockOpenApiParserSettings settings)
|
||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings, nameof(settings));
|
_settings = Guard.NotNull(settings);
|
||||||
|
|
||||||
// Check if user provided an own implementation
|
// Check if user provided an own implementation
|
||||||
if (settings.ExampleValues is null)
|
if (settings.ExampleValues is null)
|
||||||
@@ -31,7 +31,7 @@ namespace WireMock.Net.OpenApiParser.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetExampleValue(OpenApiSchema schema)
|
public object GetExampleValue(OpenApiSchema? schema)
|
||||||
{
|
{
|
||||||
var schemaExample = schema?.Example;
|
var schemaExample = schema?.Example;
|
||||||
var schemaEnum = GetRandomEnumValue(schema?.Enum);
|
var schemaEnum = GetRandomEnumValue(schema?.Enum);
|
||||||
@@ -41,7 +41,7 @@ namespace WireMock.Net.OpenApiParser.Utils
|
|||||||
switch (schema?.GetSchemaType())
|
switch (schema?.GetSchemaType())
|
||||||
{
|
{
|
||||||
case SchemaType.Boolean:
|
case SchemaType.Boolean:
|
||||||
var exampleBoolean = (OpenApiBoolean)schemaExample;
|
var exampleBoolean = schemaExample as OpenApiBoolean;
|
||||||
return exampleBoolean is null ? _settings.ExampleValues.Boolean : exampleBoolean.Value;
|
return exampleBoolean is null ? _settings.ExampleValues.Boolean : exampleBoolean.Value;
|
||||||
|
|
||||||
case SchemaType.Integer:
|
case SchemaType.Integer:
|
||||||
@@ -112,7 +112,7 @@ namespace WireMock.Net.OpenApiParser.Utils
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOpenApiAny GetRandomEnumValue(IList<IOpenApiAny> schemaEnum)
|
private static IOpenApiAny? GetRandomEnumValue(IList<IOpenApiAny>? schemaEnum)
|
||||||
{
|
{
|
||||||
if (schemaEnum?.Count > 0)
|
if (schemaEnum?.Count > 0)
|
||||||
{
|
{
|
||||||
@@ -123,5 +123,4 @@ namespace WireMock.Net.OpenApiParser.Utils
|
|||||||
|
|
||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,7 @@
|
|||||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<LangVersion>8.0</LangVersion>
|
<LangVersion>10</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
@@ -22,6 +22,10 @@
|
|||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.3" />
|
<PackageReference Include="Microsoft.OpenApi.Readers" Version="1.2.3" />
|
||||||
|
<PackageReference Include="Nullable" Version="1.3.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
|
<PackageReference Include="RamlToOpenApiConverter" Version="0.6.1" />
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="All" />
|
<PackageReference Include="JetBrains.Annotations" Version="2022.1.0" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
@@ -9,13 +9,13 @@ using WireMock.Admin.Mappings;
|
|||||||
using WireMock.Net.OpenApiParser.Mappers;
|
using WireMock.Net.OpenApiParser.Mappers;
|
||||||
using WireMock.Net.OpenApiParser.Settings;
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser
|
namespace WireMock.Net.OpenApiParser;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse a OpenApi/Swagger/V2/V3 or Raml to WireMock.Net MappingModels.
|
||||||
|
/// </summary>
|
||||||
|
public class WireMockOpenApiParser : IWireMockOpenApiParser
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// Parse a OpenApi/Swagger/V2/V3 or Raml to WireMock.Net MappingModels.
|
|
||||||
/// </summary>
|
|
||||||
public class WireMockOpenApiParser : IWireMockOpenApiParser
|
|
||||||
{
|
|
||||||
private readonly OpenApiStreamReader _reader = new OpenApiStreamReader();
|
private readonly OpenApiStreamReader _reader = new OpenApiStreamReader();
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromFile(string, out OpenApiDiagnostic)" />
|
/// <inheritdoc cref="IWireMockOpenApiParser.FromFile(string, out OpenApiDiagnostic)" />
|
||||||
@@ -60,9 +60,8 @@ namespace WireMock.Net.OpenApiParser
|
|||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromDocument(OpenApiDocument, WireMockOpenApiParserSettings)" />
|
/// <inheritdoc cref="IWireMockOpenApiParser.FromDocument(OpenApiDocument, WireMockOpenApiParserSettings)" />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IEnumerable<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings settings = null)
|
public IEnumerable<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings? settings = null)
|
||||||
{
|
{
|
||||||
return new OpenApiPathsMapper(settings).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
|
return new OpenApiPathsMapper(settings).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
using RestEase;
|
using RestEase;
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
@@ -179,6 +179,20 @@ namespace WireMock.Client
|
|||||||
[Post("scenarios")]
|
[Post("scenarios")]
|
||||||
Task<StatusModel> ResetScenariosAsync();
|
Task<StatusModel> ResetScenariosAsync();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete (reset) a specific scenario
|
||||||
|
/// </summary>
|
||||||
|
[Delete("scenarios/{name}")]
|
||||||
|
[AllowAnyStatusCode]
|
||||||
|
Task<StatusModel> DeleteScenarioAsync([Path] string name);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete (reset) all scenarios
|
||||||
|
/// </summary>
|
||||||
|
[Post("scenarios/{name}/reset")]
|
||||||
|
[AllowAnyStatusCode]
|
||||||
|
Task<StatusModel> ResetScenarioAsync([Path] string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new File
|
/// Create a new File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -15,7 +15,7 @@ namespace WireMock.Net.StandAlone;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public static class StandAloneApp
|
public static class StandAloneApp
|
||||||
{
|
{
|
||||||
private static readonly string Version = typeof(StandAloneApp).GetTypeInfo().Assembly.GetName().Version.ToString();
|
private static readonly string Version = typeof(StandAloneApp).GetTypeInfo().Assembly.GetName().Version!.ToString();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Start WireMock.Net standalone Server based on the WireMockServerSettings.
|
/// Start WireMock.Net standalone Server based on the WireMockServerSettings.
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using System.Net;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
@@ -35,6 +36,8 @@ internal static class HttpResponseMessageHelper
|
|||||||
contentEncodingHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)).Value;
|
contentEncodingHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)).Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (httpResponseMessage.StatusCode != HttpStatusCode.NoContent) // A body is not allowed for 204.
|
||||||
|
{
|
||||||
var bodyParserSettings = new BodyParserSettings
|
var bodyParserSettings = new BodyParserSettings
|
||||||
{
|
{
|
||||||
Stream = stream,
|
Stream = stream,
|
||||||
@@ -45,6 +48,7 @@ internal static class HttpResponseMessageHelper
|
|||||||
};
|
};
|
||||||
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
foreach (var header in headers)
|
foreach (var header in headers)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -89,7 +89,7 @@ internal class WebhookSender
|
|||||||
};
|
};
|
||||||
|
|
||||||
// Create HttpRequestMessage
|
// Create HttpRequestMessage
|
||||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, webhookRequest.Url);
|
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, webhookRequestUrl);
|
||||||
|
|
||||||
// Delay (if required)
|
// Delay (if required)
|
||||||
if (TryGetDelay(webhookRequest, out var delay))
|
if (TryGetDelay(webhookRequest, out var delay))
|
||||||
|
|||||||
@@ -12,13 +12,13 @@ public class LogEntry : ILogEntry
|
|||||||
public Guid Guid { get; set; }
|
public Guid Guid { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="ILogEntry.RequestMessage" />
|
/// <inheritdoc cref="ILogEntry.RequestMessage" />
|
||||||
public IRequestMessage RequestMessage { get; set; }
|
public IRequestMessage RequestMessage { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
|
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
|
||||||
public IResponseMessage ResponseMessage { get; set; }
|
public IResponseMessage ResponseMessage { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
|
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
|
||||||
public IRequestMatchResult RequestMatchResult { get; set; }
|
public IRequestMatchResult RequestMatchResult { get; set; } = null!;
|
||||||
|
|
||||||
/// <inheritdoc cref="ILogEntry.MappingGuid" />
|
/// <inheritdoc cref="ILogEntry.MappingGuid" />
|
||||||
public Guid? MappingGuid { get; set; }
|
public Guid? MappingGuid { get; set; }
|
||||||
@@ -33,5 +33,5 @@ public class LogEntry : ILogEntry
|
|||||||
public string? PartialMappingTitle { get; set; }
|
public string? PartialMappingTitle { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
|
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
|
||||||
public IRequestMatchResult PartialMatchResult { get; set; }
|
public IRequestMatchResult PartialMatchResult { get; set; } = null!;
|
||||||
}
|
}
|
||||||
@@ -2,14 +2,14 @@ using Newtonsoft.Json;
|
|||||||
using System;
|
using System;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
|
|
||||||
namespace WireMock.Logging
|
namespace WireMock.Logging;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WireMockConsoleLogger which logs to Console
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IWireMockLogger" />
|
||||||
|
public class WireMockConsoleLogger : IWireMockLogger
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// WireMockConsoleLogger which logs to Console
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IWireMockLogger" />
|
|
||||||
public class WireMockConsoleLogger : IWireMockLogger
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockConsoleLogger"/> class.
|
/// Initializes a new instance of the <see cref="WireMockConsoleLogger"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -70,5 +70,4 @@ namespace WireMock.Logging
|
|||||||
|
|
||||||
return $"{DateTime.UtcNow} [{level}] : {message}";
|
return $"{DateTime.UtcNow} [{level}] : {message}";
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,14 +1,14 @@
|
|||||||
using System;
|
using System;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
|
|
||||||
namespace WireMock.Logging
|
namespace WireMock.Logging;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WireMockNullLogger which does not log.
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="IWireMockLogger" />
|
||||||
|
public class WireMockNullLogger : IWireMockLogger
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// WireMockNullLogger which does not log.
|
|
||||||
/// </summary>
|
|
||||||
/// <seealso cref="IWireMockLogger" />
|
|
||||||
public class WireMockNullLogger : IWireMockLogger
|
|
||||||
{
|
|
||||||
/// <see cref="IWireMockLogger.Debug"/>
|
/// <see cref="IWireMockLogger.Debug"/>
|
||||||
public void Debug(string formatString, params object[] args)
|
public void Debug(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
@@ -44,5 +44,4 @@ namespace WireMock.Logging
|
|||||||
{
|
{
|
||||||
// Log nothing
|
// Log nothing
|
||||||
}
|
}
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -21,6 +21,7 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
|||||||
|
|
||||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||||
public MatchBehaviour MatchBehaviour { get; }
|
public MatchBehaviour MatchBehaviour { get; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IMatcher.ThrowException"/>
|
/// <inheritdoc cref="IMatcher.ThrowException"/>
|
||||||
public bool ThrowException { get; }
|
public bool ThrowException { get; }
|
||||||
|
|
||||||
|
|||||||
@@ -104,7 +104,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="func">The function.</param>
|
/// <param name="func">The function.</param>
|
||||||
public RequestMessageBodyMatcher(Func<IBodyData, bool> func)
|
public RequestMessageBodyMatcher(Func<IBodyData?, bool> func)
|
||||||
{
|
{
|
||||||
BodyDataFunc = Guard.NotNull(func);
|
BodyDataFunc = Guard.NotNull(func);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -53,7 +53,8 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
|||||||
/// <param name="key">The key.</param>
|
/// <param name="key">The key.</param>
|
||||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||||
/// <param name="values">The values.</param>
|
/// <param name="values">The values.</param>
|
||||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, string[]? values) : this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray())
|
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params string[]? values) :
|
||||||
|
this(matchBehaviour, key, ignoreCase, values?.Select(value => new ExactMatcher(matchBehaviour, ignoreCase, false, MatchOperator.And, value)).Cast<IStringMatcher>().ToArray())
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -64,7 +65,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
|||||||
/// <param name="key">The key.</param>
|
/// <param name="key">The key.</param>
|
||||||
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||||
/// <param name="matchers">The matchers.</param>
|
/// <param name="matchers">The matchers.</param>
|
||||||
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, IStringMatcher[]? matchers)
|
public RequestMessageParamMatcher(MatchBehaviour matchBehaviour, string key, bool ignoreCase, params IStringMatcher[]? matchers)
|
||||||
{
|
{
|
||||||
MatchBehaviour = matchBehaviour;
|
MatchBehaviour = matchBehaviour;
|
||||||
Key = Guard.NotNull(key);
|
Key = Guard.NotNull(key);
|
||||||
@@ -95,7 +96,7 @@ public class RequestMessageParamMatcher : IRequestMatcher
|
|||||||
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
|
return MatchScores.ToScore(requestMessage.Query != null && Funcs.Any(f => f(requestMessage.Query)));
|
||||||
}
|
}
|
||||||
|
|
||||||
var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key!, IgnoreCase ?? false);
|
var valuesPresentInRequestMessage = ((RequestMessage)requestMessage).GetParameter(Key, IgnoreCase ?? false);
|
||||||
if (valuesPresentInRequestMessage == null)
|
if (valuesPresentInRequestMessage == null)
|
||||||
{
|
{
|
||||||
// Key is not present at all, just return Mismatch
|
// Key is not present at all, just return Mismatch
|
||||||
|
|||||||
@@ -1,13 +1,13 @@
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Util
|
namespace WireMock.Util;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// BodyData
|
||||||
|
/// </summary>
|
||||||
|
public class BodyData : IBodyData
|
||||||
{
|
{
|
||||||
/// <summary>
|
|
||||||
/// BodyData
|
|
||||||
/// </summary>
|
|
||||||
public class BodyData : IBodyData
|
|
||||||
{
|
|
||||||
/// <inheritdoc cref="IBodyData.Encoding" />
|
/// <inheritdoc cref="IBodyData.Encoding" />
|
||||||
public Encoding? Encoding { get; set; }
|
public Encoding? Encoding { get; set; }
|
||||||
|
|
||||||
@@ -37,5 +37,7 @@ namespace WireMock.Util
|
|||||||
|
|
||||||
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
|
/// <inheritdoc cref="IRequestMessage.DetectedCompression" />
|
||||||
public string? DetectedCompression { get; set; }
|
public string? DetectedCompression { get; set; }
|
||||||
}
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string? IsFuncUsed { get; set; }
|
||||||
}
|
}
|
||||||
@@ -3,13 +3,13 @@ using System.Collections.Concurrent;
|
|||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
#if !USE_ASPNETCORE
|
#if !USE_ASPNETCORE
|
||||||
using Owin;
|
using Owin;
|
||||||
#else
|
#else
|
||||||
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.Types;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
namespace WireMock.Owin;
|
||||||
@@ -69,4 +69,8 @@ internal interface IWireMockMiddlewareOptions
|
|||||||
bool CustomCertificateDefined { get; }
|
bool CustomCertificateDefined { get; }
|
||||||
|
|
||||||
bool? SaveUnmatchedRequests { get; set; }
|
bool? SaveUnmatchedRequests { get; set; }
|
||||||
|
|
||||||
|
bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
|
QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
}
|
}
|
||||||
@@ -68,7 +68,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
body = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
body = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RequestMessage(urlDetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };
|
return new RequestMessage(options, urlDetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
|
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
|
||||||
|
|||||||
@@ -81,11 +81,11 @@ namespace WireMock.Owin.Mappers
|
|||||||
var statusCodeType = responseMessage.StatusCode?.GetType();
|
var statusCodeType = responseMessage.StatusCode?.GetType();
|
||||||
switch (statusCodeType)
|
switch (statusCodeType)
|
||||||
{
|
{
|
||||||
case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
|
case { } typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
|
||||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
|
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case Type typeAsString when typeAsString == typeof(string):
|
case { } typeAsString when typeAsString == typeof(string):
|
||||||
// Note: this case will also match on null
|
// Note: this case will also match on null
|
||||||
int.TryParse(responseMessage.StatusCode as string, out int result);
|
int.TryParse(responseMessage.StatusCode as string, out int result);
|
||||||
response.StatusCode = MapStatusCode(result);
|
response.StatusCode = MapStatusCode(result);
|
||||||
@@ -98,9 +98,16 @@ namespace WireMock.Owin.Mappers
|
|||||||
SetResponseHeaders(responseMessage, response);
|
SetResponseHeaders(responseMessage, response);
|
||||||
|
|
||||||
if (bytes != null)
|
if (bytes != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
await response.Body.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
await response.Body.WriteAsync(bytes, 0, bytes.Length).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_options.Logger.Warn("Error writing response body. Exception : {0}", ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private int MapStatusCode(int code)
|
private int MapStatusCode(int code)
|
||||||
@@ -123,7 +130,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString);
|
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
||||||
|
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
var formatting = responseMessage.BodyData.BodyAsJsonIndented == true
|
var formatting = responseMessage.BodyData.BodyAsJsonIndented == true
|
||||||
@@ -136,7 +143,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
return responseMessage.BodyData.BodyAsBytes;
|
return responseMessage.BodyData.BodyAsBytes;
|
||||||
|
|
||||||
case BodyType.File:
|
case BodyType.File:
|
||||||
return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return null;
|
return null;
|
||||||
@@ -154,7 +161,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
});
|
});
|
||||||
|
|
||||||
// Set other headers
|
// Set other headers
|
||||||
foreach (var item in responseMessage.Headers)
|
foreach (var item in responseMessage.Headers!)
|
||||||
{
|
{
|
||||||
var headerName = item.Key;
|
var headerName = item.Key;
|
||||||
var value = item.Value;
|
var value = item.Value;
|
||||||
|
|||||||
@@ -32,22 +32,25 @@ namespace WireMock.Owin
|
|||||||
private readonly IOwinRequestMapper _requestMapper;
|
private readonly IOwinRequestMapper _requestMapper;
|
||||||
private readonly IOwinResponseMapper _responseMapper;
|
private readonly IOwinResponseMapper _responseMapper;
|
||||||
private readonly IMappingMatcher _mappingMatcher;
|
private readonly IMappingMatcher _mappingMatcher;
|
||||||
|
private readonly LogEntryMapper _logEntryMapper;
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
#if !USE_ASPNETCORE
|
||||||
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher) : base(next)
|
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher) : base(next)
|
||||||
{
|
{
|
||||||
_options = Guard.NotNull(options, nameof(options));
|
_options = Guard.NotNull(options);
|
||||||
_requestMapper = Guard.NotNull(requestMapper, nameof(requestMapper));
|
_requestMapper = Guard.NotNull(requestMapper);
|
||||||
_responseMapper = Guard.NotNull(responseMapper, nameof(responseMapper));
|
_responseMapper = Guard.NotNull(responseMapper);
|
||||||
_mappingMatcher = Guard.NotNull(mappingMatcher, nameof(mappingMatcher));
|
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||||
|
_logEntryMapper = new LogEntryMapper(options);
|
||||||
}
|
}
|
||||||
#else
|
#else
|
||||||
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher)
|
public WireMockMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinRequestMapper requestMapper, IOwinResponseMapper responseMapper, IMappingMatcher mappingMatcher)
|
||||||
{
|
{
|
||||||
_options = Guard.NotNull(options, nameof(options));
|
_options = Guard.NotNull(options);
|
||||||
_requestMapper = Guard.NotNull(requestMapper, nameof(requestMapper));
|
_requestMapper = Guard.NotNull(requestMapper);
|
||||||
_responseMapper = Guard.NotNull(responseMapper, nameof(responseMapper));
|
_responseMapper = Guard.NotNull(responseMapper);
|
||||||
_mappingMatcher = Guard.NotNull(mappingMatcher, nameof(mappingMatcher));
|
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||||
|
_logEntryMapper = new LogEntryMapper(options);
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
@@ -264,30 +267,56 @@ namespace WireMock.Owin
|
|||||||
|
|
||||||
private void LogRequest(LogEntry entry, bool addRequest)
|
private void LogRequest(LogEntry entry, bool addRequest)
|
||||||
{
|
{
|
||||||
_options.Logger.DebugRequestResponse(LogEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||||
|
|
||||||
if (addRequest)
|
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
||||||
|
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
||||||
{
|
{
|
||||||
_options.LogEntries.Add(entry);
|
TryAddLogEntry(entry);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_options.MaxRequestLogCount != null)
|
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
||||||
|
if (_options.MaxRequestLogCount is > 0)
|
||||||
{
|
{
|
||||||
var logEntries = _options.LogEntries.ToList();
|
var logEntries = _options.LogEntries.ToList();
|
||||||
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
||||||
{
|
{
|
||||||
_options.LogEntries.Remove(logEntry);
|
TryRemoveLogEntry(logEntry);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (_options.RequestLogExpirationDuration != null)
|
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
||||||
|
if (_options.RequestLogExpirationDuration is > 0)
|
||||||
{
|
{
|
||||||
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
||||||
|
|
||||||
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
||||||
|
{
|
||||||
|
TryRemoveLogEntry(logEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryAddLogEntry(LogEntry logEntry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_options.LogEntries.Add(logEntry);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore exception (can happen during stress testing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryRemoveLogEntry(LogEntry logEntry)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
_options.LogEntries.Remove(logEntry);
|
_options.LogEntries.Remove(logEntry);
|
||||||
}
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore exception (can happen during stress testing)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -26,7 +26,7 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
|
public ConcurrentDictionary<Guid, IMapping> Mappings { get; } = new ConcurrentDictionary<Guid, IMapping>();
|
||||||
|
|
||||||
public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new();
|
public ConcurrentDictionary<string, ScenarioState> Scenarios { get; } = new(StringComparer.OrdinalIgnoreCase);
|
||||||
|
|
||||||
public ConcurrentObservableCollection<LogEntry> LogEntries { get; } = new();
|
public ConcurrentObservableCollection<LogEntry> LogEntries { get; } = new();
|
||||||
|
|
||||||
@@ -84,4 +84,10 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/>
|
/// <inheritdoc cref="IWireMockMiddlewareOptions.SaveUnmatchedRequests"/>
|
||||||
public bool? SaveUnmatchedRequests { get; set; }
|
public bool? SaveUnmatchedRequests { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
namespace WireMock.Pact.Models.V2;
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
public class Interaction
|
public class Interaction
|
||||||
|
|||||||
@@ -1,7 +1,8 @@
|
|||||||
namespace WireMock.Pact.Models.V2
|
#pragma warning disable CS1591
|
||||||
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class MatchingRule
|
||||||
{
|
{
|
||||||
public class MatchingRule
|
|
||||||
{
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// type or regex
|
/// type or regex
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -21,5 +22,4 @@ namespace WireMock.Pact.Models.V2
|
|||||||
/// Used for Match = "regex"
|
/// Used for Match = "regex"
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Regex { get; set; }
|
public string Regex { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
namespace WireMock.Pact.Models.V2
|
#pragma warning disable CS1591
|
||||||
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class Metadata
|
||||||
{
|
{
|
||||||
public class Metadata
|
|
||||||
{
|
|
||||||
public string PactSpecificationVersion { get; set; }
|
public string PactSpecificationVersion { get; set; }
|
||||||
|
|
||||||
public PactSpecification PactSpecification { get; set; } = new PactSpecification();
|
public PactSpecification PactSpecification { get; set; } = new PactSpecification();
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,9 +1,10 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Pact.Models.V2
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class Pact
|
||||||
{
|
{
|
||||||
public class Pact
|
|
||||||
{
|
|
||||||
public Pacticipant Consumer { get; set; }
|
public Pacticipant Consumer { get; set; }
|
||||||
|
|
||||||
public List<Interaction> Interactions { get; set; } = new List<Interaction>();
|
public List<Interaction> Interactions { get; set; } = new List<Interaction>();
|
||||||
@@ -11,5 +12,4 @@ namespace WireMock.Pact.Models.V2
|
|||||||
public Metadata Metadata { get; set; }
|
public Metadata Metadata { get; set; }
|
||||||
|
|
||||||
public Pacticipant Provider { get; set; }
|
public Pacticipant Provider { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,6 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using WireMock.Constants;
|
||||||
|
|
||||||
namespace WireMock.Pact.Models.V2;
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
@@ -6,7 +8,7 @@ public class PactRequest
|
|||||||
{
|
{
|
||||||
public IDictionary<string, string>? Headers { get; set; }
|
public IDictionary<string, string>? Headers { get; set; }
|
||||||
|
|
||||||
public string Method { get; set; } = "GET";
|
public string Method { get; set; } = HttpRequestMethod.GET;
|
||||||
|
|
||||||
public string? Path { get; set; } = "/";
|
public string? Path { get; set; } = "/";
|
||||||
|
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Pact.Models.V2;
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|||||||
@@ -1,11 +1,11 @@
|
|||||||
namespace WireMock.Pact.Models.V2
|
#pragma warning disable CS1591
|
||||||
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class PactRust
|
||||||
{
|
{
|
||||||
public class PactRust
|
|
||||||
{
|
|
||||||
public string Ffi { get; set; }
|
public string Ffi { get; set; }
|
||||||
|
|
||||||
public string Mockserver { get; set; }
|
public string Mockserver { get; set; }
|
||||||
|
|
||||||
public string Models { get; set; }
|
public string Models { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace WireMock.Pact.Models.V2
|
#pragma warning disable CS1591
|
||||||
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class PactSpecification
|
||||||
{
|
{
|
||||||
public class PactSpecification
|
|
||||||
{
|
|
||||||
public string Version { get; set; } = "2.0";
|
public string Version { get; set; } = "2.0";
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace WireMock.Pact.Models.V2
|
#pragma warning disable CS1591
|
||||||
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class Pacticipant
|
||||||
{
|
{
|
||||||
public class Pacticipant
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
|
#pragma warning disable CS1591
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Pact.Models.V2
|
namespace WireMock.Pact.Models.V2;
|
||||||
|
|
||||||
|
public class ProviderState
|
||||||
{
|
{
|
||||||
public class ProviderState
|
|
||||||
{
|
|
||||||
public string Name { get; set; }
|
public string Name { get; set; }
|
||||||
|
|
||||||
public IDictionary<string, string> Params { get; set; }
|
public IDictionary<string, string> Params { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,17 +1,10 @@
|
|||||||
using Stef.Validation;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using WireMock.Constants;
|
using Stef.Validation;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
using WireMock.Matchers;
|
|
||||||
using WireMock.RequestBuilders;
|
|
||||||
using WireMock.ResponseBuilders;
|
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Types;
|
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Proxy;
|
namespace WireMock.Proxy;
|
||||||
@@ -62,69 +55,4 @@ internal class ProxyHelper
|
|||||||
|
|
||||||
return (responseMessage, newMapping);
|
return (responseMessage, newMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
private IMapping ToMapping(ProxyAndRecordSettings proxyAndRecordSettings, IRequestMessage requestMessage, ResponseMessage responseMessage)
|
|
||||||
{
|
|
||||||
var excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
|
|
||||||
var excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
|
|
||||||
|
|
||||||
var request = Request.Create();
|
|
||||||
request.WithPath(requestMessage.Path);
|
|
||||||
request.UsingMethod(requestMessage.Method);
|
|
||||||
|
|
||||||
requestMessage.Query?.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
|
|
||||||
requestMessage.Cookies?.Loop((key, value) =>
|
|
||||||
{
|
|
||||||
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
request.WithCookie(key, value);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
var allExcludedHeaders = new List<string>(excludedHeaders) { "Cookie" };
|
|
||||||
requestMessage.Headers?.Loop((key, value) =>
|
|
||||||
{
|
|
||||||
if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
|
|
||||||
{
|
|
||||||
request.WithHeader(key, value.ToArray());
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
|
||||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
|
||||||
{
|
|
||||||
case BodyType.Json:
|
|
||||||
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson!, true, throwExceptionWhenMatcherFails));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BodyType.String:
|
|
||||||
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, false, throwExceptionWhenMatcherFails, MatchOperator.Or, requestMessage.BodyData.BodyAsString));
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BodyType.Bytes:
|
|
||||||
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
var response = Response.Create(responseMessage);
|
|
||||||
|
|
||||||
return new Mapping
|
|
||||||
(
|
|
||||||
guid: Guid.NewGuid(),
|
|
||||||
title: $"Proxy Mapping for {requestMessage.Method} {requestMessage.Path}",
|
|
||||||
description: string.Empty,
|
|
||||||
path: null,
|
|
||||||
settings: _settings,
|
|
||||||
request,
|
|
||||||
response,
|
|
||||||
priority: WireMockConstants.ProxyPriority, // This was 0
|
|
||||||
scenario: null,
|
|
||||||
executionConditionState: null,
|
|
||||||
nextState: null,
|
|
||||||
stateTimes: null,
|
|
||||||
webhooks: null,
|
|
||||||
useWebhooksFireAndForget: null,
|
|
||||||
timeSettings: null
|
|
||||||
);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
||||||
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using WireMock.Http;
|
using Stef.Validation;
|
||||||
|
using WireMock.Constants;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
using Stef.Validation;
|
|
||||||
|
|
||||||
namespace WireMock.RequestBuilders;
|
namespace WireMock.RequestBuilders;
|
||||||
|
|
||||||
@@ -13,63 +13,63 @@ public partial class Request
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingConnect(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.CONNECT));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.CONNECT));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingDelete(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.DELETE));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.DELETE));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingGet(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.GET));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.GET));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingHead(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.HEAD));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.HEAD));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingOptions(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.OPTIONS));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.OPTIONS));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingPost(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.POST));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.POST));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingPatch(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.PATCH));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PATCH));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingPut(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.PUT));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.PUT));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
public IRequestBuilder UsingTrace(MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
{
|
{
|
||||||
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethods.TRACE));
|
_requestMatchers.Add(new RequestMessageMethodMatcher(matchBehaviour, MatchOperator.Or, HttpRequestMethod.TRACE));
|
||||||
return this;
|
return this;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -6,6 +6,7 @@ using System.Linq;
|
|||||||
using System.Net;
|
using System.Net;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
|
using WireMock.Owin;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -26,7 +27,7 @@ public class RequestMessage : IRequestMessage
|
|||||||
public string AbsoluteUrl { get; }
|
public string AbsoluteUrl { get; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IRequestMessage.ProxyUrl" />
|
/// <inheritdoc cref="IRequestMessage.ProxyUrl" />
|
||||||
public string ProxyUrl { get; set; }
|
public string? ProxyUrl { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IRequestMessage.DateTime" />
|
/// <inheritdoc cref="IRequestMessage.DateTime" />
|
||||||
public DateTime DateTime { get; set; }
|
public DateTime DateTime { get; set; }
|
||||||
@@ -91,16 +92,36 @@ public class RequestMessage : IRequestMessage
|
|||||||
/// <inheritdoc cref="IRequestMessage.Origin" />
|
/// <inheritdoc cref="IRequestMessage.Origin" />
|
||||||
public string Origin { get; }
|
public string Origin { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Used for Unit Testing
|
||||||
|
/// </summary>
|
||||||
|
public RequestMessage(
|
||||||
|
UrlDetails urlDetails,
|
||||||
|
string method,
|
||||||
|
string clientIP,
|
||||||
|
IBodyData? bodyData = null,
|
||||||
|
IDictionary<string, string[]>? headers = null,
|
||||||
|
IDictionary<string, string>? cookies = null) : this(null, urlDetails, method, clientIP, bodyData, headers, cookies)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RequestMessage"/> class.
|
/// Initializes a new instance of the <see cref="RequestMessage"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
/// <param name="options">The<seealso cref="IWireMockMiddlewareOptions"/>.</param>
|
||||||
/// <param name="urlDetails">The original url details.</param>
|
/// <param name="urlDetails">The original url details.</param>
|
||||||
/// <param name="method">The HTTP method.</param>
|
/// <param name="method">The HTTP method.</param>
|
||||||
/// <param name="clientIP">The client IP Address.</param>
|
/// <param name="clientIP">The client IP Address.</param>
|
||||||
/// <param name="bodyData">The BodyData.</param>
|
/// <param name="bodyData">The BodyData.</param>
|
||||||
/// <param name="headers">The headers.</param>
|
/// <param name="headers">The headers.</param>
|
||||||
/// <param name="cookies">The cookies.</param>
|
/// <param name="cookies">The cookies.</param>
|
||||||
public RequestMessage(UrlDetails urlDetails, string method, string clientIP, IBodyData? bodyData = null, IDictionary<string, string[]>? headers = null, IDictionary<string, string>? cookies = null)
|
internal RequestMessage(
|
||||||
|
IWireMockMiddlewareOptions? options,
|
||||||
|
UrlDetails urlDetails, string method,
|
||||||
|
string clientIP,
|
||||||
|
IBodyData? bodyData = null,
|
||||||
|
IDictionary<string, string[]>? headers = null,
|
||||||
|
IDictionary<string, string>? cookies = null)
|
||||||
{
|
{
|
||||||
Guard.NotNull(urlDetails, nameof(urlDetails));
|
Guard.NotNull(urlDetails, nameof(urlDetails));
|
||||||
Guard.NotNull(method, nameof(method));
|
Guard.NotNull(method, nameof(method));
|
||||||
@@ -134,7 +155,7 @@ public class RequestMessage : IRequestMessage
|
|||||||
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
|
||||||
Cookies = cookies;
|
Cookies = cookies;
|
||||||
RawQuery = urlDetails.Url.Query;
|
RawQuery = urlDetails.Url.Query;
|
||||||
Query = QueryStringParser.Parse(RawQuery);
|
Query = QueryStringParser.Parse(RawQuery, options?.QueryParameterMultipleValueSupport);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
|
|||||||
@@ -21,7 +21,8 @@ public partial class Response
|
|||||||
{
|
{
|
||||||
DetectedBodyType = BodyType.String,
|
DetectedBodyType = BodyType.String,
|
||||||
BodyAsString = bodyFactory(req),
|
BodyAsString = bodyFactory(req),
|
||||||
Encoding = encoding ?? Encoding.UTF8
|
Encoding = encoding ?? Encoding.UTF8,
|
||||||
|
IsFuncUsed = "Func<IRequestMessage, string>"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
@@ -37,7 +38,8 @@ public partial class Response
|
|||||||
{
|
{
|
||||||
DetectedBodyType = BodyType.String,
|
DetectedBodyType = BodyType.String,
|
||||||
BodyAsString = await bodyFactory(req).ConfigureAwait(false),
|
BodyAsString = await bodyFactory(req).ConfigureAwait(false),
|
||||||
Encoding = encoding ?? Encoding.UTF8
|
Encoding = encoding ?? Encoding.UTF8,
|
||||||
|
IsFuncUsed = "Func<IRequestMessage, Task<string>>"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -325,15 +325,15 @@ public partial class Response : IResponseBuilder
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
throw new NotImplementedException($"TransformerType '{TransformerType}' is not supported.");
|
throw new NotSupportedException($"TransformerType '{TransformerType}' is not supported.");
|
||||||
}
|
}
|
||||||
|
|
||||||
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
return (responseMessageTransformer.Transform(mapping, requestMessage, responseMessage, UseTransformerForBodyAsFile, TransformerReplaceNodeOptions), null);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true)
|
if (!UseTransformer && ResponseMessage.BodyData?.BodyAsFileIsCached == true && responseMessage.BodyData?.BodyAsFile is not null)
|
||||||
{
|
{
|
||||||
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData!.BodyAsFile);
|
ResponseMessage.BodyData.BodyAsBytes = settings.FileSystemHandler.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile);
|
||||||
}
|
}
|
||||||
|
|
||||||
return (responseMessage, null);
|
return (responseMessage, null);
|
||||||
|
|||||||
@@ -8,7 +8,7 @@ public class ScenarioState
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Name (from the Scenario).
|
/// Gets or sets the Name (from the Scenario).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Name { get; set; }
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the NextState.
|
/// Gets or sets the NextState.
|
||||||
|
|||||||
@@ -1,16 +1,25 @@
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Owin;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Serialization;
|
namespace WireMock.Serialization;
|
||||||
|
|
||||||
internal static class LogEntryMapper
|
internal class LogEntryMapper
|
||||||
{
|
{
|
||||||
public static LogEntryModel Map(ILogEntry logEntry)
|
private readonly IWireMockMiddlewareOptions _options;
|
||||||
|
|
||||||
|
public LogEntryMapper(IWireMockMiddlewareOptions options)
|
||||||
|
{
|
||||||
|
_options = Guard.NotNull(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
public LogEntryModel Map(ILogEntry logEntry)
|
||||||
{
|
{
|
||||||
var logRequestModel = new LogRequestModel
|
var logRequestModel = new LogRequestModel
|
||||||
{
|
{
|
||||||
@@ -78,25 +87,7 @@ internal static class LogEntryMapper
|
|||||||
logResponseModel.DetectedBodyType = logEntry.ResponseMessage.BodyData.DetectedBodyType;
|
logResponseModel.DetectedBodyType = logEntry.ResponseMessage.BodyData.DetectedBodyType;
|
||||||
logResponseModel.DetectedBodyTypeFromContentType = logEntry.ResponseMessage.BodyData.DetectedBodyTypeFromContentType;
|
logResponseModel.DetectedBodyTypeFromContentType = logEntry.ResponseMessage.BodyData.DetectedBodyTypeFromContentType;
|
||||||
|
|
||||||
switch (logEntry.ResponseMessage.BodyData.DetectedBodyType)
|
MapBody(logEntry, logResponseModel);
|
||||||
{
|
|
||||||
case BodyType.String:
|
|
||||||
logResponseModel.Body = logEntry.ResponseMessage.BodyData.BodyAsString;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BodyType.Json:
|
|
||||||
logResponseModel.BodyAsJson = logEntry.ResponseMessage.BodyData.BodyAsJson;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BodyType.Bytes:
|
|
||||||
logResponseModel.BodyAsBytes = logEntry.ResponseMessage.BodyData.BodyAsBytes;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case BodyType.File:
|
|
||||||
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
|
||||||
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
logResponseModel.BodyEncoding = logEntry.ResponseMessage.BodyData.Encoding != null
|
logResponseModel.BodyEncoding = logEntry.ResponseMessage.BodyData.Encoding != null
|
||||||
? new EncodingModel
|
? new EncodingModel
|
||||||
@@ -124,6 +115,36 @@ internal static class LogEntryMapper
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void MapBody(ILogEntry logEntry, LogResponseModel logResponseModel)
|
||||||
|
{
|
||||||
|
switch (logEntry.ResponseMessage.BodyData!.DetectedBodyType)
|
||||||
|
{
|
||||||
|
case BodyType.String:
|
||||||
|
if (!string.IsNullOrEmpty(logEntry.ResponseMessage.BodyData.IsFuncUsed) && _options.DoNotSaveDynamicResponseInLogEntry == true)
|
||||||
|
{
|
||||||
|
logResponseModel.Body = logEntry.ResponseMessage.BodyData.IsFuncUsed;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
logResponseModel.Body = logEntry.ResponseMessage.BodyData.BodyAsString;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BodyType.Json:
|
||||||
|
logResponseModel.BodyAsJson = logEntry.ResponseMessage.BodyData.BodyAsJson;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BodyType.Bytes:
|
||||||
|
logResponseModel.BodyAsBytes = logEntry.ResponseMessage.BodyData.BodyAsBytes;
|
||||||
|
break;
|
||||||
|
|
||||||
|
case BodyType.File:
|
||||||
|
logResponseModel.BodyAsFile = logEntry.ResponseMessage.BodyData.BodyAsFile;
|
||||||
|
logResponseModel.BodyAsFileIsCached = logEntry.ResponseMessage.BodyData.BodyAsFileIsCached;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
private static LogRequestMatchModel? Map(IRequestMatchResult? matchResult)
|
private static LogRequestMatchModel? Map(IRequestMatchResult? matchResult)
|
||||||
{
|
{
|
||||||
if (matchResult == null)
|
if (matchResult == null)
|
||||||
|
|||||||
@@ -13,11 +13,8 @@ internal class MappingToFileSaver
|
|||||||
|
|
||||||
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
|
public MappingToFileSaver(WireMockServerSettings settings, MappingConverter mappingConverter)
|
||||||
{
|
{
|
||||||
Guard.NotNull(settings);
|
_settings = Guard.NotNull(settings);
|
||||||
Guard.NotNull(mappingConverter);
|
_mappingConverter = Guard.NotNull(mappingConverter);
|
||||||
|
|
||||||
_settings = settings;
|
|
||||||
_mappingConverter = mappingConverter;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public void SaveMappingToFile(IMapping mapping, string? folder = null)
|
public void SaveMappingToFile(IMapping mapping, string? folder = null)
|
||||||
@@ -30,17 +27,31 @@ internal class MappingToFileSaver
|
|||||||
}
|
}
|
||||||
|
|
||||||
var model = _mappingConverter.ToMappingModel(mapping);
|
var model = _mappingConverter.ToMappingModel(mapping);
|
||||||
string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
|
|
||||||
|
|
||||||
string path = Path.Combine(folder, filename);
|
var filename = BuildSanitizedFileName(mapping);
|
||||||
|
var path = Path.Combine(folder, filename);
|
||||||
|
|
||||||
_settings.Logger.Info("Saving Mapping file {0}", filename);
|
_settings.Logger.Info("Saving Mapping file {0}", path);
|
||||||
|
|
||||||
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
|
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string SanitizeFileName(string name, char replaceChar = '_')
|
private string BuildSanitizedFileName(IMapping mapping, char replaceChar = '_')
|
||||||
{
|
{
|
||||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
|
string name;
|
||||||
|
if (!string.IsNullOrEmpty(mapping.Title))
|
||||||
|
{
|
||||||
|
name = mapping.Title!;
|
||||||
|
if (_settings.ProxyAndRecordSettings?.AppendGuidToSavedMappingFile == true)
|
||||||
|
{
|
||||||
|
name += $"{replaceChar}{mapping.Guid}";
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
name = mapping.Guid.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar))}.json";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -125,9 +125,9 @@ public interface IRespondWithAProvider
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Support FireAndForget for any configured Webhooks
|
/// Support FireAndForget for any configured Webhooks
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="UseWebhooksFireAndForget"></param>
|
/// <param name="useWebhooksFireAndForget"></param>
|
||||||
/// <returns></returns>
|
/// <returns></returns>
|
||||||
IRespondWithAProvider WithWebhookFireAndForget(bool UseWebhooksFireAndForget);
|
IRespondWithAProvider WithWebhookFireAndForget(bool useWebhooksFireAndForget);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a Webhook to call after the response has been generated.
|
/// Add a Webhook to call after the response has been generated.
|
||||||
@@ -141,7 +141,7 @@ public interface IRespondWithAProvider
|
|||||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
IRespondWithAProvider WithWebhook(
|
IRespondWithAProvider WithWebhook(
|
||||||
string url,
|
string url,
|
||||||
string? method = "post",
|
string method = "post",
|
||||||
IDictionary<string, WireMockList<string>>? headers = null,
|
IDictionary<string, WireMockList<string>>? headers = null,
|
||||||
string? body = null,
|
string? body = null,
|
||||||
bool useTransformer = true,
|
bool useTransformer = true,
|
||||||
@@ -160,7 +160,7 @@ public interface IRespondWithAProvider
|
|||||||
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
IRespondWithAProvider WithWebhook(
|
IRespondWithAProvider WithWebhook(
|
||||||
string url,
|
string url,
|
||||||
string? method = "post",
|
string method = "post",
|
||||||
IDictionary<string, WireMockList<string>>? headers = null,
|
IDictionary<string, WireMockList<string>>? headers = null,
|
||||||
object? body = null,
|
object? body = null,
|
||||||
bool useTransformer = true,
|
bool useTransformer = true,
|
||||||
|
|||||||
@@ -30,7 +30,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
|
|||||||
private readonly WireMockServerSettings _settings;
|
private readonly WireMockServerSettings _settings;
|
||||||
private readonly bool _saveToFile;
|
private readonly bool _saveToFile;
|
||||||
|
|
||||||
private bool _useWebhookFireAndForget = false;
|
private bool _useWebhookFireAndForget;
|
||||||
|
|
||||||
public Guid Guid { get; private set; } = Guid.NewGuid();
|
public Guid Guid { get; private set; } = Guid.NewGuid();
|
||||||
|
|
||||||
|
|||||||
@@ -3,9 +3,7 @@ using System.Collections.Generic;
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Net.Http;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
@@ -18,11 +16,9 @@ using WireMock.Http;
|
|||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
using WireMock.Proxy;
|
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseProviders;
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Serialization;
|
using WireMock.Serialization;
|
||||||
using WireMock.Settings;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -46,6 +42,8 @@ public partial class WireMockServer
|
|||||||
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
|
private static readonly RegexMatcher AdminRequestContentTypeJson = new ContentTypeMatcher(WireMockConstants.ContentTypeJson, true);
|
||||||
private static readonly RegexMatcher AdminMappingsGuidPathMatcher = new(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
private static readonly RegexMatcher AdminMappingsGuidPathMatcher = new(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||||
private static readonly RegexMatcher AdminRequestsGuidPathMatcher = new(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
private static readonly RegexMatcher AdminRequestsGuidPathMatcher = new(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||||
|
private static readonly RegexMatcher AdminScenariosNameMatcher = new(@"^\/__admin\/scenarios\/.+$");
|
||||||
|
private static readonly RegexMatcher AdminScenariosNameWithResetMatcher = new(@"^\/__admin\/scenarios\/.+\/reset$");
|
||||||
|
|
||||||
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
private EnhancedFileSystemWatcher? _enhancedFileSystemWatcher;
|
||||||
|
|
||||||
@@ -93,9 +91,11 @@ public partial class WireMockServer
|
|||||||
// __admin/scenarios
|
// __admin/scenarios
|
||||||
Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet));
|
Given(Request.Create().WithPath(AdminScenarios).UsingGet()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosGet));
|
||||||
Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
|
Given(Request.Create().WithPath(AdminScenarios).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
|
||||||
|
Given(Request.Create().WithPath(AdminScenariosNameMatcher).UsingDelete()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
|
||||||
|
|
||||||
// __admin/scenarios/reset
|
// __admin/scenarios/reset
|
||||||
Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
|
Given(Request.Create().WithPath(AdminScenarios + "/reset").UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenariosReset));
|
||||||
|
Given(Request.Create().WithPath(AdminScenariosNameWithResetMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(ScenarioReset));
|
||||||
|
|
||||||
// __admin/files/{filename}
|
// __admin/files/{filename}
|
||||||
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
|
Given(Request.Create().WithPath(_adminFilesFilenamePathMatcher).UsingPost()).AtPriority(WireMockConstants.AdminPriority).RespondWith(new DynamicResponseProvider(FilePost));
|
||||||
@@ -204,62 +204,6 @@ public partial class WireMockServer
|
|||||||
}
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Proxy and Record
|
|
||||||
private HttpClient? _httpClientForProxy;
|
|
||||||
|
|
||||||
private void InitProxyAndRecord(WireMockServerSettings settings)
|
|
||||||
{
|
|
||||||
if (settings.ProxyAndRecordSettings == null)
|
|
||||||
{
|
|
||||||
_httpClientForProxy = null;
|
|
||||||
DeleteMapping(ProxyMappingGuid);
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
_httpClientForProxy = HttpClientBuilder.Build(settings.ProxyAndRecordSettings);
|
|
||||||
|
|
||||||
var proxyRespondProvider = Given(Request.Create().WithPath("/*").UsingAnyMethod()).WithGuid(ProxyMappingGuid).WithTitle("Default Proxy Mapping on /*");
|
|
||||||
if (settings.StartAdminInterface == true)
|
|
||||||
{
|
|
||||||
proxyRespondProvider.AtPriority(WireMockConstants.ProxyPriority);
|
|
||||||
}
|
|
||||||
|
|
||||||
proxyRespondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task<IResponseMessage> ProxyAndRecordAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
|
||||||
{
|
|
||||||
var requestUri = new Uri(requestMessage.Url);
|
|
||||||
var proxyUri = new Uri(settings.ProxyAndRecordSettings!.Url);
|
|
||||||
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
|
||||||
|
|
||||||
var proxyHelper = new ProxyHelper(settings);
|
|
||||||
|
|
||||||
var (responseMessage, mapping) = await proxyHelper.SendAsync(
|
|
||||||
null,
|
|
||||||
_settings.ProxyAndRecordSettings!,
|
|
||||||
_httpClientForProxy!,
|
|
||||||
requestMessage,
|
|
||||||
proxyUriWithRequestPathAndQuery.AbsoluteUri
|
|
||||||
).ConfigureAwait(false);
|
|
||||||
|
|
||||||
if (mapping != null)
|
|
||||||
{
|
|
||||||
if (settings.ProxyAndRecordSettings.SaveMapping)
|
|
||||||
{
|
|
||||||
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (settings.ProxyAndRecordSettings.SaveMappingToFile)
|
|
||||||
{
|
|
||||||
_mappingToFileSaver.SaveMappingToFile(mapping);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return responseMessage;
|
|
||||||
}
|
|
||||||
#endregion
|
|
||||||
|
|
||||||
#region Settings
|
#region Settings
|
||||||
private IResponseMessage SettingsGet(IRequestMessage requestMessage)
|
private IResponseMessage SettingsGet(IRequestMessage requestMessage)
|
||||||
{
|
{
|
||||||
@@ -277,6 +221,9 @@ public partial class WireMockServer
|
|||||||
UseRegexExtended = _settings.UseRegexExtended,
|
UseRegexExtended = _settings.UseRegexExtended,
|
||||||
WatchStaticMappings = _settings.WatchStaticMappings,
|
WatchStaticMappings = _settings.WatchStaticMappings,
|
||||||
WatchStaticMappingsInSubdirectories = _settings.WatchStaticMappingsInSubdirectories,
|
WatchStaticMappingsInSubdirectories = _settings.WatchStaticMappingsInSubdirectories,
|
||||||
|
HostingScheme = _settings.HostingScheme,
|
||||||
|
DoNotSaveDynamicResponseInLogEntry = _settings.DoNotSaveDynamicResponseInLogEntry,
|
||||||
|
QueryParameterMultipleValueSupport = _settings.QueryParameterMultipleValueSupport,
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
CorsPolicyOptions = _settings.CorsPolicyOptions?.ToString()
|
CorsPolicyOptions = _settings.CorsPolicyOptions?.ToString()
|
||||||
@@ -305,6 +252,8 @@ public partial class WireMockServer
|
|||||||
_settings.UseRegexExtended = settings.UseRegexExtended;
|
_settings.UseRegexExtended = settings.UseRegexExtended;
|
||||||
_settings.WatchStaticMappings = settings.WatchStaticMappings;
|
_settings.WatchStaticMappings = settings.WatchStaticMappings;
|
||||||
_settings.WatchStaticMappingsInSubdirectories = settings.WatchStaticMappingsInSubdirectories;
|
_settings.WatchStaticMappingsInSubdirectories = settings.WatchStaticMappingsInSubdirectories;
|
||||||
|
_settings.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||||
|
_settings.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||||
|
|
||||||
InitSettings(_settings);
|
InitSettings(_settings);
|
||||||
|
|
||||||
@@ -525,7 +474,7 @@ public partial class WireMockServer
|
|||||||
return ResponseMessageBuilder.Create("Request not found", 404);
|
return ResponseMessageBuilder.Create("Request not found", 404);
|
||||||
}
|
}
|
||||||
|
|
||||||
var model = LogEntryMapper.Map(entry);
|
var model = new LogEntryMapper(_options).Map(entry);
|
||||||
|
|
||||||
return ToJson(model);
|
return ToJson(model);
|
||||||
}
|
}
|
||||||
@@ -546,9 +495,10 @@ public partial class WireMockServer
|
|||||||
#region Requests
|
#region Requests
|
||||||
private IResponseMessage RequestsGet(IRequestMessage requestMessage)
|
private IResponseMessage RequestsGet(IRequestMessage requestMessage)
|
||||||
{
|
{
|
||||||
|
var logEntryMapper = new LogEntryMapper(_options);
|
||||||
var result = LogEntries
|
var result = LogEntries
|
||||||
.Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
|
.Where(r => !r.RequestMessage.Path.StartsWith("/__admin/"))
|
||||||
.Select(LogEntryMapper.Map);
|
.Select(logEntryMapper.Map);
|
||||||
|
|
||||||
return ToJson(result);
|
return ToJson(result);
|
||||||
}
|
}
|
||||||
@@ -578,7 +528,8 @@ public partial class WireMockServer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(LogEntryMapper.Map);
|
var logEntryMapper = new LogEntryMapper(_options);
|
||||||
|
var result = dict.OrderBy(x => x.Value.AverageTotalScore).Select(x => x.Key).Select(logEntryMapper.Map);
|
||||||
|
|
||||||
return ToJson(result);
|
return ToJson(result);
|
||||||
}
|
}
|
||||||
@@ -605,6 +556,17 @@ public partial class WireMockServer
|
|||||||
|
|
||||||
return ResponseMessageBuilder.Create("Scenarios reset");
|
return ResponseMessageBuilder.Create("Scenarios reset");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private IResponseMessage ScenarioReset(IRequestMessage requestMessage)
|
||||||
|
{
|
||||||
|
var name = string.Equals(HttpRequestMethod.DELETE, requestMessage.Method, StringComparison.OrdinalIgnoreCase) ?
|
||||||
|
requestMessage.Path.Substring(AdminScenarios.Length + 1) :
|
||||||
|
requestMessage.Path.Split('/').Reverse().Skip(1).First();
|
||||||
|
|
||||||
|
return ResetScenario(name) ?
|
||||||
|
ResponseMessageBuilder.Create("Scenario reset") :
|
||||||
|
ResponseMessageBuilder.Create($"No scenario found by name '{name}'.", 404);
|
||||||
|
}
|
||||||
#endregion
|
#endregion
|
||||||
|
|
||||||
#region Pact
|
#region Pact
|
||||||
|
|||||||
68
src/WireMock.Net/Server/WireMockServer.Proxy.cs
Normal file
68
src/WireMock.Net/Server/WireMockServer.Proxy.cs
Normal file
@@ -0,0 +1,68 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net.Http;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using WireMock.Constants;
|
||||||
|
using WireMock.Http;
|
||||||
|
using WireMock.Proxy;
|
||||||
|
using WireMock.RequestBuilders;
|
||||||
|
using WireMock.ResponseProviders;
|
||||||
|
using WireMock.Settings;
|
||||||
|
|
||||||
|
namespace WireMock.Server;
|
||||||
|
|
||||||
|
public partial class WireMockServer
|
||||||
|
{
|
||||||
|
private HttpClient? _httpClientForProxy;
|
||||||
|
|
||||||
|
private void InitProxyAndRecord(WireMockServerSettings settings)
|
||||||
|
{
|
||||||
|
if (settings.ProxyAndRecordSettings == null)
|
||||||
|
{
|
||||||
|
_httpClientForProxy = null;
|
||||||
|
DeleteMapping(ProxyMappingGuid);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
_httpClientForProxy = HttpClientBuilder.Build(settings.ProxyAndRecordSettings);
|
||||||
|
|
||||||
|
var proxyRespondProvider = Given(Request.Create().WithPath("/*").UsingAnyMethod()).WithGuid(ProxyMappingGuid).WithTitle("Default Proxy Mapping on /*");
|
||||||
|
if (settings.StartAdminInterface == true)
|
||||||
|
{
|
||||||
|
proxyRespondProvider.AtPriority(WireMockConstants.ProxyPriority);
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyRespondProvider.RespondWith(new ProxyAsyncResponseProvider(ProxyAndRecordAsync, settings));
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task<IResponseMessage> ProxyAndRecordAsync(IRequestMessage requestMessage, WireMockServerSettings settings)
|
||||||
|
{
|
||||||
|
var requestUri = new Uri(requestMessage.Url);
|
||||||
|
var proxyUri = new Uri(settings.ProxyAndRecordSettings!.Url);
|
||||||
|
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
||||||
|
|
||||||
|
var proxyHelper = new ProxyHelper(settings);
|
||||||
|
|
||||||
|
var (responseMessage, mapping) = await proxyHelper.SendAsync(
|
||||||
|
null,
|
||||||
|
_settings.ProxyAndRecordSettings!,
|
||||||
|
_httpClientForProxy!,
|
||||||
|
requestMessage,
|
||||||
|
proxyUriWithRequestPathAndQuery.AbsoluteUri
|
||||||
|
).ConfigureAwait(false);
|
||||||
|
|
||||||
|
if (mapping != null)
|
||||||
|
{
|
||||||
|
if (settings.ProxyAndRecordSettings.SaveMapping)
|
||||||
|
{
|
||||||
|
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (settings.ProxyAndRecordSettings.SaveMappingToFile)
|
||||||
|
{
|
||||||
|
_mappingToFileSaver.SaveMappingToFile(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return responseMessage;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -295,6 +295,8 @@ public partial class WireMockServer : IWireMockServer
|
|||||||
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
|
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
|
||||||
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||||
_options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
_options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||||
|
_options.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||||
|
_options.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||||
|
|
||||||
if (settings.CustomCertificateDefined)
|
if (settings.CustomCertificateDefined)
|
||||||
{
|
{
|
||||||
@@ -476,6 +478,13 @@ public partial class WireMockServer : IWireMockServer
|
|||||||
_options.Scenarios.Clear();
|
_options.Scenarios.Clear();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[PublicAPI]
|
||||||
|
public bool ResetScenario(string name)
|
||||||
|
{
|
||||||
|
return _options.Scenarios.ContainsKey(name) && _options.Scenarios.TryRemove(name, out _);
|
||||||
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockServer.WithMapping(MappingModel[])" />
|
/// <inheritdoc cref="IWireMockServer.WithMapping(MappingModel[])" />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IWireMockServer WithMapping(params MappingModel[] mappings)
|
public IWireMockServer WithMapping(params MappingModel[] mappings)
|
||||||
|
|||||||
@@ -58,4 +58,9 @@ public class ProxyAndRecordSettings : HttpClientSettings
|
|||||||
/// Default value is false.
|
/// Default value is false.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool UseDefinedRequestMatchers { get; set; }
|
public bool UseDefinedRequestMatchers { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Append an unique GUID to the filename from the saved mapping file.
|
||||||
|
/// </summary>
|
||||||
|
public bool AppendGuidToSavedMappingFile { get; set; }
|
||||||
}
|
}
|
||||||
@@ -12,7 +12,6 @@ using WireMock.RegularExpressions;
|
|||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.Types;
|
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
namespace WireMock.Settings
|
namespace WireMock.Settings
|
||||||
@@ -253,6 +252,20 @@ namespace WireMock.Settings
|
|||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public bool? SaveUnmatchedRequests { get; set; }
|
public bool? SaveUnmatchedRequests { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// See <seealso cref="QueryParameterMultipleValueSupport"/>.
|
||||||
|
///
|
||||||
|
/// Default value = "All".
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Custom matcher mappings for static mappings
|
/// Custom matcher mappings for static mappings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,4 +1,3 @@
|
|||||||
using System;
|
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
@@ -54,20 +53,32 @@ public static class WireMockServerSettingsParser
|
|||||||
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
|
UseRegexExtended = parser.GetBoolValue(nameof(WireMockServerSettings.UseRegexExtended), true),
|
||||||
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
|
WatchStaticMappings = parser.GetBoolValue("WatchStaticMappings"),
|
||||||
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
WatchStaticMappingsInSubdirectories = parser.GetBoolValue("WatchStaticMappingsInSubdirectories"),
|
||||||
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme))
|
HostingScheme = parser.GetEnumValue<HostingScheme>(nameof(WireMockServerSettings.HostingScheme)),
|
||||||
|
DoNotSaveDynamicResponseInLogEntry = parser.GetBoolValue(nameof(WireMockServerSettings.DoNotSaveDynamicResponseInLogEntry)),
|
||||||
|
QueryParameterMultipleValueSupport = parser.GetEnumValue<QueryParameterMultipleValueSupport>(nameof(WireMockServerSettings.QueryParameterMultipleValueSupport))
|
||||||
};
|
};
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
settings.CorsPolicyOptions = parser.GetEnumValue(nameof(WireMockServerSettings.CorsPolicyOptions), CorsPolicyOptions.None);
|
settings.CorsPolicyOptions = parser.GetEnumValue(nameof(WireMockServerSettings.CorsPolicyOptions), CorsPolicyOptions.None);
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
var loggerType = parser.GetStringValue("WireMockLogger");
|
||||||
|
switch (loggerType)
|
||||||
|
{
|
||||||
|
case nameof(WireMockConsoleLogger):
|
||||||
|
settings.Logger = new WireMockConsoleLogger();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case nameof(WireMockNullLogger):
|
||||||
|
settings.Logger = new WireMockNullLogger();
|
||||||
|
break;
|
||||||
|
|
||||||
|
default:
|
||||||
if (logger != null)
|
if (logger != null)
|
||||||
{
|
{
|
||||||
settings.Logger = logger;
|
settings.Logger = logger;
|
||||||
}
|
}
|
||||||
else if (parser.GetStringValue("WireMockLogger") == "WireMockConsoleLogger")
|
break;
|
||||||
{
|
|
||||||
settings.Logger = new WireMockConsoleLogger();
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (parser.Contains(nameof(WireMockServerSettings.Port)))
|
if (parser.Contains(nameof(WireMockServerSettings.Port)))
|
||||||
@@ -93,6 +104,7 @@ public static class WireMockServerSettingsParser
|
|||||||
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
|
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern", "*"),
|
||||||
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
|
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
|
||||||
UseDefinedRequestMatchers = parser.GetBoolValue(nameof(ProxyAndRecordSettings.UseDefinedRequestMatchers)),
|
UseDefinedRequestMatchers = parser.GetBoolValue(nameof(ProxyAndRecordSettings.UseDefinedRequestMatchers)),
|
||||||
|
AppendGuidToSavedMappingFile = parser.GetBoolValue(nameof(ProxyAndRecordSettings.AppendGuidToSavedMappingFile)),
|
||||||
Url = proxyUrl!
|
Url = proxyUrl!
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ interface ITransformer
|
|||||||
|
|
||||||
IBodyData? TransformBody(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, ReplaceNodeOptions options);
|
IBodyData? TransformBody(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IBodyData? bodyData, ReplaceNodeOptions options);
|
||||||
|
|
||||||
IDictionary<string, WireMockList<string>>? TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
|
IDictionary<string, WireMockList<string>> TransformHeaders(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, IDictionary<string, WireMockList<string>>? headers);
|
||||||
|
|
||||||
string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value);
|
string TransformString(IMapping mapping, IRequestMessage originalRequestMessage, IResponseMessage originalResponseMessage, string? value);
|
||||||
}
|
}
|
||||||
@@ -36,7 +36,7 @@ internal class Transformer : ITransformer
|
|||||||
return newBodyData;
|
return newBodyData;
|
||||||
}
|
}
|
||||||
|
|
||||||
public IDictionary<string, WireMockList<string>>? TransformHeaders(
|
public IDictionary<string, WireMockList<string>> TransformHeaders(
|
||||||
IMapping mapping,
|
IMapping mapping,
|
||||||
IRequestMessage originalRequestMessage,
|
IRequestMessage originalRequestMessage,
|
||||||
IResponseMessage originalResponseMessage,
|
IResponseMessage originalResponseMessage,
|
||||||
@@ -239,6 +239,7 @@ internal class Transformer : ITransformer
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// ReSharper disable once UnusedParameter.Local
|
||||||
private static void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, string transformedString)
|
private static void ReplaceNodeValue(ReplaceNodeOptions options, JToken node, string transformedString)
|
||||||
{
|
{
|
||||||
StringUtils.TryParseQuotedString(transformedString, out var result, out _);
|
StringUtils.TryParseQuotedString(transformedString, out var result, out _);
|
||||||
@@ -270,13 +271,13 @@ internal class Transformer : ITransformer
|
|||||||
Encoding = original.Encoding,
|
Encoding = original.Encoding,
|
||||||
DetectedBodyType = original.DetectedBodyType,
|
DetectedBodyType = original.DetectedBodyType,
|
||||||
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
DetectedBodyTypeFromContentType = original.DetectedBodyTypeFromContentType,
|
||||||
BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString, model)
|
BodyAsString = handlebarsContext.ParseAndRender(original.BodyAsString!, model)
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IBodyData TransformBodyAsFile(ITransformerContext handlebarsContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
private static IBodyData TransformBodyAsFile(ITransformerContext handlebarsContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile, model);
|
string transformedBodyAsFilename = handlebarsContext.ParseAndRender(original.BodyAsFile!, model);
|
||||||
|
|
||||||
if (!useTransformerForBodyAsFile)
|
if (!useTransformerForBodyAsFile)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -5,7 +5,7 @@ using System.Net.Http.Headers;
|
|||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Http;
|
using WireMock.Constants;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
@@ -29,15 +29,15 @@ internal static class BodyParser
|
|||||||
*/
|
*/
|
||||||
private static readonly IDictionary<string, bool> BodyAllowedForMethods = new Dictionary<string, bool>
|
private static readonly IDictionary<string, bool> BodyAllowedForMethods = new Dictionary<string, bool>
|
||||||
{
|
{
|
||||||
{ HttpRequestMethods.HEAD, false },
|
{ HttpRequestMethod.HEAD, false },
|
||||||
{ HttpRequestMethods.GET, false },
|
{ HttpRequestMethod.GET, false },
|
||||||
{ HttpRequestMethods.PUT, true },
|
{ HttpRequestMethod.PUT, true },
|
||||||
{ HttpRequestMethods.POST, true },
|
{ HttpRequestMethod.POST, true },
|
||||||
{ HttpRequestMethods.DELETE, true },
|
{ HttpRequestMethod.DELETE, true },
|
||||||
{ HttpRequestMethods.TRACE, false },
|
{ HttpRequestMethod.TRACE, false },
|
||||||
{ HttpRequestMethods.OPTIONS, true },
|
{ HttpRequestMethod.OPTIONS, true },
|
||||||
{ HttpRequestMethods.CONNECT, false },
|
{ HttpRequestMethod.CONNECT, false },
|
||||||
{ HttpRequestMethods.PATCH, true }
|
{ HttpRequestMethod.PATCH, true }
|
||||||
};
|
};
|
||||||
|
|
||||||
private static readonly IStringMatcher[] MultipartContentTypesMatchers = {
|
private static readonly IStringMatcher[] MultipartContentTypesMatchers = {
|
||||||
@@ -122,7 +122,7 @@ internal static class BodyParser
|
|||||||
// In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is
|
// In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is
|
||||||
if (data.DetectedBodyTypeFromContentType == BodyType.MultiPart)
|
if (data.DetectedBodyTypeFromContentType == BodyType.MultiPart)
|
||||||
{
|
{
|
||||||
if (BytesEncodingUtils.TryGetEncoding(data.BodyAsBytes, out Encoding encoding) &&
|
if (BytesEncodingUtils.TryGetEncoding(data.BodyAsBytes, out var encoding) &&
|
||||||
SupportedBodyAsStringEncodingForMultipart.Select(x => x.Equals(encoding)).Any())
|
SupportedBodyAsStringEncodingForMultipart.Select(x => x.Equals(encoding)).Any())
|
||||||
{
|
{
|
||||||
data.BodyAsString = encoding.GetString(data.BodyAsBytes);
|
data.BodyAsString = encoding.GetString(data.BodyAsBytes);
|
||||||
|
|||||||
@@ -11,25 +11,41 @@ namespace WireMock.Util;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
internal static class QueryStringParser
|
internal static class QueryStringParser
|
||||||
{
|
{
|
||||||
public static IDictionary<string, WireMockList<string>> Parse(string queryString)
|
private static readonly Dictionary<string, WireMockList<string>> Empty = new();
|
||||||
|
|
||||||
|
public static IDictionary<string, WireMockList<string>> Parse(string? queryString, QueryParameterMultipleValueSupport? support = null)
|
||||||
{
|
{
|
||||||
if (string.IsNullOrEmpty(queryString))
|
if (string.IsNullOrEmpty(queryString))
|
||||||
{
|
{
|
||||||
return new Dictionary<string, WireMockList<string>>();
|
return Empty;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var queryParameterMultipleValueSupport = support ?? QueryParameterMultipleValueSupport.All;
|
||||||
|
|
||||||
string[] JoinParts(string[] parts)
|
string[] JoinParts(string[] parts)
|
||||||
{
|
{
|
||||||
if (parts.Length > 1)
|
if (parts.Length > 1)
|
||||||
{
|
{
|
||||||
return parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries); // support "?key=1,2"
|
return queryParameterMultipleValueSupport.HasFlag(QueryParameterMultipleValueSupport.Comma) ?
|
||||||
|
parts[1].Split(new[] { "," }, StringSplitOptions.RemoveEmptyEntries) : // Support "?key=1,2"
|
||||||
|
new[] { parts[1] };
|
||||||
}
|
}
|
||||||
|
|
||||||
return new string[0];
|
return new string[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
return queryString.TrimStart('?')
|
var splitOn = new List<string>();
|
||||||
.Split(new[] { '&', ';' }, StringSplitOptions.RemoveEmptyEntries) // Support "?key=value;key=anotherValue" and "?key=value&key=anotherValue"
|
if (queryParameterMultipleValueSupport.HasFlag(QueryParameterMultipleValueSupport.Ampersand))
|
||||||
|
{
|
||||||
|
splitOn.Add("&"); // Support "?key=value&key=anotherValue"
|
||||||
|
}
|
||||||
|
if (queryParameterMultipleValueSupport.HasFlag(QueryParameterMultipleValueSupport.SemiColon))
|
||||||
|
{
|
||||||
|
splitOn.Add(";"); // Support "?key=value;key=anotherValue"
|
||||||
|
}
|
||||||
|
|
||||||
|
return queryString!.TrimStart('?')
|
||||||
|
.Split(splitOn.ToArray(), StringSplitOptions.RemoveEmptyEntries)
|
||||||
.Select(parameter => parameter.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries))
|
.Select(parameter => parameter.Split(new[] { '=' }, 2, StringSplitOptions.RemoveEmptyEntries))
|
||||||
.GroupBy(parts => parts[0], JoinParts)
|
.GroupBy(parts => parts[0], JoinParts)
|
||||||
.ToDictionary(grouping => grouping.Key, grouping => new WireMockList<string>(grouping.SelectMany(x => x).Select(WebUtility.UrlDecode)));
|
.ToDictionary(grouping => grouping.Key, grouping => new WireMockList<string>(grouping.SelectMany(x => x).Select(WebUtility.UrlDecode)));
|
||||||
|
|||||||
@@ -21,10 +21,6 @@
|
|||||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<!--<ItemGroup>
|
|
||||||
<None Include="WireMock.Net-Logo.png" Pack="true" PackagePath="../../"/>
|
|
||||||
</ItemGroup>-->
|
|
||||||
|
|
||||||
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
|
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
|
||||||
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
|
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
|
||||||
<!--<Target Name="CheckIfShouldKillVBCSCompiler" />-->
|
<!--<Target Name="CheckIfShouldKillVBCSCompiler" />-->
|
||||||
@@ -145,7 +141,6 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'netcoreapp3.1' ">
|
||||||
<!--<PackageReference Include="System.Diagnostics.CodeAnalysis" Version="4.3.0" />-->
|
|
||||||
<PackageReference Include="Nullable" Version="1.3.0" />
|
<PackageReference Include="Nullable" Version="1.3.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user