Compare commits

..

23 Commits

Author SHA1 Message Date
Stef Heyenrath
43cff52b69 1.8.12 2025-06-15 11:50:31 +02:00
Stef Heyenrath
7b93b2668d Fix TypeLoader (#1320)
* no ilmerge

* .

* .

* nullable

* .UsingNuGet

* fix

* .

* directoriesToSearch

* .
2025-06-15 11:44:09 +02:00
Dom Light
70a9180af4 Set description when converting MappingModel to IRespondWithAProvider (#1317)
Adding a mapping with a description to `WireMockServer.WithMapping`
did not include the description to the resulting
`IRespondWithAProvider`, which means that calling
`WireMockServer.SavePact` does not populate the description in the
contract file.

This PR includes the description when mapping from `MappingModel` to
`IRespondWithAProvider`.
2025-06-14 11:13:04 +02:00
Stef Heyenrath
acd6592562 remove some old console projects 2025-06-13 13:07:48 +02:00
Sébastien Crocquesel
2a010dcd42 Use default resource cleaning behavior in test (#1316) 2025-06-12 22:06:58 +02:00
Stef Heyenrath
8151119cca 1.8.11 2025-06-11 12:04:21 +02:00
Stef Heyenrath
77000372c6 Fix for WithTransformer and JsonBody as list (#1315)
* Fix for WithTransformer and JsonBody as list

* Fix WithTransformer when the response BodyAsJson is a List
2025-06-11 11:51:29 +02:00
Stef Heyenrath
ec248a9a78 Fix TestcontainersTests to ignore exception when stopping (#1314) 2025-06-11 11:12:58 +02:00
Stef Heyenrath
2f7e3a3178 Update TestcontainersTests to ignore exception when stopping 2025-06-11 10:21:42 +02:00
Stef Heyenrath
ac9c51e34e Update RandomDataGenerator.Net to 1.0.19 (#1313)
* Update RandomDataGenerator.Net to 1.0.19

* Handlebars.Net.Helpers
2025-06-11 09:00:23 +02:00
Sébastien Crocquesel
8ba243ddcd Bump Testcontainers version to 4.5.0 (#1311)
* Bump Testcontainers version to 4.5.0

The Testcontainers dependency Docker.DotNet was bumped to 3.128.1 and is not binary compatible with previous version.
When a user has a direct dependency on Testcontainers 4.5.0, WireMock.Net.Testcontainers fails with :

System.MissingMethodException : Method not found: 'Docker.DotNet.DockerClient Docker.DotNet.DockerClientConfiguration.CreateClient(System.Version)'

* Bump System.Net.Http.Json version to 8.0.1

Minimum required version for Testcontainers 4.5.0

* Do not dispose null container
2025-06-10 22:23:56 +02:00
Stef Heyenrath
d4b95e73ea Remove unit test which uses postman-echo 2025-06-10 13:16:24 +02:00
Stef Heyenrath
f9ae045847 Images/Icons 2025-06-10 12:23:07 +02:00
Stef Heyenrath
05b5876b5c 1.8.10 2025-06-10 08:15:22 +02:00
Stef Heyenrath
c1bd2d315f Update AwesomeAssertions to version 9 (#1309) 2025-06-06 21:06:38 +02:00
Stef Heyenrath
8917a6eaaa For some projects, change dependency to WireMock.Net.Minimal (#1308) 2025-06-06 11:22:34 +02:00
Stef Heyenrath
3cc9040f51 Update RequestModelBuilder (add WithHeader) (#1306)
* Update RequestModelBuilder (add WithHeader)

* rejectOnMatch

* fix
2025-06-05 12:24:40 +02:00
Stef Heyenrath
6136bc177c 1.8.9 2025-05-28 07:18:51 +02:00
Stef Heyenrath
86d4717216 Add option to provide X509Certificate (#1303)
* Add option to provide X509CertificateRawData

* X509Certificate

* remove X509CertificateRawData
2025-05-28 07:15:46 +02:00
Stef Heyenrath
3438539138 1.8.8 2025-05-24 12:34:30 +02:00
Stef Heyenrath
96eca4262a Create WireMock.Net.MimePart project (#1300)
* Create WireMock.Net.MimePart project

* .

* REFACTOR

* ILRepack

* --

* ...

* x

* x

* .

* fix

* public class MimePartMatcher

* shared

* min

* .

* <!--<DelaySign>true</DelaySign>-->

* Update README.md

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>

---------

Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com>
2025-05-24 12:17:42 +02:00
Stef Heyenrath
c15206ecd8 Update README.md [codecov] 2025-05-22 15:30:01 +02:00
Stef Heyenrath
ec15c544c4 Update README.md (fix codefactor link) 2025-05-22 08:46:11 +02:00
354 changed files with 11498 additions and 11171 deletions

View File

@@ -1,15 +0,0 @@
{
"TestRunner": "",
"TestPlatform": "x86",
"TestApartmentState": "STA",
"TestSettings": "",
"ExcludeAttributes": "System.Diagnostics.CodeAnalysis.ExcludeFromCodeCoverageAttribute",
"ExcludeFiles": "",
"ExcludeDirectories": "",
"Filters": "+[*]*",
"IsIncludingSolutionAssemblies": true,
"IsExcludingTestAssemblies": false,
"IsCoveringByTest": true,
"IsMergingByHash": true,
"IsSkippingAutoProps": true
}

View File

@@ -1,5 +1,8 @@
name: CreateRelease
permissions:
contents: write
on:
push:
tags:
@@ -10,6 +13,9 @@ jobs:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v3
uses: actions/checkout@v4
- name: Release
uses: softprops/action-gh-release@v1
uses: softprops/action-gh-release@v2
with:
generate_release_notes: true

View File

@@ -22,6 +22,9 @@ jobs:
- name: 'WireMock.Net.Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
- name: 'WireMock.Net.Tests.UsingNuGet'
run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
- name: 'WireMock.Net.TUnitTests'
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
@@ -46,6 +49,9 @@ jobs:
- name: 'WireMock.Net.Tests'
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
- name: 'WireMock.Net.Tests.UsingNuGet'
run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
- name: 'WireMock.Net.TUnitTests'
run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0

11
.vscode/launch.json vendored
View File

@@ -1,11 +0,0 @@
{
"version": "0.2.0",
"configurations": [
{
"name": ".NET Core Attach",
"type": "coreclr",
"request": "attach",
"processId": "${command:pickProcess}"
}
]
}

17
.vscode/tasks.json vendored
View File

@@ -1,17 +0,0 @@
{
// See https://go.microsoft.com/fwlink/?LinkId=733558
// for the documentation about the tasks.json format
"version": "2.0.0",
"tasks": [
{
"taskName": "build_WireMock.Net.StandAlone.NETCoreApp",
"command": "dotnet build ${workspaceRoot}/examples/WireMock.Net.StandAlone.NETCoreApp/WireMock.Net.StandAlone.NETCoreApp.csproj -f netcoreapp2.0 ",
"type": "shell",
"group": "build",
"presentation": {
"reveal": "silent"
},
"problemMatcher": "$msCompile"
}
]
}

View File

@@ -1,3 +1,29 @@
# 1.8.12 (15 June 2025)
- [#1317](https://github.com/wiremock/WireMock.Net/pull/1317) - Set description when converting MappingModel to IRespondWithAProvider [feature] contributed by [BodrickLight](https://github.com/BodrickLight)
- [#1320](https://github.com/wiremock/WireMock.Net/pull/1320) - Fix TypeLoader [bug] contributed by [StefH](https://github.com/StefH)
- [#1319](https://github.com/wiremock/WireMock.Net/issues/1319) - Why is IRequestMessage.BodyAsMimeMessage null in new versions (&gt; 1.8.7) [bug]
# 1.8.11 (11 June 2025)
- [#1311](https://github.com/wiremock/WireMock.Net/pull/1311) - Bump Testcontainers version to 4.5.0 [feature] contributed by [scrocquesel](https://github.com/scrocquesel)
- [#1313](https://github.com/wiremock/WireMock.Net/pull/1313) - Update RandomDataGenerator.Net to 1.0.19 [feature] contributed by [StefH](https://github.com/StefH)
- [#1315](https://github.com/wiremock/WireMock.Net/pull/1315) - Fix for WithTransformer and JsonBody as list [bug] contributed by [StefH](https://github.com/StefH)
- [#1310](https://github.com/wiremock/WireMock.Net/issues/1310) - Binary compat issue with testcontainers 4.5.0 [bug]
- [#1312](https://github.com/wiremock/WireMock.Net/issues/1312) - WithTransformer breaks when the response BodyAsJson is a List [bug]
# 1.8.10 (10 June 2025)
- [#1306](https://github.com/wiremock/WireMock.Net/pull/1306) - Update RequestModelBuilder (add WithHeader) [feature] contributed by [StefH](https://github.com/StefH)
- [#1308](https://github.com/wiremock/WireMock.Net/pull/1308) - For some projects, change dependency to WireMock.Net.Minimal [feature] contributed by [StefH](https://github.com/StefH)
- [#1309](https://github.com/wiremock/WireMock.Net/pull/1309) - Update AwesomeAssertions to version 9 [feature] contributed by [StefH](https://github.com/StefH)
- [#1305](https://github.com/wiremock/WireMock.Net/issues/1305) - AdminApiMappingBuilder do not expose WithHeader for Request [feature]
- [#1307](https://github.com/wiremock/WireMock.Net/issues/1307) - Update WireMock.Net.AwesomeAssertions to use latest version from AwesomeAssertions [feature]
# 1.8.9 (28 May 2025)
- [#1303](https://github.com/wiremock/WireMock.Net/pull/1303) - Add option to provide X509Certificate [feature] contributed by [StefH](https://github.com/StefH)
- [#1302](https://github.com/wiremock/WireMock.Net/issues/1302) - Support In-Memory SSL Certificate [feature]
# 1.8.8 (24 May 2025)
- [#1300](https://github.com/wiremock/WireMock.Net/pull/1300) - Create WireMock.Net.MimePart project [feature] contributed by [StefH](https://github.com/StefH)
# 1.8.7 (22 May 2025)
- [#1297](https://github.com/wiremock/WireMock.Net/pull/1297) - Fix BodyParser to correctly check for json [bug] contributed by [StefH](https://github.com/StefH)
- [#1299](https://github.com/wiremock/WireMock.Net/pull/1299) - Use TinyMapper.Signed [bug] contributed by [StefH](https://github.com/StefH)

View File

@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>1.8.7</VersionPrefix>
<VersionPrefix>1.8.12</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>

View File

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

View File

@@ -1,10 +1,6 @@
# 1.8.7 (22 May 2025)
- #1297 Fix BodyParser to correctly check for json [bug]
- #1299 Use TinyMapper.Signed [bug]
- #1301 Fix errors when converting response bodies with top-level JSON arrays to C# code [bug]
- #973 TinyMapper error [bug]
- #1272 WithMappingFromOpenApiFile fails with exception when example item present in text-plain response in OAS contract
- #1295 Content-Type `multipart/form-data` header not proxied [bug]
- #1298 TinyMapper error redux [bug]
# 1.8.12 (15 June 2025)
- #1317 Set description when converting MappingModel to IRespondWithAProvider [feature]
- #1320 Fix TypeLoader [bug]
- #1319 Why is IRequestMessage.BodyAsMimeMessage null in new versions (&gt; 1.8.7) [bug]
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md

View File

@@ -1,4 +1,4 @@
# WireMock.Net
# ![Project Icon](./resources/logo_32x32.png) WireMock.Net
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics the functionality from the JAVA based [WireMock](http://wiremock.org).
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/wiremock/WireMock.Net/wiki/What-Is-WireMock.Net).
@@ -30,9 +30,9 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
| | |
| ***Quality*** | &nbsp; |
| &nbsp;&nbsp;**Build Azure** | [![Build Status Azure](https://stef.visualstudio.com/WireMock.Net/_apis/build/status/WireMock.Net)](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=7) |
| &nbsp;&nbsp;**Quality** | [![Sonar Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=alert_status)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [![CodeFactor](https://www.codefactor.io/repository/github/wiremock-net/wiremock.net/badge)](https://www.codefactor.io/repository/github/wiremock-net/wiremock.net) |
| &nbsp;&nbsp;**Quality** | [![Sonar Quality Gate](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=alert_status)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [![CodeFactor](https://www.codefactor.io/repository/github/wiremock/wiremock.net/badge)](https://www.codefactor.io/repository/github/wiremock/wiremock.net) |
| &nbsp;&nbsp;**Sonar Bugs** | [![Sonar Bugs](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=bugs)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [![Sonar Code Smells](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=code_smells)](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
| &nbsp;&nbsp;**Coverage** | [![Sonar Coverage](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=coverage)](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [![codecov](https://codecov.io/gh/WireMock-Net/WireMock.Net/branch/master/graph/badge.svg)](https://codecov.io/gh/WireMock-Net/WireMock.Net)|
| &nbsp;&nbsp;**Coverage** | [![Sonar Coverage](https://sonarcloud.io/api/project_badges/measure?project=WireMock-Net_WireMock.Net&metric=coverage)](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [![codecov](https://codecov.io/gh/wiremock/WireMock.Net/branch/master/graph/badge.svg)](https://codecov.io/gh/wiremock/WireMock.Net)|
| &nbsp;&nbsp;**TIOBE** | [TIOBE Quality Indicator](https://ticsdemo.tiobe.com/tiobeweb/DEMO/TqiDashboard.html#axes=Project(WireMock.Net),Sub()&metric=tqi)
### :package: NuGet packages
@@ -40,6 +40,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
| | Official | Preview [:information_source:](https://github.com/wiremock/WireMock.Net/wiki/MyGet-preview-versions) |
| - | - | - |
| &nbsp;&nbsp;**WireMock.Net** | [![NuGet Badge WireMock.Net](https://img.shields.io/nuget/v/WireMock.Net)](https://www.nuget.org/packages/WireMock.Net) | [![MyGet Badge WireMock.Net](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
| &nbsp;&nbsp;**WireMock.Net.Minimal** 🔺| [![NuGet Badge WireMock.Net.Minimal](https://img.shields.io/nuget/v/WireMock.Net.Minimal)](https://www.nuget.org/packages/WireMock.Net.Minimal) | [![MyGet Badge WireMock.Net](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Minimal?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Minimal)
| &nbsp;&nbsp;**WireMock.Net.StandAlone** | [![NuGet Badge WireMock.Net](https://img.shields.io/nuget/v/WireMock.Net.StandAlone)](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [![MyGet Badge WireMock.Net.StandAlone](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.StandAlone?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
| &nbsp;&nbsp;**WireMock.Net.Testcontainers** | [![NuGet Badge WireMock.Net.Testcontainers](https://img.shields.io/nuget/v/WireMock.Net.Testcontainers)](https://www.nuget.org/packages/WireMock.Net.Testcontainers) | [![MyGet Badge WireMock.Net.Testcontainers](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Testcontainers?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Testcontainers)
| &nbsp;&nbsp;**WireMock.Net.Aspire** | [![NuGet Badge WireMock.Net.Aspire](https://img.shields.io/nuget/v/WireMock.Net.Aspire)](https://www.nuget.org/packages/WireMock.Net.Aspire) | [![MyGet Badge WireMock.Net.Aspire](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Aspire?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Aspire)
@@ -52,10 +53,15 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
| | | |
| &nbsp;&nbsp;**WireMock.Net.Matchers.CSharpCode** | [![NuGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/nuget/v/WireMock.Net.Matchers.CSharpCode)](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [![MyGet Badge WireMock.Net.Matchers.CSharpCode](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.Matchers.CSharpCode?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
| &nbsp;&nbsp;**WireMock.Net.OpenApiParser** | [![NuGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/nuget/v/WireMock.Net.OpenApiParser)](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [![MyGet Badge WireMock.Net.OpenApiParser](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.OpenApiParser?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
| &nbsp;&nbsp;**WireMock.Net.MimePart** | [![NuGet Badge WireMock.Net.MimePart](https://img.shields.io/nuget/v/WireMock.Net.MimePart)](https://www.nuget.org/packages/WireMock.Net.MimePart) | [![MyGet Badge WireMock.Net.MimePart](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.MimePart?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.MimePart)
| | | |
| &nbsp;&nbsp;**WireMock.Net.RestClient** | [![NuGet Badge WireMock.Net.RestClient](https://img.shields.io/nuget/v/WireMock.Net.RestClient)](https://www.nuget.org/packages/WireMock.Net.RestClient) | [![MyGet Badge WireMock.Net.RestClient](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Net.RestClient?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
| &nbsp;&nbsp;**WireMock.Org.RestClient** | [![NuGet Badge WireMock.Org.RestClient](https://img.shields.io/nuget/v/WireMock.Org.RestClient)](https://www.nuget.org/packages/WireMock.Org.RestClient) | [![MyGet Badge WireMock.Org.RestClient](https://img.shields.io/myget/wiremock-net/vpre/WireMock.Org.RestClient?includePreReleases=true&label=MyGet)](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
<br />
🔺 **WireMock.Net.Minimal** does not include: **WireMock.Net.MimePart**
---
## :exclamation: Breaking changes
@@ -65,6 +71,7 @@ A breaking change is introduced which is related to System.Linq.Dynamic.Core Dyn
- The `LinqMatcher` is not allowed.
- The [Handlebars.Net.Helpers.DynamicLinq](https://www.nuget.org/packages/Handlebars.Net.Helpers.DynamicLinq) package is not included anymore.
### 1.8.0
Some breaking changes are introduced in this version:

View File

@@ -38,12 +38,8 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Client", "examples\WireMock.Net.Client\WireMock.Net.Client.csproj", "{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Proxy.Net452", "examples\WireMock.Net.Console.Proxy.Net452\WireMock.Net.Console.Proxy.Net452.csproj", "{26433A8F-BF01-4962-97EB-81BFFBB61096}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Service", "examples\Wiremock.Net.Service\WireMock.Net.Service.csproj", "{7F0B2446-0363-4720-AF46-F47F83B557DC}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Net452.Classic", "examples\WireMock.Net.Console.Net452.Classic\WireMock.Net.Console.Net452.Classic.csproj", "{668F689E-57B4-422E-8846-C0FF643CA268}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.RequestLogTest", "examples\WireMock.Net.Console.RequestLogTest\WireMock.Net.Console.RequestLogTest.csproj", "{A9D039B9-7509-4CF1-9EFD-87EB82998575}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.OpenApiParser.ConsoleApp", "examples\WireMock.Net.OpenApiParser.ConsoleApp\WireMock.Net.OpenApiParser.ConsoleApp.csproj", "{5C09FB93-1535-4F92-AF26-21E8A061EE4A}"
@@ -130,6 +126,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.AwesomeAsserti
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.OpenApiParser", "src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj", "{E5B03EEF-822C-4295-952B-4479AD30082B}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.MimePart", "src\WireMock.Net.MimePart\WireMock.Net.MimePart.csproj", "{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Shared", "src\WireMock.Net.Shared\WireMock.Net.Shared.csproj", "{D3804228-91F4-4502-9595-39584E5A0177}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Minimal", "src\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj", "{BFEF8990-65B3-4274-310F-7355F0B84035}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.ConsoleApp.UsingNuGet", "examples\WireMock.Net.ConsoleApp.UsingNuGet\WireMock.Net.ConsoleApp.UsingNuGet.csproj", "{1F80A6E6-D146-4E40-9EA8-49DB8494239F}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Tests.UsingNuGet", "test\WireMock.Net.Tests.UsingNuGet\WireMock.Net.Tests.UsingNuGet.csproj", "{BBA332C6-28A9-42E7-9C4D-A0816E52A198}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -160,18 +166,10 @@ Global
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Debug|Any CPU.Build.0 = Debug|Any CPU
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|Any CPU.ActiveCfg = Release|Any CPU
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|Any CPU.Build.0 = Release|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.Build.0 = Debug|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|Any CPU.ActiveCfg = Release|Any CPU
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|Any CPU.Build.0 = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|Any CPU.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|Any CPU.Build.0 = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Debug|Any CPU.Build.0 = Debug|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.ActiveCfg = Release|Any CPU
{668F689E-57B4-422E-8846-C0FF643CA268}.Release|Any CPU.Build.0 = Release|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A9D039B9-7509-4CF1-9EFD-87EB82998575}.Release|Any CPU.ActiveCfg = Release|Any CPU
@@ -308,6 +306,26 @@ Global
{E5B03EEF-822C-4295-952B-4479AD30082B}.Debug|Any CPU.Build.0 = Debug|Any CPU
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|Any CPU.ActiveCfg = Release|Any CPU
{E5B03EEF-822C-4295-952B-4479AD30082B}.Release|Any CPU.Build.0 = Release|Any CPU
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}.Release|Any CPU.Build.0 = Release|Any CPU
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A0177}.Debug|Any CPU.Build.0 = Debug|Any CPU
{D3804228-91F4-4502-9595-39584E5A0177}.Release|Any CPU.ActiveCfg = Release|Any CPU
{D3804228-91F4-4502-9595-39584E5A0177}.Release|Any CPU.Build.0 = Release|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BFEF8990-65B3-4274-310F-7355F0B84035}.Release|Any CPU.Build.0 = Release|Any CPU
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.ActiveCfg = Release|Any CPU
{1F80A6E6-D146-4E40-9EA8-49DB8494239F}.Release|Any CPU.Build.0 = Release|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Debug|Any CPU.Build.0 = Debug|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.ActiveCfg = Release|Any CPU
{BBA332C6-28A9-42E7-9C4D-A0816E52A198}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -319,9 +337,7 @@ Global
{B6269AAC-170A-43D5-8B9A-579DED3D9A95} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{31DC2EF8-C3FE-467D-84BE-FB5D956E612E} = {0BB8B634-407A-4610-A91F-11586990767A}
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{26433A8F-BF01-4962-97EB-81BFFBB61096} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{668F689E-57B4-422E-8846-C0FF643CA268} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{A9D039B9-7509-4CF1-9EFD-87EB82998575} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{5C09FB93-1535-4F92-AF26-21E8A061EE4A} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{B6269AAC-170A-4346-8B9A-579DED3D9A95} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
@@ -358,6 +374,11 @@ Global
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5} = {0BB8B634-407A-4610-A91F-11586990767A}
{7753670F-7C7F-44BF-8BC7-08325588E60C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{E5B03EEF-822C-4295-952B-4479AD30082B} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{F8B4A93E-46EF-4237-88FE-15FDAB7635D4} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{D3804228-91F4-4502-9595-39584E5A0177} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{BFEF8990-65B3-4274-310F-7355F0B84035} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{1F80A6E6-D146-4E40-9EA8-49DB8494239F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{BBA332C6-28A9-42E7-9C4D-A0816E52A198} = {0BB8B634-407A-4610-A91F-11586990767A}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}

View File

@@ -109,6 +109,13 @@ jobs:
packageType: 'sdk'
version: '8.0.x'
- task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Tests.UsingNuGet'
inputs:
command: 'test'
projects: './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj'
arguments: '--configuration Release'
- task: DotNetCoreCLI@2
displayName: 'WireMock.Net.Tests with Coverage'
inputs:

View File

@@ -6,11 +6,6 @@
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF</DefineConstants>
</PropertyGroup>
<ItemGroup>
<Compile Include="..\WireMock.Net.Console.Net452.Classic\MainApp.cs" Link="MainApp.cs" />
<Compile Include="..\WireMock.Net.Console.Net452.Classic\CustomFileSystemFileHandler.cs" Link="CustomFileSystemFileHandler.cs" />
</ItemGroup>
<ItemGroup>
<Content Include="__admin\mappings\*.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>

View File

@@ -1,18 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="HandlebarsDotNet.Helpers.Core" publicKeyToken="00d131fae0c250bc" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.3.3.0" newVersion="2.3.3.0" />
</dependentAssembly>
<dependentAssembly>
<assemblyIdentity name="Handlebars" publicKeyToken="22225d0bf33cd661" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-2.1.2.0" newVersion="2.1.2.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration>

View File

@@ -1,16 +0,0 @@
// Copyright © WireMock.Net
using System.IO;
using log4net.Config;
namespace WireMock.Net.ConsoleApplication;
static class Program
{
static void Main(params string[] args)
{
XmlConfigurator.Configure(new FileInfo("log4net.config"));
MainApp.Run();
}
}

View File

@@ -1,37 +0,0 @@
// Copyright © WireMock.Net
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WireMock.Net.Console.Net452.Classic")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WireMock.Net.Console.Net452.Classic")]
[assembly: AssemblyCopyright("Copyright © Stef Heyenrath 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("668f689e-57b4-422e-8846-c0ff643ca268")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,123 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="14.0" DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{668F689E-57B4-422E-8846-C0FF643CA268}</ProjectGuid>
<OutputType>Exe</OutputType>
<AppDesignerFolder>Properties</AppDesignerFolder>
<RootNamespace>WireMock.Net.ConsoleApplication</RootNamespace>
<AssemblyName>WireMock.Net.ConsoleApplication</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<ApplicationIcon>..\..\resources\WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup>
<ItemGroup>
<Reference Include="AnyOf, Version=0.3.0.0, Culture=neutral, PublicKeyToken=b35e6abbb527c6b1, processorArchitecture=MSIL">
<HintPath>..\..\packages\AnyOf.0.3.0\lib\net45\AnyOf.dll</HintPath>
</Reference>
<Reference Include="Handlebars, Version=2.1.6.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.2.1.6\lib\net451\Handlebars.dll</HintPath>
</Reference>
<Reference Include="Handlebars.Net.Helpers, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.4.3\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
</Reference>
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.4.3.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.4.3\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
</Reference>
<Reference Include="log4net, Version=2.0.17.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
<HintPath>..\..\packages\log4net.2.0.17\lib\net45\log4net.dll</HintPath>
</Reference>
<Reference Include="Microsoft.CSharp" />
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="SimMetrics.Net, Version=1.0.5.0, Culture=neutral, PublicKeyToken=c58dc06d59f3391b, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimMetrics.Net.1.0.5\lib\net45\SimMetrics.Net.dll</HintPath>
</Reference>
<Reference Include="Stef.Validation, Version=0.1.1.0, Culture=neutral, PublicKeyToken=8f3400880c321038, processorArchitecture=MSIL">
<HintPath>..\..\packages\Stef.Validation.0.1.1\lib\net40\Stef.Validation.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Configuration" />
<Reference Include="System.Core" />
<Reference Include="System.Net.Http" />
<Reference Include="System.ValueTuple, Version=4.0.3.0, Culture=neutral, PublicKeyToken=cc7b13ffcd2ddd51, processorArchitecture=MSIL">
<HintPath>..\..\packages\System.ValueTuple.4.5.0\lib\netstandard1.0\System.ValueTuple.dll</HintPath>
</Reference>
<Reference Include="System.Web" />
<Reference Include="System.XML" />
</ItemGroup>
<ItemGroup>
<Compile Include="CustomFileSystemFileHandler.cs" />
<Compile Include="MainApp.cs" />
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config">
<SubType>Designer</SubType>
</None>
<None Include="log4net.config">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
<None Include="packages.config">
<SubType>Designer</SubType>
</None>
<Content Include="__admin\mappings\11111110-a633-40e8-a244-5cb80bc0ab66.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</Content>
<None Include="__admin\mappings\873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
</None>
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj">
<Project>{b6269aac-170a-4346-8b9a-579ded3d9a94}</Project>
<Name>WireMock.Net.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj">
<Project>{d3804228-91f4-4502-9595-39584e5a01ad}</Project>
<Name>WireMock.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="log4net">
<Version>2.0.17</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
<!-- To modify your build process, add your task inside one of the targets below and uncomment it.
Other similar extension points exist, see Microsoft.Common.targets.
<Target Name="BeforeBuild">
</Target>
<Target Name="AfterBuild">
</Target>
-->
</Project>

View File

@@ -1,21 +0,0 @@
{
"Request": {
"Path": {
"Matchers": [
{
"Name": "WildcardMatcher",
"Pattern": "/static/mapping"
}
]
},
"Methods": [
"get"
]
},
"Response": {
"BodyAsJson": { "body": "static mapping" },
"Headers": {
"Content-Type": "application/json"
}
}
}

View File

@@ -1,19 +0,0 @@
{
"Guid": "873d495f-940e-4b86-a1f4-4f0fc7be8b8b",
"Priority": 4,
"Request": {
"Path": {},
"Methods": [
"get"
]
},
"Response": {
"StatusCode": 200,
"BodyDestination": "SameAsSource",
"Body": "NO PATH OR URL",
"UseTransformer": false,
"Headers": {
"Content-Type": "application/json"
}
}
}

View File

@@ -1,20 +0,0 @@
<?xml version="1.0" encoding="utf-8" ?>
<configuration>
<configSections>
<section name="log4net" type="System.Configuration.IgnoreSectionHandler" />
</configSections>
<appSettings>
<add key="log4net.Internal.Debug" value="true"/>
</appSettings>
<log4net>
<appender name="ConsoleAppender" type="log4net.Appender.ConsoleAppender">
<layout type="log4net.Layout.PatternLayout">
<conversionPattern value="%date [%thread] %-5level %logger{1} - %message%newline" />
</layout>
</appender>
<root>
<level value="DEBUG" />
<appender-ref ref="ConsoleAppender" />
</root>
</log4net>
</configuration>

View File

@@ -1,13 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="AnyOf" version="0.3.0" targetFramework="net452" />
<package id="Handlebars.Net" version="2.1.6" targetFramework="net452" />
<package id="Handlebars.Net.Helpers" version="2.4.3" targetFramework="net452" />
<package id="Handlebars.Net.Helpers.Core" version="2.4.3" targetFramework="net452" />
<package id="log4net" version="2.0.17" targetFramework="net452" />
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
<package id="SimMetrics.Net" version="1.0.5" targetFramework="net452" />
<package id="Stef.Validation" version="0.1.1" targetFramework="net452" />
<package id="System.ValueTuple" version="4.5.0" targetFramework="net452" />
</packages>

View File

@@ -1,6 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
<startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2"/>
</startup>
</configuration>

View File

@@ -1,60 +0,0 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Specialized;
using System.Net.Http;
using WireMock.Server;
using WireMock.Settings;
namespace WireMock.Net.Console.Proxy.Net452
{
class Program
{
static void Main(string[] args)
{
string[] urls = { "http://localhost:9091/", "https://localhost:9443/" };
var server = WireMockServer.Start(new WireMockServerSettings
{
Urls = urls,
StartAdminInterface = true,
ReadStaticMappings = false,
ProxyAndRecordSettings = new ProxyAndRecordSettings
{
Url = "http://postman-echo.com/post",
//ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
SaveMapping = true,
SaveMappingToFile = false,
ExcludedHeaders = new[] { "dnt", "Content-Length" }
}
});
System.Console.WriteLine("Subscribing to LogEntriesChanged");
server.LogEntriesChanged += Server_LogEntriesChanged;
var uri = new Uri(urls[0]);
var form = new MultipartFormDataContent
{
{ new StringContent("data"), "test", "test.txt" }
};
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
System.Console.WriteLine("Unsubscribing to LogEntriesChanged");
server.LogEntriesChanged -= Server_LogEntriesChanged;
form = new MultipartFormDataContent
{
{ new StringContent("data2"), "test2", "test2.txt" }
};
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
System.Console.WriteLine("Press any key to stop the server");
System.Console.ReadKey();
server.Stop();
}
private static void Server_LogEntriesChanged(object sender, NotifyCollectionChangedEventArgs eventRecordArgs)
{
System.Console.WriteLine("Server_LogEntriesChanged : {0}", eventRecordArgs.NewItems.Count);
}
}
}

View File

@@ -1,37 +0,0 @@
// Copyright © WireMock.Net
using System.Reflection;
using System.Runtime.InteropServices;
// General Information about an assembly is controlled through the following
// set of attributes. Change these attribute values to modify the information
// associated with an assembly.
[assembly: AssemblyTitle("WireMock.Net.Console.Proxy.Net452")]
[assembly: AssemblyDescription("")]
[assembly: AssemblyConfiguration("")]
[assembly: AssemblyCompany("")]
[assembly: AssemblyProduct("WireMock.Net.Console.Proxy.Net452")]
[assembly: AssemblyCopyright("Copyright © Stef Heyenrath 2018")]
[assembly: AssemblyTrademark("")]
[assembly: AssemblyCulture("")]
// Setting ComVisible to false makes the types in this assembly not visible
// to COM components. If you need to access a type in this assembly from
// COM, set the ComVisible attribute to true on that type.
[assembly: ComVisible(false)]
// The following GUID is for the ID of the typelib if this project is exposed to COM
[assembly: Guid("26433a8f-bf01-4962-97eb-81bffbb61096")]
// Version information for an assembly consists of the following four values:
//
// Major Version
// Minor Version
// Build Number
// Revision
//
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
[assembly: AssemblyVersion("1.0.0.0")]
[assembly: AssemblyFileVersion("1.0.0.0")]

View File

@@ -1,101 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="15.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Import Project="$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props" Condition="Exists('$(MSBuildExtensionsPath)\$(MSBuildToolsVersion)\Microsoft.Common.props')" />
<PropertyGroup>
<Configuration Condition=" '$(Configuration)' == '' ">Debug</Configuration>
<Platform Condition=" '$(Platform)' == '' ">AnyCPU</Platform>
<ProjectGuid>{26433A8F-BF01-4962-97EB-81BFFBB61096}</ProjectGuid>
<OutputType>Exe</OutputType>
<RootNamespace>WireMock.Net.Console.Proxy.Net452</RootNamespace>
<AssemblyName>WireMock.Net.Console.Proxy.Net452</AssemblyName>
<TargetFrameworkVersion>v4.5.2</TargetFrameworkVersion>
<FileAlignment>512</FileAlignment>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<TargetFrameworkProfile />
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugSymbols>true</DebugSymbols>
<DebugType>full</DebugType>
<Optimize>false</Optimize>
<OutputPath>bin\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Release|AnyCPU' ">
<PlatformTarget>AnyCPU</PlatformTarget>
<DebugType>pdbonly</DebugType>
<Optimize>true</Optimize>
<OutputPath>bin\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>WireMock.Net.Console.Proxy.Net452.Program</StartupObject>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Debug|x64'">
<DebugSymbols>true</DebugSymbols>
<OutputPath>bin\x64\Debug\</OutputPath>
<DefineConstants>DEBUG;TRACE</DefineConstants>
<DebugType>full</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)' == 'Release|x64'">
<OutputPath>bin\x64\Release\</OutputPath>
<DefineConstants>TRACE</DefineConstants>
<Optimize>true</Optimize>
<DebugType>pdbonly</DebugType>
<PlatformTarget>x64</PlatformTarget>
<ErrorReport>prompt</ErrorReport>
<CodeAnalysisRuleSet>MinimumRecommendedRules.ruleset</CodeAnalysisRuleSet>
<Prefer32Bit>true</Prefer32Bit>
</PropertyGroup>
<ItemGroup>
<None Condition="'$(Platform)' == 'x64'" Include="..\packages\Libuv.1.10.0\runtimes\win7-x64\native\libuv.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
<Link>libuv.dll</Link>
</None>
<None Condition="'$(Platform)' == 'x86'" Include="..\packages\Libuv.1.10.0\runtimes\win7-x86\native\libuv.dll">
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
<Visible>False</Visible>
<Link>libuv.dll</Link>
</None>
</ItemGroup>
<ItemGroup>
<Reference Include="Microsoft.Owin.Host.HttpListener, Version=3.1.0.0, Culture=neutral, PublicKeyToken=31bf3856ad364e35, processorArchitecture=MSIL">
<HintPath>..\..\packages\Microsoft.Owin.Host.HttpListener.3.1.0\lib\net45\Microsoft.Owin.Host.HttpListener.dll</HintPath>
</Reference>
<Reference Include="Newtonsoft.Json, Version=13.0.0.0, Culture=neutral, PublicKeyToken=30ad4fe6b2a6aeed, processorArchitecture=MSIL">
<HintPath>..\..\packages\Newtonsoft.Json.13.0.3\lib\net45\Newtonsoft.Json.dll</HintPath>
</Reference>
<Reference Include="System" />
<Reference Include="System.Core" />
<Reference Include="System.Xml.Linq" />
<Reference Include="System.Data.DataSetExtensions" />
<Reference Include="Microsoft.CSharp" />
<Reference Include="System.Data" />
<Reference Include="System.Net.Http" />
<Reference Include="System.Xml" />
</ItemGroup>
<ItemGroup>
<Compile Include="Program.cs" />
<Compile Include="Properties\AssemblyInfo.cs" />
</ItemGroup>
<ItemGroup>
<None Include="App.config" />
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj">
<Project>{d3804228-91f4-4502-9595-39584e5a01ad}</Project>
<Name>WireMock.Net</Name>
</ProjectReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -1,5 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="13.0.3" targetFramework="net452" />
</packages>

View File

@@ -0,0 +1,88 @@
// Copyright © WireMock.Net
using System.Net.Http.Headers;
using System.Text;
using WireMock.Matchers;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
Directory.SetCurrentDirectory(Path.GetTempPath());
using var server = WireMockServer.Start();
var textPlainContent = "This is some plain text";
var textPlainContentType = "text/plain";
var textPlainContentTypeMatcher = new ContentTypeMatcher(textPlainContentType);
var textPlainContentMatcher = new ExactMatcher(textPlainContent);
var textPlainMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textPlainContentTypeMatcher, null, null, textPlainContentMatcher);
var textJson = "{ \"Key\" : \"Value\" }";
var textJsonContentType = "text/json";
var textJsonContentTypeMatcher = new ContentTypeMatcher(textJsonContentType);
var textJsonContentMatcher = new JsonMatcher(new { Key = "Value" }, true);
var jsonMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, textJsonContentTypeMatcher, null, null, textJsonContentMatcher);
var imagePngBytes = Convert.FromBase64String("iVBORw0KGgoAAAANSUhEUgAAAAIAAAACAgMAAAAP2OW3AAAADFBMVEX/tID/vpH/pWX/sHidUyjlAAAADElEQVR4XmMQYNgAAADkAMHebX3mAAAAAElFTkSuQmCC");
var imagePngContentMatcher = new ExactObjectMatcher(imagePngBytes);
var imagePngMatcher = new MimePartMatcher(MatchBehaviour.AcceptOnMatch, null, null, null, imagePngContentMatcher);
var matchers = new IMatcher[]
{
textPlainMatcher,
jsonMatcher,
imagePngMatcher
};
server
.Given(Request.Create()
.UsingPost()
.WithPath("/multipart")
.WithMultiPart(matchers)
)
.RespondWith(Response.Create()
.WithBodyAsJson(new
{
Method = "{{request.Method}}",
BodyAsMimeMessage = "{{request.BodyAsMimeMessage.TextBody}}"
})
.WithTransformer()
);
server
.Given(Request.Create()
.UsingPost()
.WithPath("/multipart2")
.WithMultiPart(matchers)
)
.RespondWith(Response.Create()
.WithBody(request =>
{
if (request.BodyAsMimeMessage == null)
{
throw new InvalidProgramException("Not expected");
}
return "OK";
})
.WithTransformer()
);
var formDataContent = new MultipartFormDataContent
{
{ new StringContent(textPlainContent, Encoding.UTF8, textPlainContentType), "text" },
{ new StringContent(textJson, Encoding.UTF8, textJsonContentType), "json" }
};
var fileContent = new ByteArrayContent(imagePngBytes);
fileContent.Headers.ContentType = new MediaTypeHeaderValue("image/png");
formDataContent.Add(fileContent, "somefile", "image.png");
var client = server.CreateClient();
var response = await client.PostAsync("/multipart", formDataContent);
var content = await response.Content.ReadAsStringAsync();
Console.WriteLine(content);
var response2 = await client.PostAsync("/multipart2", formDataContent);
var content2 = await response2.Content.ReadAsStringAsync();
Console.WriteLine(content2);

View File

@@ -0,0 +1,18 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>Exe</OutputType>
<TargetFramework>net8.0</TargetFramework>
<ImplicitUsings>enable</ImplicitUsings>
<Nullable>enable</Nullable>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
<!--<ItemGroup>
<PackageReference Include="WireMock.Net" Version="1.8.11" />
</ItemGroup>-->
</Project>

View File

@@ -113,20 +113,13 @@
</None>
<None Include="packages.config" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj">
<Project>{b6269aac-170a-4346-8b9a-579ded3d9a94}</Project>
<Name>WireMock.Net.Abstractions</Name>
</ProjectReference>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj">
<Project>{d3804228-91f4-4502-9595-39584e5a01ad}</Project>
<Name>WireMock.Net</Name>
</ProjectReference>
</ItemGroup>
<ItemGroup>
<PackageReference Include="log4net">
<Version>3.0.3</Version>
</PackageReference>
<PackageReference Include="WireMock.Net">
<Version>1.8.11</Version>
</PackageReference>
</ItemGroup>
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
</Project>

View File

@@ -159,9 +159,7 @@ internal class Program
private static async Task TestWindowsCopyAsync()
{
var builder = new WireMockContainerBuilder()
.WithWatchStaticMappings(true)
.WithAutoRemove(true)
.WithCleanUp(true);
.WithWatchStaticMappings(true);
var container = builder.Build();
@@ -186,8 +184,6 @@ internal class Program
var mappings = await adminClient.GetMappingsAsync();
Console.WriteLine("mappings = " + JsonConvert.SerializeObject(mappings, Formatting.Indented));
await Task.Delay(1_000);
await container.StopAsync();
}
@@ -205,9 +201,7 @@ internal class Program
.WithNetwork(dummyNetwork)
.WithAdminUserNameAndPassword("x", "y")
.WithMappings(mappingsPath)
.WithWatchStaticMappings(true)
// .WithAutoRemove(true)
.WithCleanUp(true);
.WithWatchStaticMappings(true);
if (image != null)
{

Binary file not shown.

Before

Width:  |  Height:  |  Size: 31 KiB

After

Width:  |  Height:  |  Size: 22 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 62 KiB

After

Width:  |  Height:  |  Size: 47 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 14 KiB

After

Width:  |  Height:  |  Size: 11 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 15 KiB

After

Width:  |  Height:  |  Size: 12 KiB

BIN
resources/logo_32x32.png Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 1.9 KiB

View File

@@ -138,4 +138,27 @@ public partial class RequestModelBuilder
return builder.Build();
});
}
/// <summary>
/// WithHeader: matching based on name, pattern and matchBehaviour.
/// </summary>
/// <param name="name">The name.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="rejectOnMatch">The match behaviour. Default value is <c>false</c>.</param>
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
public RequestModelBuilder WithHeader(string name, string pattern, bool rejectOnMatch = false)
{
return WithHeaders(headersBuilder => headersBuilder
.Add(headerBuilder => headerBuilder
.WithName(name)
.WithMatchers(matchersBuilder => matchersBuilder
.Add(matcherBuilder => matcherBuilder
.WithName("WildcardMatcher")
.WithPattern(pattern)
.WithRejectOnMatch(rejectOnMatch)
)
)
)
);
}
}

View File

@@ -0,0 +1,8 @@
// Copyright © WireMock.Net
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]
// Needed for Moq in the UnitTest project
[assembly: InternalsVisibleTo("DynamicProxyGenAssembly2, PublicKey=0024000004800000940000000602000000240000525341310004000001000100c547cac37abd99c8db225ef2f6c8a3602f3b3606cc9891605d02baa56104f4cfc0734aa39b93bf7852f7d9266654753cc297e7d2edfe0bac1cdcf9f717241550e0a7b191195b7667bb4f64bcb8e2121380fd1d9d46ad2d92d2d15605093924cceaf74c4861eff62abf69b9291ed0a340e113be11e6a7d3113e92484cf7045cc7")]

View File

@@ -1,7 +1,7 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>Commonly used models, enumerations and types.</Description>
<Description>Commonly used interfaces, models, enumerations and types.</Description>
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net45;net451;net461;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
@@ -17,7 +17,6 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
@@ -25,6 +24,10 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
@@ -35,37 +38,46 @@
</PropertyGroup>
<ItemGroup>
<!-- CVE-2018-8292 -->
<PackageReference Include="System.Net.Http " Version="4.3.4" />
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
<PackageReference Include="FluentBuilder" Version="0.10.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
<PackageReference Include="PolySharp" Version="1.15.0">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<!-- CVE-2018-8292 -->
<PackageReference Include="System.Net.Http " Version="4.3.4" />
<!--<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
<PackageReference Include="Stef.Validation" Version="0.1.1" />
<PackageReference Include="AnyOf" Version="0.4.0" />-->
</ItemGroup>
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard')) and '$(TargetFramework)' != 'netstandard1.0'">
<PackageReference Include="System.Security.Cryptography.X509Certificates" Version="4.3.0" />
</ItemGroup>
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net46" Version="1.0.2">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>
<ItemGroup>
<!--<ItemGroup>
<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
</ItemGroup>-->
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net461'">
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
<!--<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>-->
<!--<PackageReference Include="PolySharp" Version="1.14.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>-->
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
@@ -16,7 +16,6 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
@@ -25,6 +24,10 @@
<ApplicationIcon>../../resources/WireMock.Net-LogoAspire.ico</ApplicationIcon>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
@@ -39,7 +42,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<ImplicitUsings>enable</ImplicitUsings>
@@ -16,7 +16,6 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
@@ -31,9 +30,13 @@
</ItemGroup>
<ItemGroup>
<Compile Include="..\WireMock.Net\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
<Compile Include="..\WireMock.Net.Minimal\Util\EnhancedFileSystemWatcher.cs" Link="Utils\EnhancedFileSystemWatcher.cs" />
</ItemGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>

View File

@@ -1,6 +1,6 @@
// Copyright © WireMock.Net
using FluentAssertions.Primitives;
using AwesomeAssertions.Primitives;
using WireMock.Server;
// ReSharper disable once CheckNamespace

View File

@@ -1,5 +1,5 @@
// Copyright © WireMock.Net
global using System.Linq;
global using FluentAssertions;
global using FluentAssertions.Execution;
global using AwesomeAssertions;
global using AwesomeAssertions.Execution;

View File

@@ -16,7 +16,6 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
@@ -24,16 +23,20 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="AwesomeAssertions" Version="8.1.0" />
<PackageReference Include="AwesomeAssertions" Version="9.0.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
</ItemGroup>
</Project>

View File

@@ -1,4 +1,4 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>FluentAssertions extensions for WireMock.Net</Description>
@@ -16,7 +16,6 @@
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
@@ -24,6 +23,10 @@
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
@@ -37,7 +40,7 @@
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
</ItemGroup>
</Project>

View File

@@ -25,13 +25,13 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher
private const string TemplateForIsMatchWithDynamic = "public class CodeHelper {{ public bool IsMatch(dynamic it) {{ {0} }} }}";
private readonly string[] _usings =
{
[
"System",
"System.Linq",
"System.Collections.Generic",
"Microsoft.CSharp",
"Newtonsoft.Json.Linq"
};
];
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }

View File

@@ -1,49 +1,52 @@
<Project Sdk="Microsoft.NET.Sdk">
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code.</Description>
<AssemblyTitle>WireMock.Net.Matchers.CSharpCode</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;csharp;csharpcode</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-444DED3D9A44}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup>
<Description>A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code.</Description>
<AssemblyTitle>WireMock.Net.Matchers.CSharpCode</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net7.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;csharp;csharpcode</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{B6269AAC-170A-4346-8B9A-444DED3D9A44}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<!--<DelaySign>true</DelaySign>-->
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
<Target Name="CheckIfShouldKillVBCSCompiler" />
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
</ItemGroup>
<!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
<Target Name="CheckIfShouldKillVBCSCompiler" />
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="3.6.0" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'net461' ">
<PackageReference Include="CS-Script" Version="3.30.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="3.6.0" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<PackageReference Include="CS-Script" Version="4.8.17" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' or '$(TargetFramework)' == 'net461' ">
<PackageReference Include="CS-Script" Version="3.30.3" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' or '$(TargetFramework)' == 'netcoreapp3.1' or '$(TargetFramework)' == 'net5.0' or '$(TargetFramework)' == 'net6.0' or '$(TargetFramework)' == 'net7.0' or '$(TargetFramework)' == 'net8.0'">
<PackageReference Include="CS-Script" Version="4.8.17" />
</ItemGroup>
</Project>

View File

@@ -0,0 +1,28 @@
<?xml version="1.0" encoding="utf-8" ?>
<!-- See also https://github.com/ravibpatel/ILRepack.Lib.MSBuild.Task/issues/26 -->
<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<Target Name="ILRepacker" AfterTargets="Build" Condition="'$(Configuration)' == 'Release'">
<ItemGroup>
<InputAssemblies Include="$(OutputPath)WireMock.Net.MimePart.dll" />
<InputAssemblies Include="@(ReferencePathWithRefAssemblies)" Condition="'%(filename)' == 'MimeKitLite'" />
<LibraryPath Include="%(ReferencePathWithRefAssemblies.RelativeDir)" />
</ItemGroup>
<ItemGroup>
<DoNotInternalizeAssemblies Include="WireMock.Net.MimePart" />
</ItemGroup>
<ILRepack
Parallel="true"
Internalize="true"
RenameInternalized="true"
InternalizeExclude="@(DoNotInternalizeAssemblies)"
InputAssemblies="@(InputAssemblies)"
LibraryPath="@(LibraryPath)"
TargetKind="Dll"
KeyFile="../../src/WireMock.Net/WireMock.Net.snk"
OutputFile="$(OutputPath)$(AssemblyName).dll"
/>
</Target>
</Project>

View File

@@ -1,12 +1,8 @@
// Copyright © WireMock.Net
#if MIMEKIT
using System;
using MimeKit;
using WireMock.Extensions;
using WireMock.Matchers;
using WireMock.Matchers.Helpers;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
@@ -14,31 +10,23 @@ namespace WireMock.Matchers;
/// <summary>
/// MimePartMatcher
/// </summary>
public class MimePartMatcher : IMatcher
public class MimePartMatcher : IMimePartMatcher
{
private readonly Func<MimePart, MatchResult>[] _funcs;
/// <inheritdoc />
public string Name => nameof(MimePartMatcher);
/// <summary>
/// ContentType Matcher (image/png; name=image.png.)
/// </summary>
/// <inheritdoc />
public IStringMatcher? ContentTypeMatcher { get; }
/// <summary>
/// ContentDisposition Matcher (attachment; filename=image.png)
/// </summary>
/// <inheritdoc />
public IStringMatcher? ContentDispositionMatcher { get; }
/// <summary>
/// ContentTransferEncoding Matcher (base64)
/// </summary>
/// <inheritdoc />
public IStringMatcher? ContentTransferEncodingMatcher { get; }
/// <summary>
/// Content Matcher
/// </summary>
/// <inheritdoc />
public IMatcher? ContentMatcher { get; }
/// <inheritdoc />
@@ -70,19 +58,15 @@ public class MimePartMatcher : IMatcher
];
}
/// <summary>
/// Determines whether the specified MimePart is match.
/// </summary>
/// <param name="mimePart">The MimePart.</param>
/// <returns>A value between 0.0 - 1.0 of the similarity.</returns>
public MatchResult IsMatch(MimePart mimePart)
/// <inheritdoc />
public MatchResult IsMatch(object value)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
try
{
if (Array.TrueForAll(_funcs, func => func(mimePart).IsPerfect()))
if (value is MimePart mimePart && Array.TrueForAll(_funcs, func => func(mimePart).IsPerfect()))
{
score = MatchScores.Perfect;
}
@@ -125,5 +109,4 @@ public class MimePartMatcher : IMatcher
{
return contentType?.ToString().Replace("Content-Type: ", string.Empty);
}
}
#endif
}

View File

@@ -0,0 +1,5 @@
// Copyright © WireMock.Net
using System.Runtime.CompilerServices;
[assembly: InternalsVisibleTo("WireMock.Net.Tests, PublicKey=0024000004800000940000000602000000240000525341310004000001000100e138ec44d93acac565953052636eb8d5e7e9f27ddb030590055cd1a0ab2069a5623f1f77ca907d78e0b37066ca0f6d63da7eecc3fcb65b76aa8ebeccf7ebe1d11264b8404cd9b1cbbf2c83f566e033b3e54129f6ef28daffff776ba7aebbc53c0d635ebad8f45f78eb3f7e0459023c218f003416e080f96a1a3c5ffeb56bee9e")]

View File

@@ -1,7 +1,7 @@
// Copyright © WireMock.Net
#if MIMEKIT
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.IO;
using System.Linq;
@@ -13,15 +13,22 @@ using WireMock.Types;
namespace WireMock.Util;
internal static class MimeKitUtils
internal class MimeKitUtils : IMimeKitUtils
{
public static bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out MimeMessage? mimeMessage)
/// <inheritdoc />
public object LoadFromStream(Stream stream)
{
return MimeMessage.Load(Guard.NotNull(stream));
}
/// <inheritdoc />
public bool TryGetMimeMessage(IRequestMessage requestMessage, [NotNullWhen(true)] out object? mimeMessage)
{
Guard.NotNull(requestMessage);
if (requestMessage.BodyData != null &&
requestMessage.Headers?.TryGetValue(HttpKnownHeaderNames.ContentType, out var contentTypeHeader) == true &&
StartsWithMultiPart(contentTypeHeader) // Only parse when "multipart/mixed"
StartsWithMultiPart(contentTypeHeader)
)
{
var bytes = requestMessage.BodyData?.DetectedBodyType switch
@@ -37,7 +44,7 @@ internal static class MimeKitUtils
var fixedBytes = FixBytes(bytes, contentTypeHeader[0]);
mimeMessage = MimeMessage.Load(new MemoryStream(fixedBytes));
mimeMessage = LoadFromStream(new MemoryStream(fixedBytes));
return true;
}
@@ -45,6 +52,19 @@ internal static class MimeKitUtils
return false;
}
/// <inheritdoc />
public IReadOnlyList<object> GetBodyParts(object mimeMessage)
{
if (mimeMessage is not MimeMessage mm)
{
throw new ArgumentException($"The mimeMessage must be of type {nameof(MimeMessage)}", nameof(mimeMessage));
}
return mm.BodyParts
.OfType<MimePart>()
.ToArray();
}
private static bool StartsWithMultiPart(WireMockList<string> contentTypeHeader)
{
return contentTypeHeader.Any(ct => ct.TrimStart().StartsWith("multipart/", StringComparison.OrdinalIgnoreCase));
@@ -61,5 +81,4 @@ internal static class MimeKitUtils
return result;
}
}
#endif
}

View File

@@ -0,0 +1,63 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<Description>MultiPart Mime support for WireMock.Net using MimeKitLite</Description>
<AssemblyTitle>WireMock.Net.MimePart</AssemblyTitle>
<Authors>Stef Heyenrath</Authors>
<TargetFrameworks>netstandard2.0;netstandard2.1;net462;net47;net48;net6.0;net8.0</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
<PackageTags>wiremock;matchers;matcher;mime;multipart;mimekit</PackageTags>
<RootNamespace>WireMock</RootNamespace>
<ProjectGuid>{F8B4A93E-46EF-4237-88FE-15FDAB7635D4}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<SignAssembly>true</SignAssembly>
<!--<DelaySign>true</DelaySign>-->
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Debug' ">
<SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
</PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="Nullable" Version="1.3.1">
<PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Stef.Validation" Version="0.1.1" />
</ItemGroup>
<!--<ItemGroup>
<PackageReference Include="MimeKitLite" Version="4.12.0" />
</ItemGroup>-->
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
<PackageReference Include="MimeKitLite" Version="4.12.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Release'">
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.40" PrivateAssets="All" />
<PackageReference Include="MimeKitLite" Version="4.12.0" PrivateAssets="All" />
</ItemGroup>
<ItemGroup>
<ProjectReference Include="..\WireMock.Net.Shared\WireMock.Net.Shared.csproj" />
</ItemGroup>
</Project>

View File

@@ -45,7 +45,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
public AnyOf<string, StringPattern>[] GetPatterns()
{
return EmptyArray<AnyOf<string, StringPattern>>.Value;
return [];
}
public MatchOperator MatchOperator => MatchOperator.Or;
@@ -57,7 +57,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
return MatchScores.Mismatch;
}
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, WireMockConstants.DefaultRegexTimeout);
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, RegexConstants.DefaultTimeout);
try
{

View File

@@ -12,7 +12,7 @@ internal static class StringExtensions
public static string Replace(this string text, string oldValue, string newValue, StringComparison stringComparison)
{
var options = stringComparison == StringComparison.OrdinalIgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
return Regex.Replace(text, oldValue, newValue, options, WireMockConstants.DefaultRegexTimeout);
return Regex.Replace(text, oldValue, newValue, options, RegexConstants.DefaultTimeout);
}
}
#endif

View File

@@ -1,13 +1,9 @@
// Copyright © WireMock.Net
using System;
namespace WireMock.Constants;
internal static class WireMockConstants
{
internal static readonly TimeSpan DefaultRegexTimeout = TimeSpan.FromSeconds(10);
internal const int AdminPriority = int.MinValue;
internal const int MinPriority = -1_000_000;
internal const int ProxyPriority = -2_000_000;

View File

@@ -61,7 +61,7 @@ internal static class HttpRequestMessageHelper
if (contentLengthHeaderAllowed)
{
// Set Content to empty ByteArray to be able to set the Content-Length on the content in case of a HEAD method.
httpRequestMessage.Content ??= new ByteArrayContent(EmptyArray<byte>.Value);
httpRequestMessage.Content ??= new ByteArrayContent([]);
}
else
{

View File

@@ -1,122 +1,122 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Models;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Transformers.Handlebars;
using WireMock.Transformers.Scriban;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Http;
internal class WebhookSender
{
private const string ClientIp = "::1";
private static readonly ThreadLocal<Random> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
private readonly WireMockServerSettings _settings;
public WebhookSender(WireMockServerSettings settings)
{
_settings = Guard.NotNull(settings);
}
public async Task<HttpResponseMessage> SendAsync(
HttpClient client,
IMapping mapping,
IWebhookRequest webhookRequest,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage
)
{
Guard.NotNull(client);
Guard.NotNull(mapping);
Guard.NotNull(webhookRequest);
Guard.NotNull(originalRequestMessage);
Guard.NotNull(originalResponseMessage);
IBodyData? bodyData;
IDictionary<string, WireMockList<string>>? headers;
string requestUrl;
if (webhookRequest.UseTransformer == true)
{
ITransformer transformer;
switch (webhookRequest.TransformerType)
{
case TransformerType.Handlebars:
var factoryHandlebars = new HandlebarsContextFactory(_settings);
transformer = new Transformer(_settings, factoryHandlebars);
break;
case TransformerType.Scriban:
case TransformerType.ScribanDotLiquid:
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
transformer = new Transformer(_settings, factoryDotLiquid);
break;
default:
throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported.");
}
bodyData = transformer.TransformBody(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.TransformerReplaceNodeOptions);
headers = transformer.TransformHeaders(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Headers);
requestUrl = transformer.TransformString(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Url);
mapping.Settings.WebhookSettings?.PostTransform(mapping, requestUrl, bodyData, headers);
}
else
{
bodyData = webhookRequest.BodyData;
headers = webhookRequest.Headers;
requestUrl = webhookRequest.Url;
}
// Create RequestMessage
var requestMessage = new RequestMessage(
new UrlDetails(requestUrl),
webhookRequest.Method,
ClientIp,
bodyData,
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
)
{
DateTime = DateTime.UtcNow
};
// Create HttpRequestMessage
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, requestUrl);
// Delay (if required)
if (TryGetDelay(webhookRequest, out var delay))
{
await Task.Delay(delay.Value).ConfigureAwait(false);
}
// Call the URL
return await client.SendAsync(httpRequestMessage).ConfigureAwait(false);
}
private static bool TryGetDelay(IWebhookRequest webhookRequest, [NotNullWhen(true)] out int? delay)
{
delay = webhookRequest.Delay;
var minimumDelay = webhookRequest.MinimumRandomDelay;
var maximumDelay = webhookRequest.MaximumRandomDelay;
if (minimumDelay is not null && maximumDelay is not null && maximumDelay >= minimumDelay)
{
delay = Random.Value!.Next(minimumDelay.Value, maximumDelay.Value);
return true;
}
return delay is not null;
}
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Linq;
using System.Net.Http;
using System.Threading;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Models;
using WireMock.Settings;
using WireMock.Transformers;
using WireMock.Transformers.Handlebars;
using WireMock.Transformers.Scriban;
using WireMock.Types;
using WireMock.Util;
namespace WireMock.Http;
internal class WebhookSender
{
private const string ClientIp = "::1";
private static readonly ThreadLocal<Random> Random = new(() => new Random(DateTime.UtcNow.Millisecond));
private readonly WireMockServerSettings _settings;
public WebhookSender(WireMockServerSettings settings)
{
_settings = Guard.NotNull(settings);
}
public async Task<HttpResponseMessage> SendAsync(
HttpClient client,
IMapping mapping,
IWebhookRequest webhookRequest,
IRequestMessage originalRequestMessage,
IResponseMessage originalResponseMessage
)
{
Guard.NotNull(client);
Guard.NotNull(mapping);
Guard.NotNull(webhookRequest);
Guard.NotNull(originalRequestMessage);
Guard.NotNull(originalResponseMessage);
IBodyData? bodyData;
IDictionary<string, WireMockList<string>>? headers;
string requestUrl;
if (webhookRequest.UseTransformer == true)
{
ITransformer transformer;
switch (webhookRequest.TransformerType)
{
case TransformerType.Handlebars:
var factoryHandlebars = new HandlebarsContextFactory(_settings);
transformer = new Transformer(_settings, factoryHandlebars);
break;
case TransformerType.Scriban:
case TransformerType.ScribanDotLiquid:
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
transformer = new Transformer(_settings, factoryDotLiquid);
break;
default:
throw new NotImplementedException($"TransformerType '{webhookRequest.TransformerType}' is not supported.");
}
bodyData = transformer.TransformBody(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.BodyData, webhookRequest.TransformerReplaceNodeOptions);
headers = transformer.TransformHeaders(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Headers);
requestUrl = transformer.TransformString(mapping, originalRequestMessage, originalResponseMessage, webhookRequest.Url);
mapping.Settings.WebhookSettings?.PostTransform(mapping, requestUrl, bodyData, headers);
}
else
{
bodyData = webhookRequest.BodyData;
headers = webhookRequest.Headers;
requestUrl = webhookRequest.Url;
}
// Create RequestMessage
var requestMessage = new RequestMessage(
new UrlDetails(requestUrl),
webhookRequest.Method,
ClientIp,
bodyData,
headers?.ToDictionary(x => x.Key, x => x.Value.ToArray())
)
{
DateTime = DateTime.UtcNow
};
// Create HttpRequestMessage
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, requestUrl);
// Delay (if required)
if (TryGetDelay(webhookRequest, out var delay))
{
await Task.Delay(delay.Value).ConfigureAwait(false);
}
// Call the URL
return await client.SendAsync(httpRequestMessage).ConfigureAwait(false);
}
private static bool TryGetDelay(IWebhookRequest webhookRequest, [NotNullWhen(true)] out int? delay)
{
delay = webhookRequest.Delay;
var minimumDelay = webhookRequest.MinimumRandomDelay;
var maximumDelay = webhookRequest.MaximumRandomDelay;
if (minimumDelay is not null && maximumDelay is not null && maximumDelay >= minimumDelay)
{
delay = Random.Value!.Next(minimumDelay.Value, maximumDelay.Value);
return true;
}
return delay is not null;
}
}

View File

@@ -3,6 +3,7 @@
using System;
using System.IO;
using System.Security.Cryptography.X509Certificates;
using WireMock.Owin;
namespace WireMock.HttpsCertificate;
@@ -13,19 +14,13 @@ internal static class CertificateLoader
/// <summary>
/// Used by the WireMock.Net server
/// </summary>
public static X509Certificate2 LoadCertificate(
string? storeName,
string? storeLocation,
string? thumbprintOrSubjectName,
string? filePath,
string? passwordOrKey,
string host)
public static X509Certificate2 LoadCertificate(IWireMockMiddlewareOptions options, string host)
{
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
if (!string.IsNullOrEmpty(options.X509StoreName) && !string.IsNullOrEmpty(options.X509StoreLocation))
{
var thumbprintOrSubjectNameOrHost = thumbprintOrSubjectName ?? host;
var thumbprintOrSubjectNameOrHost = options.X509ThumbprintOrSubjectName ?? host;
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), storeName), (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation));
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), options.X509StoreName!), (StoreLocation)Enum.Parse(typeof(StoreLocation), options.X509StoreLocation!));
try
{
certStore.Open(OpenFlags.ReadOnly);
@@ -39,7 +34,7 @@ internal static class CertificateLoader
if (matchingCertificates.Count == 0)
{
// No certificates matched the search criteria.
throw new FileNotFoundException($"No Certificate found with in store '{storeName}', location '{storeLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
throw new FileNotFoundException($"No Certificate found with in store '{options.X509StoreName}', location '{options.X509StoreLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
}
}
@@ -56,27 +51,28 @@ internal static class CertificateLoader
}
}
if (!string.IsNullOrEmpty(filePath))
if (!string.IsNullOrEmpty(options.X509CertificateFilePath))
{
if (filePath!.EndsWith(ExtensionPem, StringComparison.OrdinalIgnoreCase))
if (options.X509CertificateFilePath.EndsWith(ExtensionPem, StringComparison.OrdinalIgnoreCase))
{
// PEM logic based on: https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
#if NET5_0_OR_GREATER
if (!string.IsNullOrEmpty(passwordOrKey))
if (!string.IsNullOrEmpty(options.X509CertificatePassword))
{
var certPem = File.ReadAllText(filePath);
var cert = X509Certificate2.CreateFromPem(certPem, passwordOrKey);
var certPem = File.ReadAllText(options.X509CertificateFilePath);
var cert = X509Certificate2.CreateFromPem(certPem, options.X509CertificatePassword);
const string defaultPasswordPem = "WireMock.Net";
return new X509Certificate2(cert.Export(X509ContentType.Pfx, defaultPasswordPem), defaultPasswordPem);
}
return X509Certificate2.CreateFromPemFile(filePath);
return X509Certificate2.CreateFromPemFile(options.X509CertificateFilePath);
#elif NETCOREAPP3_1
var cert = new X509Certificate2(filePath);
if (!string.IsNullOrEmpty(passwordOrKey))
var cert = new X509Certificate2(options.X509CertificateFilePath);
if (!string.IsNullOrEmpty(options.X509CertificatePassword))
{
var key = System.Security.Cryptography.ECDsa.Create()!;
key.ImportECPrivateKey(System.Text.Encoding.UTF8.GetBytes(passwordOrKey), out _);
key.ImportECPrivateKey(System.Text.Encoding.UTF8.GetBytes(options.X509CertificatePassword), out _);
return cert.CopyWithPrivateKey(key);
}
return cert;
@@ -85,10 +81,17 @@ internal static class CertificateLoader
#endif
}
return !string.IsNullOrEmpty(passwordOrKey) ? new X509Certificate2(filePath, passwordOrKey) : new X509Certificate2(filePath);
return !string.IsNullOrEmpty(options.X509CertificatePassword) ?
new X509Certificate2(options.X509CertificateFilePath, options.X509CertificatePassword) :
new X509Certificate2(options.X509CertificateFilePath);
}
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath are mandatory. Note that X509CertificatePassword is optional.");
if (options.X509Certificate != null)
{
return options.X509Certificate;
}
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath OR X509Certificate are mandatory. Note that X509CertificatePassword is optional.");
}
/// <summary>

View File

@@ -1,39 +1,39 @@
// Copyright © WireMock.Net
using System;
using WireMock.Matchers.Request;
namespace WireMock.Logging;
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry : ILogEntry
{
/// <inheritdoc cref="ILogEntry.Guid" />
public Guid Guid { get; set; }
/// <inheritdoc cref="ILogEntry.RequestMessage" />
public IRequestMessage RequestMessage { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
public IResponseMessage ResponseMessage { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
public IRequestMatchResult RequestMatchResult { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.MappingGuid" />
public Guid? MappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.MappingTitle" />
public string? MappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingGuid" />
public Guid? PartialMappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingTitle" />
public string? PartialMappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
public IRequestMatchResult PartialMatchResult { get; set; } = null!;
// Copyright © WireMock.Net
using System;
using WireMock.Matchers.Request;
namespace WireMock.Logging;
/// <summary>
/// LogEntry
/// </summary>
public class LogEntry : ILogEntry
{
/// <inheritdoc cref="ILogEntry.Guid" />
public Guid Guid { get; set; }
/// <inheritdoc cref="ILogEntry.RequestMessage" />
public IRequestMessage RequestMessage { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.ResponseMessage" />
public IResponseMessage ResponseMessage { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.RequestMatchResult" />
public IRequestMatchResult RequestMatchResult { get; set; } = null!;
/// <inheritdoc cref="ILogEntry.MappingGuid" />
public Guid? MappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.MappingTitle" />
public string? MappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingGuid" />
public Guid? PartialMappingGuid { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMappingTitle" />
public string? PartialMappingTitle { get; set; }
/// <inheritdoc cref="ILogEntry.PartialMatchResult" />
public IRequestMatchResult PartialMatchResult { get; set; } = null!;
}

View File

@@ -1,197 +1,197 @@
// Copyright © WireMock.Net
using System;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.ResponseProviders;
using WireMock.Settings;
namespace WireMock;
/// <summary>
/// The Mapping.
/// </summary>
public class Mapping : IMapping
{
/// <inheritdoc />
public Guid Guid { get; }
/// <inheritdoc />
public DateTime? UpdatedAt { get; set; }
/// <inheritdoc />
public string? Title { get; }
/// <inheritdoc />
public string? Description { get; }
/// <inheritdoc />
public string? Path { get; set; }
/// <inheritdoc />
public int Priority { get; }
/// <inheritdoc />
public string? Scenario { get; private set; }
/// <inheritdoc />
public string? ExecutionConditionState { get; }
/// <inheritdoc />
public string? NextState { get; }
/// <inheritdoc />
public int? StateTimes { get; }
/// <inheritdoc />
public IRequestMatcher RequestMatcher { get; }
/// <inheritdoc />
public IResponseProvider Provider { get; }
/// <inheritdoc />
public WireMockServerSettings Settings { get; }
/// <inheritdoc />
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
/// <inheritdoc />
public bool IsAdminInterface => Provider is DynamicResponseProvider or DynamicAsyncResponseProvider or ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool IsProxy => Provider is ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool LogMapping => Provider is not (DynamicResponseProvider or DynamicAsyncResponseProvider);
/// <inheritdoc />
public IWebhook[]? Webhooks { get; }
/// <inheritdoc />
public bool? UseWebhooksFireAndForget { get; }
/// <inheritdoc />
public ITimeSettings? TimeSettings { get; }
/// <inheritdoc />
public object? Data { get; }
/// <inheritdoc />
public double? Probability { get; private set; }
/// <inheritdoc />
public IdOrTexts? ProtoDefinition { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="Mapping"/> class.
/// </summary>
/// <param name="guid">The unique identifier.</param>
/// <param name="updatedAt">The datetime when this mapping was created.</param>
/// <param name="title">The unique title (can be null).</param>
/// <param name="description">The description (can be null).</param>
/// <param name="path">The full file path from this mapping title (can be null).</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="provider">The provider.</param>
/// <param name="priority">The priority for this mapping.</param>
/// <param name="scenario">The scenario. [Optional]</param>
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
/// <param name="webhooks">The Webhooks. [Optional]</param>
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
/// <param name="data">The data object. [Optional]</param>
public Mapping
(
Guid guid,
DateTime updatedAt,
string? title,
string? description,
string? path,
WireMockServerSettings settings,
IRequestMatcher requestMatcher,
IResponseProvider provider,
int priority,
string? scenario,
string? executionConditionState,
string? nextState,
int? stateTimes,
IWebhook[]? webhooks,
bool? useWebhooksFireAndForget,
ITimeSettings? timeSettings,
object? data
)
{
Guid = guid;
UpdatedAt = updatedAt;
Title = title;
Description = description;
Path = path;
Settings = settings;
RequestMatcher = requestMatcher;
Provider = provider;
Priority = priority;
Scenario = scenario;
ExecutionConditionState = executionConditionState;
NextState = nextState;
StateTimes = stateTimes;
Webhooks = webhooks;
UseWebhooksFireAndForget = useWebhooksFireAndForget;
TimeSettings = timeSettings;
Data = data;
}
/// <inheritdoc />
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{
return Provider.ProvideResponseAsync(this, requestMessage, Settings);
}
/// <inheritdoc />
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
{
var result = new RequestMatchResult();
RequestMatcher.GetMatchingScore(requestMessage, result);
// Only check state if Scenario is defined
if (Scenario != null)
{
var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
matcher.GetMatchingScore(requestMessage, result);
//// If ExecutionConditionState is null, this means that request is the start from a scenario. So just return.
//if (ExecutionConditionState != null)
//{
// // ExecutionConditionState is not null, so get score for matching with the nextState.
// var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
// matcher.GetMatchingScore(requestMessage, result);
//}
}
return result;
}
/// <inheritdoc />
public IMapping WithProbability(double probability)
{
Probability = Guard.NotNull(probability);
return this;
}
/// <inheritdoc />
public IMapping WithScenario(string scenario)
{
Scenario = Guard.NotNullOrWhiteSpace(scenario);
return this;
}
/// <inheritdoc />
public IMapping WithProtoDefinition(IdOrTexts protoDefinition)
{
ProtoDefinition = protoDefinition;
return this;
}
// Copyright © WireMock.Net
using System;
using System.Threading.Tasks;
using Stef.Validation;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.ResponseProviders;
using WireMock.Settings;
namespace WireMock;
/// <summary>
/// The Mapping.
/// </summary>
public class Mapping : IMapping
{
/// <inheritdoc />
public Guid Guid { get; }
/// <inheritdoc />
public DateTime? UpdatedAt { get; set; }
/// <inheritdoc />
public string? Title { get; }
/// <inheritdoc />
public string? Description { get; }
/// <inheritdoc />
public string? Path { get; set; }
/// <inheritdoc />
public int Priority { get; }
/// <inheritdoc />
public string? Scenario { get; private set; }
/// <inheritdoc />
public string? ExecutionConditionState { get; }
/// <inheritdoc />
public string? NextState { get; }
/// <inheritdoc />
public int? StateTimes { get; }
/// <inheritdoc />
public IRequestMatcher RequestMatcher { get; }
/// <inheritdoc />
public IResponseProvider Provider { get; }
/// <inheritdoc />
public WireMockServerSettings Settings { get; }
/// <inheritdoc />
public bool IsStartState => Scenario == null || Scenario != null && NextState != null && ExecutionConditionState == null;
/// <inheritdoc />
public bool IsAdminInterface => Provider is DynamicResponseProvider or DynamicAsyncResponseProvider or ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool IsProxy => Provider is ProxyAsyncResponseProvider;
/// <inheritdoc />
public bool LogMapping => Provider is not (DynamicResponseProvider or DynamicAsyncResponseProvider);
/// <inheritdoc />
public IWebhook[]? Webhooks { get; }
/// <inheritdoc />
public bool? UseWebhooksFireAndForget { get; }
/// <inheritdoc />
public ITimeSettings? TimeSettings { get; }
/// <inheritdoc />
public object? Data { get; }
/// <inheritdoc />
public double? Probability { get; private set; }
/// <inheritdoc />
public IdOrTexts? ProtoDefinition { get; private set; }
/// <summary>
/// Initializes a new instance of the <see cref="Mapping"/> class.
/// </summary>
/// <param name="guid">The unique identifier.</param>
/// <param name="updatedAt">The datetime when this mapping was created.</param>
/// <param name="title">The unique title (can be null).</param>
/// <param name="description">The description (can be null).</param>
/// <param name="path">The full file path from this mapping title (can be null).</param>
/// <param name="settings">The WireMockServerSettings.</param>
/// <param name="requestMatcher">The request matcher.</param>
/// <param name="provider">The provider.</param>
/// <param name="priority">The priority for this mapping.</param>
/// <param name="scenario">The scenario. [Optional]</param>
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
/// <param name="webhooks">The Webhooks. [Optional]</param>
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
/// <param name="data">The data object. [Optional]</param>
public Mapping
(
Guid guid,
DateTime updatedAt,
string? title,
string? description,
string? path,
WireMockServerSettings settings,
IRequestMatcher requestMatcher,
IResponseProvider provider,
int priority,
string? scenario,
string? executionConditionState,
string? nextState,
int? stateTimes,
IWebhook[]? webhooks,
bool? useWebhooksFireAndForget,
ITimeSettings? timeSettings,
object? data
)
{
Guid = guid;
UpdatedAt = updatedAt;
Title = title;
Description = description;
Path = path;
Settings = settings;
RequestMatcher = requestMatcher;
Provider = provider;
Priority = priority;
Scenario = scenario;
ExecutionConditionState = executionConditionState;
NextState = nextState;
StateTimes = stateTimes;
Webhooks = webhooks;
UseWebhooksFireAndForget = useWebhooksFireAndForget;
TimeSettings = timeSettings;
Data = data;
}
/// <inheritdoc />
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
{
return Provider.ProvideResponseAsync(this, requestMessage, Settings);
}
/// <inheritdoc />
public IRequestMatchResult GetRequestMatchResult(IRequestMessage requestMessage, string? nextState)
{
var result = new RequestMatchResult();
RequestMatcher.GetMatchingScore(requestMessage, result);
// Only check state if Scenario is defined
if (Scenario != null)
{
var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
matcher.GetMatchingScore(requestMessage, result);
//// If ExecutionConditionState is null, this means that request is the start from a scenario. So just return.
//if (ExecutionConditionState != null)
//{
// // ExecutionConditionState is not null, so get score for matching with the nextState.
// var matcher = new RequestMessageScenarioAndStateMatcher(nextState, ExecutionConditionState);
// matcher.GetMatchingScore(requestMessage, result);
//}
}
return result;
}
/// <inheritdoc />
public IMapping WithProbability(double probability)
{
Probability = Guard.NotNull(probability);
return this;
}
/// <inheritdoc />
public IMapping WithScenario(string scenario)
{
Scenario = Guard.NotNullOrWhiteSpace(scenario);
return this;
}
/// <inheritdoc />
public IMapping WithProtoDefinition(IdOrTexts protoDefinition)
{
ProtoDefinition = protoDefinition;
return this;
}
}

View File

@@ -1,90 +1,90 @@
// Copyright © WireMock.Net
using System.Net.Http.Headers;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// ContentTypeMatcher which accepts also all charsets
/// </summary>
/// <seealso cref="RegexMatcher" />
public class ContentTypeMatcher : WildcardMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this([pattern], ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour,
[pattern], ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : base(matchBehaviour, patterns, ignoreCase)
{
_patterns = Guard.NotNull(patterns);
}
/// <inheritdoc />
public override MatchResult IsMatch(string? input)
{
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
{
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
}
return base.IsMatch(contentType.MediaType);
}
/// <inheritdoc />
public override AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public override string Name => nameof(ContentTypeMatcher);
/// <inheritdoc />
public override string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}" +
$")";
}
// Copyright © WireMock.Net
using System.Net.Http.Headers;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// ContentTypeMatcher which accepts also all charsets
/// </summary>
/// <seealso cref="RegexMatcher" />
public class ContentTypeMatcher : WildcardMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this([pattern], ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour,
[pattern], ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ContentTypeMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">IgnoreCase (default false)</param>
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : base(matchBehaviour, patterns, ignoreCase)
{
_patterns = Guard.NotNull(patterns);
}
/// <inheritdoc />
public override MatchResult IsMatch(string? input)
{
if (string.IsNullOrEmpty(input) || !MediaTypeHeaderValue.TryParse(input, out var contentType))
{
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.Mismatch);
}
return base.IsMatch(contentType.MediaType);
}
/// <inheritdoc />
public override AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public override string Name => nameof(ContentTypeMatcher);
/// <inheritdoc />
public override string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}" +
$")";
}
}

View File

@@ -1,107 +1,107 @@
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// ExactMatcher
/// </summary>
/// <seealso cref="IStringMatcher" /> and <seealso cref="IIgnoreCaseMatcher" />
public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly AnyOf<string, StringPattern>[] _values;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The string value.</param>
public ExactMatcher(MatchBehaviour matchBehaviour, string value) : this(matchBehaviour, true, MatchOperator.Or, new AnyOf<string, StringPattern>(value))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="values">The values.</param>
public ExactMatcher(params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, values)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="values">The values.</param>
public ExactMatcher(bool ignoreCase, params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, MatchOperator.Or, values)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="values">The values.</param>
public ExactMatcher(
MatchBehaviour matchBehaviour,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] values)
{
_values = Guard.NotNull(values);
MatchBehaviour = matchBehaviour;
IgnoreCase = ignoreCase;
MatchOperator = matchOperator;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
Func<string?, bool> equals = IgnoreCase
? pattern => string.Equals(pattern, input, StringComparison.OrdinalIgnoreCase)
: pattern => pattern == input;
var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _values;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(ExactMatcher);
/// <inheritdoc />
public bool IgnoreCase { get; }
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_values)}" +
$")";
}
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// ExactMatcher
/// </summary>
/// <seealso cref="IStringMatcher" /> and <seealso cref="IIgnoreCaseMatcher" />
public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly AnyOf<string, StringPattern>[] _values;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The string value.</param>
public ExactMatcher(MatchBehaviour matchBehaviour, string value) : this(matchBehaviour, true, MatchOperator.Or, new AnyOf<string, StringPattern>(value))
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="values">The values.</param>
public ExactMatcher(params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, false, MatchOperator.Or, values)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="values">The values.</param>
public ExactMatcher(bool ignoreCase, params AnyOf<string, StringPattern>[] values) : this(MatchBehaviour.AcceptOnMatch, ignoreCase, MatchOperator.Or, values)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="ExactMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="ignoreCase">Ignore the case from the pattern(s).</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="values">The values.</param>
public ExactMatcher(
MatchBehaviour matchBehaviour,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] values)
{
_values = Guard.NotNull(values);
MatchBehaviour = matchBehaviour;
IgnoreCase = ignoreCase;
MatchOperator = matchOperator;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
Func<string?, bool> equals = IgnoreCase
? pattern => string.Equals(pattern, input, StringComparison.OrdinalIgnoreCase)
: pattern => pattern == input;
var score = MatchScores.ToScore(_values.Select(v => equals(v)).ToArray(), MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _values;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(ExactMatcher);
/// <inheritdoc />
public bool IgnoreCase { get; }
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_values)}" +
$")";
}
}

View File

@@ -1,179 +1,179 @@
// Copyright © WireMock.Net
using System.Collections.Generic;
using System.Linq;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// FormUrl Encoded fields Matcher
/// </summary>
/// <inheritdoc cref="IStringMatcher"/>
/// <inheritdoc cref="IIgnoreCaseMatcher"/>
public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
private readonly List<(WildcardMatcher Key, WildcardMatcher? Value)> _pairs = [];
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
AnyOf<string, StringPattern> pattern,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(MatchBehaviour.AcceptOnMatch, [pattern], ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
MatchBehaviour matchBehaviour,
AnyOf<string, StringPattern> pattern,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(matchBehaviour, [pattern], ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
AnyOf<string, StringPattern>[] patterns,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
MatchBehaviour matchBehaviour,
AnyOf<string, StringPattern>[] patterns,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or)
{
_patterns = Guard.NotNull(patterns);
IgnoreCase = ignoreCase;
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
foreach (var pattern in _patterns)
{
if (QueryStringParser.TryParse(pattern, IgnoreCase, out var nameValueCollection))
{
foreach (var nameValue in nameValueCollection)
{
var keyMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, [nameValue.Key], ignoreCase, MatchOperator);
var valueMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, [nameValue.Value], ignoreCase, MatchOperator);
_pairs.Add((keyMatcher, valueMatcher));
}
}
}
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
// Input is null or empty and if no patterns defined, return Perfect match.
if (string.IsNullOrEmpty(input) && _patterns.Length == 0)
{
return new MatchResult(MatchScores.Perfect);
}
if (!QueryStringParser.TryParse(input, IgnoreCase, out var inputNameValueCollection))
{
return new MatchResult(MatchScores.Mismatch);
}
var matches = GetMatches(inputNameValueCollection);
var score = MatchScores.ToScore(matches, MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
}
private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection)
{
var matches = new List<bool>();
if (_pairs.Count > inputNameValueCollection.Count)
{
matches.AddRange(Enumerable.Repeat(false, _pairs.Count - inputNameValueCollection.Count));
}
foreach (var inputKeyValuePair in inputNameValueCollection)
{
var match = false;
foreach (var pair in _pairs)
{
var keyMatchResult = pair.Key.IsMatch(inputKeyValuePair.Key).IsPerfect();
if (keyMatchResult)
{
match = pair.Value?.IsMatch(inputKeyValuePair.Value).IsPerfect() ?? false;
if (match)
{
break;
}
}
}
matches.Add(match);
}
return matches.ToArray();
}
/// <inheritdoc />
public virtual AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public virtual string Name => nameof(FormUrlEncodedMatcher);
/// <inheritdoc />
public bool IgnoreCase { get; }
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
$")";
}
// Copyright © WireMock.Net
using System.Collections.Generic;
using System.Linq;
using AnyOfTypes;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// FormUrl Encoded fields Matcher
/// </summary>
/// <inheritdoc cref="IStringMatcher"/>
/// <inheritdoc cref="IIgnoreCaseMatcher"/>
public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
private readonly List<(WildcardMatcher Key, WildcardMatcher? Value)> _pairs = [];
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
AnyOf<string, StringPattern> pattern,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(MatchBehaviour.AcceptOnMatch, [pattern], ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
MatchBehaviour matchBehaviour,
AnyOf<string, StringPattern> pattern,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(matchBehaviour, [pattern], ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
AnyOf<string, StringPattern>[] patterns,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or) :
this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase, matchOperator)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="FormUrlEncodedMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="patterns">The patterns.</param>
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
public FormUrlEncodedMatcher(
MatchBehaviour matchBehaviour,
AnyOf<string, StringPattern>[] patterns,
bool ignoreCase = false,
MatchOperator matchOperator = MatchOperator.Or)
{
_patterns = Guard.NotNull(patterns);
IgnoreCase = ignoreCase;
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
foreach (var pattern in _patterns)
{
if (QueryStringParser.TryParse(pattern, IgnoreCase, out var nameValueCollection))
{
foreach (var nameValue in nameValueCollection)
{
var keyMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, [nameValue.Key], ignoreCase, MatchOperator);
var valueMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, [nameValue.Value], ignoreCase, MatchOperator);
_pairs.Add((keyMatcher, valueMatcher));
}
}
}
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
// Input is null or empty and if no patterns defined, return Perfect match.
if (string.IsNullOrEmpty(input) && _patterns.Length == 0)
{
return new MatchResult(MatchScores.Perfect);
}
if (!QueryStringParser.TryParse(input, IgnoreCase, out var inputNameValueCollection))
{
return new MatchResult(MatchScores.Mismatch);
}
var matches = GetMatches(inputNameValueCollection);
var score = MatchScores.ToScore(matches, MatchOperator);
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
}
private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection)
{
var matches = new List<bool>();
if (_pairs.Count > inputNameValueCollection.Count)
{
matches.AddRange(Enumerable.Repeat(false, _pairs.Count - inputNameValueCollection.Count));
}
foreach (var inputKeyValuePair in inputNameValueCollection)
{
var match = false;
foreach (var pair in _pairs)
{
var keyMatchResult = pair.Key.IsMatch(inputKeyValuePair.Key).IsPerfect();
if (keyMatchResult)
{
match = pair.Value?.IsMatch(inputKeyValuePair.Value).IsPerfect() ?? false;
if (match)
{
break;
}
}
}
matches.Add(match);
}
return matches.ToArray();
}
/// <inheritdoc />
public virtual AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public virtual string Name => nameof(FormUrlEncodedMatcher);
/// <inheritdoc />
public bool IgnoreCase { get; }
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
$")";
}
}

View File

@@ -1,167 +1,167 @@
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// JsonPathMatcher
/// </summary>
/// <seealso cref="IStringMatcher" />
/// <seealso cref="IObjectMatcher" />
public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc />
public object Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or,
patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch,
MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
if (!string.IsNullOrWhiteSpace(input))
{
try
{
var jToken = JToken.Parse(input);
score = IsMatch(jToken);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
// When input is null or byte[], return Mismatch.
if (input != null && input is not byte[])
{
try
{
// Check if JToken or object
JToken jToken = input as JToken ?? JObject.FromObject(input);
score = IsMatch(jToken);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(JsonPathMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
private double IsMatch(JToken jToken)
{
var array = ConvertJTokenToJArrayIfNeeded(jToken);
// The SelectToken method can accept a string path to a child token ( i.e. "Manufacturers[0].Products[0].Price").
// In that case it will return a JValue (some type) which does not implement the IEnumerable interface.
var values = _patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null).ToArray();
return MatchScores.ToScore(values, MatchOperator);
}
// https://github.com/wiremock/WireMock.Net/issues/965
// https://stackoverflow.com/questions/66922188/newtonsoft-jsonpath-with-c-sharp-syntax
// Filtering using SelectToken() isn't guaranteed to work for objects inside objects -- only objects inside arrays.
// So this code checks if it's an JArray, if it's not an array, construct a new JArray.
private static JToken ConvertJTokenToJArrayIfNeeded(JToken jToken)
{
if (jToken.Count() == 1)
{
var property = jToken.First();
var item = property.First();
if (item is JArray)
{
return jToken;
}
return new JObject
{
[property.Path] = new JArray(item)
};
}
return jToken;
}
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// JsonPathMatcher
/// </summary>
/// <seealso cref="IStringMatcher" />
/// <seealso cref="IObjectMatcher" />
public class JsonPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc />
public object Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or,
patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch,
MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonPathMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="patterns">The patterns.</param>
public JsonPathMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
if (!string.IsNullOrWhiteSpace(input))
{
try
{
var jToken = JToken.Parse(input);
score = IsMatch(jToken);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
// When input is null or byte[], return Mismatch.
if (input != null && input is not byte[])
{
try
{
// Check if JToken or object
JToken jToken = input as JToken ?? JObject.FromObject(input);
score = IsMatch(jToken);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(JsonPathMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
private double IsMatch(JToken jToken)
{
var array = ConvertJTokenToJArrayIfNeeded(jToken);
// The SelectToken method can accept a string path to a child token ( i.e. "Manufacturers[0].Products[0].Price").
// In that case it will return a JValue (some type) which does not implement the IEnumerable interface.
var values = _patterns.Select(pattern => array.SelectToken(pattern.GetPattern()) != null).ToArray();
return MatchScores.ToScore(values, MatchOperator);
}
// https://github.com/wiremock/WireMock.Net/issues/965
// https://stackoverflow.com/questions/66922188/newtonsoft-jsonpath-with-c-sharp-syntax
// Filtering using SelectToken() isn't guaranteed to work for objects inside objects -- only objects inside arrays.
// So this code checks if it's an JArray, if it's not an array, construct a new JArray.
private static JToken ConvertJTokenToJArrayIfNeeded(JToken jToken)
{
if (jToken.Count() == 1)
{
var property = jToken.First();
var item = property.First();
if (item is JArray)
{
return jToken;
}
return new JObject
{
[property.Path] = new JArray(item)
};
}
return jToken;
}
}

View File

@@ -1,130 +1,130 @@
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using DevLab.JmesPath;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// http://jmespath.org/
/// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public object Value { get; }
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(MatchOperator matchOperator = MatchOperator.Or, params AnyOf<string, StringPattern>[] patterns) :
this(MatchBehaviour.AcceptOnMatch, matchOperator, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
if (!string.IsNullOrWhiteSpace(input))
{
try
{
var results = _patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))).ToArray();
score = MatchScores.ToScore(results, MatchOperator);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
// When input is null or byte[], return Mismatch.
if (input != null && !(input is byte[]))
{
var inputAsString = JsonConvert.SerializeObject(input);
return IsMatch(inputAsString);
}
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(JmesPathMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
// Copyright © WireMock.Net
using System;
using System.Linq;
using AnyOfTypes;
using DevLab.JmesPath;
using Newtonsoft.Json;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// http://jmespath.org/
/// </summary>
public class JmesPathMatcher : IStringMatcher, IObjectMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public object Value { get; }
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(params string[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns.ToAnyOfPatterns())
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(MatchOperator matchOperator = MatchOperator.Or, params AnyOf<string, StringPattern>[] patterns) :
this(MatchBehaviour.AcceptOnMatch, matchOperator, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JmesPathMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use.</param>
/// <param name="patterns">The patterns.</param>
public JmesPathMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? exception = null;
if (!string.IsNullOrWhiteSpace(input))
{
try
{
var results = _patterns.Select(pattern => bool.Parse(new JmesPath().Transform(input, pattern.GetPattern()))).ToArray();
score = MatchScores.ToScore(results, MatchOperator);
}
catch (Exception ex)
{
exception = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
// When input is null or byte[], return Mismatch.
if (input != null && !(input is byte[]))
{
var inputAsString = JsonConvert.SerializeObject(input);
return IsMatch(inputAsString);
}
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(JmesPathMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
}

View File

@@ -1,250 +1,250 @@
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Util;
using JsonUtils = WireMock.Util.JsonUtils;
namespace WireMock.Matchers;
/// <summary>
/// JsonMatcher
/// </summary>
public class JsonMatcher : IJsonMatcher
{
/// <inheritdoc />
public virtual string Name => nameof(JsonMatcher);
/// <inheritdoc />
public object Value { get; }
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc cref="IIgnoreCaseMatcher.IgnoreCase"/>
public bool IgnoreCase { get; }
/// <summary>
/// Support Regex
/// </summary>
public bool Regex { get; }
private readonly JToken _valueAsJToken;
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The string value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(string value, bool ignoreCase = false, bool regex = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, regex)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The object value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(object value, bool ignoreCase = false, bool regex = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, regex)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false)
{
Guard.NotNull(value);
MatchBehaviour = matchBehaviour;
IgnoreCase = ignoreCase;
Regex = regex;
Value = value;
_valueAsJToken = JsonUtils.ConvertValueToJToken(value);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
// When input is null or byte[], return Mismatch.
if (input != null && input is not byte[])
{
try
{
var inputAsJToken = JsonUtils.ConvertValueToJToken(input);
var match = IsMatch(RenameJToken(_valueAsJToken), RenameJToken(inputAsJToken));
score = MatchScores.ToScore(match);
}
catch (Exception ex)
{
error = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public virtual string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{CSharpFormatter.ConvertToAnonymousObjectDefinition(Value, 3)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(Regex)}" +
$")";
}
/// <summary>
/// Compares the input against the matcher value
/// </summary>
/// <param name="value">Matcher value</param>
/// <param name="input">Input value</param>
/// <returns></returns>
protected virtual bool IsMatch(JToken value, JToken? input)
{
// If equal, return true.
if (input == value)
{
return true;
}
// If input is null, return false.
if (input == null)
{
return false;
}
// If using Regex and the value is a string, use the MatchRegex method.
if (Regex && value.Type == JTokenType.String)
{
var valueAsString = value.ToString();
var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString());
if (valid)
{
return result;
}
}
// If the value is a Guid and the input is a string, or vice versa, convert them to strings and compare the string values.
if ((value.Type == JTokenType.Guid && input.Type == JTokenType.String) || (value.Type == JTokenType.String && input.Type == JTokenType.Guid))
{
return JToken.DeepEquals(value.ToString().ToUpperInvariant(), input.ToString().ToUpperInvariant());
}
switch (value.Type)
{
// If the value is an object, compare all properties.
case JTokenType.Object:
var valueProperties = value.ToObject<Dictionary<string, JToken>>() ?? new Dictionary<string, JToken>();
var inputProperties = input.ToObject<Dictionary<string, JToken>>() ?? new Dictionary<string, JToken>();
// If the number of properties is different, return false.
if (valueProperties.Count != inputProperties.Count)
{
return false;
}
// Compare all properties. The input must match all properties of the value.
foreach (var pair in valueProperties)
{
if (!IsMatch(pair.Value, inputProperties[pair.Key]))
{
return false;
}
}
return true;
// If the value is an array, compare all elements.
case JTokenType.Array:
var valueArray = value.ToObject<JToken[]>() ?? EmptyArray<JToken>.Value;
var inputArray = input.ToObject<JToken[]>() ?? EmptyArray<JToken>.Value;
// If the number of elements is different, return false.
if (valueArray.Length != inputArray.Length)
{
return false;
}
return !valueArray.Where((valueToken, index) => !IsMatch(valueToken, inputArray[index])).Any();
default:
// Use JToken.DeepEquals() for all other types.
return JToken.DeepEquals(value, input);
}
}
// https://stackoverflow.com/questions/11679804/json-net-rename-properties
private JToken RenameJToken(JToken input)
{
if (!IgnoreCase)
{
return input;
}
return input switch
{
JProperty property => RenameJProperty(property),
JArray array => RenameJArray(array),
JObject obj => RenameJObject(obj),
_ => input
};
}
private JProperty RenameJProperty(JProperty property)
{
if (!IgnoreCase)
{
return property;
}
var propertyValue = property.Value;
if (propertyValue.Type == JTokenType.String && !Regex)
{
var stringValue = propertyValue.Value<string>()!;
propertyValue = ToUpper(stringValue);
}
return new JProperty(ToUpper(property.Name)!, RenameJToken(propertyValue));
}
private JArray RenameJArray(JArray array)
{
if (Regex)
{
return array;
}
var renamedValues = array.Select(RenameJToken);
return new JArray(renamedValues);
}
private JObject RenameJObject(JObject obj)
{
var renamedProperties = obj.Properties().Select(RenameJProperty);
return new JObject(renamedProperties);
}
private static string? ToUpper(string? input)
{
return input?.ToUpperInvariant();
}
// Copyright © WireMock.Net
using System;
using System.Collections.Generic;
using System.Linq;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Util;
using JsonUtils = WireMock.Util.JsonUtils;
namespace WireMock.Matchers;
/// <summary>
/// JsonMatcher
/// </summary>
public class JsonMatcher : IJsonMatcher
{
/// <inheritdoc />
public virtual string Name => nameof(JsonMatcher);
/// <inheritdoc />
public object Value { get; }
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc cref="IIgnoreCaseMatcher.IgnoreCase"/>
public bool IgnoreCase { get; }
/// <summary>
/// Support Regex
/// </summary>
public bool Regex { get; }
private readonly JToken _valueAsJToken;
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The string value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(string value, bool ignoreCase = false, bool regex = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, regex)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="value">The object value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(object value, bool ignoreCase = false, bool regex = false) : this(MatchBehaviour.AcceptOnMatch, value, ignoreCase, regex)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="value">The value to check for equality.</param>
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
/// <param name="regex">Support Regex.</param>
public JsonMatcher(MatchBehaviour matchBehaviour, object value, bool ignoreCase = false, bool regex = false)
{
Guard.NotNull(value);
MatchBehaviour = matchBehaviour;
IgnoreCase = ignoreCase;
Regex = regex;
Value = value;
_valueAsJToken = JsonUtils.ConvertValueToJToken(value);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
// When input is null or byte[], return Mismatch.
if (input != null && input is not byte[])
{
try
{
var inputAsJToken = JsonUtils.ConvertValueToJToken(input);
var match = IsMatch(RenameJToken(_valueAsJToken), RenameJToken(inputAsJToken));
score = MatchScores.ToScore(match);
}
catch (Exception ex)
{
error = ex;
}
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public virtual string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{CSharpFormatter.ConvertToAnonymousObjectDefinition(Value, 3)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
$"{CSharpFormatter.ToCSharpBooleanLiteral(Regex)}" +
$")";
}
/// <summary>
/// Compares the input against the matcher value
/// </summary>
/// <param name="value">Matcher value</param>
/// <param name="input">Input value</param>
/// <returns></returns>
protected virtual bool IsMatch(JToken value, JToken? input)
{
// If equal, return true.
if (input == value)
{
return true;
}
// If input is null, return false.
if (input == null)
{
return false;
}
// If using Regex and the value is a string, use the MatchRegex method.
if (Regex && value.Type == JTokenType.String)
{
var valueAsString = value.ToString();
var (valid, result) = RegexUtils.MatchRegex(valueAsString, input.ToString());
if (valid)
{
return result;
}
}
// If the value is a Guid and the input is a string, or vice versa, convert them to strings and compare the string values.
if ((value.Type == JTokenType.Guid && input.Type == JTokenType.String) || (value.Type == JTokenType.String && input.Type == JTokenType.Guid))
{
return JToken.DeepEquals(value.ToString().ToUpperInvariant(), input.ToString().ToUpperInvariant());
}
switch (value.Type)
{
// If the value is an object, compare all properties.
case JTokenType.Object:
var valueProperties = value.ToObject<Dictionary<string, JToken>>() ?? new Dictionary<string, JToken>();
var inputProperties = input.ToObject<Dictionary<string, JToken>>() ?? new Dictionary<string, JToken>();
// If the number of properties is different, return false.
if (valueProperties.Count != inputProperties.Count)
{
return false;
}
// Compare all properties. The input must match all properties of the value.
foreach (var pair in valueProperties)
{
if (!IsMatch(pair.Value, inputProperties[pair.Key]))
{
return false;
}
}
return true;
// If the value is an array, compare all elements.
case JTokenType.Array:
var valueArray = value.ToObject<JToken[]>() ?? [];
var inputArray = input.ToObject<JToken[]>() ?? [];
// If the number of elements is different, return false.
if (valueArray.Length != inputArray.Length)
{
return false;
}
return !valueArray.Where((valueToken, index) => !IsMatch(valueToken, inputArray[index])).Any();
default:
// Use JToken.DeepEquals() for all other types.
return JToken.DeepEquals(value, input);
}
}
// https://stackoverflow.com/questions/11679804/json-net-rename-properties
private JToken RenameJToken(JToken input)
{
if (!IgnoreCase)
{
return input;
}
return input switch
{
JProperty property => RenameJProperty(property),
JArray array => RenameJArray(array),
JObject obj => RenameJObject(obj),
_ => input
};
}
private JProperty RenameJProperty(JProperty property)
{
if (!IgnoreCase)
{
return property;
}
var propertyValue = property.Value;
if (propertyValue.Type == JTokenType.String && !Regex)
{
var stringValue = propertyValue.Value<string>()!;
propertyValue = ToUpper(stringValue);
}
return new JProperty(ToUpper(property.Name)!, RenameJToken(propertyValue));
}
private JArray RenameJArray(JArray array)
{
if (Regex)
{
return array;
}
var renamedValues = array.Select(RenameJToken);
return new JArray(renamedValues);
}
private JObject RenameJObject(JObject obj)
{
var renamedProperties = obj.Properties().Select(RenameJProperty);
return new JObject(renamedProperties);
}
private static string? ToUpper(string? input)
{
return input?.ToUpperInvariant();
}
}

View File

@@ -1,151 +1,151 @@
// Copyright © WireMock.Net
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using AnyOfTypes;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Json;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// System.Linq.Dynamic.Core Expression Matcher
/// </summary>
/// <inheritdoc cref="IObjectMatcher"/>
/// <inheritdoc cref="IStringMatcher"/>
public class LinqMatcher : IObjectMatcher, IStringMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc />
public object Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
public LinqMatcher(AnyOf<string, StringPattern> pattern) : this(new[] { pattern })
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public LinqMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
public LinqMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern) : this(matchBehaviour, MatchOperator.Or, pattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="patterns">The patterns.</param>
public LinqMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
// Convert a single input string to a Queryable string-list with 1 entry.
IQueryable queryable = new[] { input }.AsQueryable();
try
{
// Use the Any(...) method to check if the result matches
score = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator);
}
catch (Exception e)
{
error = e;
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
JArray jArray;
try
{
jArray = new JArray { input };
}
catch
{
jArray = input == null ? new JArray() : new JArray { JToken.FromObject(input) };
}
// Convert a single object to a Queryable JObject-list with 1 entry.
var queryable = jArray.ToDynamicClassArray().AsQueryable();
try
{
var patternsAsStringArray = _patterns.Select(p => p.GetPattern()).ToArray();
var scores = patternsAsStringArray.Select(p => queryable.Any(p)).ToArray();
score = MatchScores.ToScore(scores, MatchOperator);
}
catch (Exception e)
{
error = e;
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(LinqMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
// Copyright © WireMock.Net
using System;
using System.Linq;
using System.Linq.Dynamic.Core;
using AnyOfTypes;
using Newtonsoft.Json.Linq;
using Stef.Validation;
using WireMock.Extensions;
using WireMock.Json;
using WireMock.Models;
using WireMock.Util;
namespace WireMock.Matchers;
/// <summary>
/// System.Linq.Dynamic.Core Expression Matcher
/// </summary>
/// <inheritdoc cref="IObjectMatcher"/>
/// <inheritdoc cref="IStringMatcher"/>
public class LinqMatcher : IObjectMatcher, IStringMatcher
{
private readonly AnyOf<string, StringPattern>[] _patterns;
/// <inheritdoc />
public MatchBehaviour MatchBehaviour { get; }
/// <inheritdoc />
public object Value { get; }
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="pattern">The pattern.</param>
public LinqMatcher(AnyOf<string, StringPattern> pattern) : this(new[] { pattern })
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="patterns">The patterns.</param>
public LinqMatcher(params AnyOf<string, StringPattern>[] patterns) : this(MatchBehaviour.AcceptOnMatch, MatchOperator.Or, patterns)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="pattern">The pattern.</param>
public LinqMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern) : this(matchBehaviour, MatchOperator.Or, pattern)
{
}
/// <summary>
/// Initializes a new instance of the <see cref="LinqMatcher"/> class.
/// </summary>
/// <param name="matchBehaviour">The match behaviour.</param>
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
/// <param name="patterns">The patterns.</param>
public LinqMatcher(
MatchBehaviour matchBehaviour,
MatchOperator matchOperator = MatchOperator.Or,
params AnyOf<string, StringPattern>[] patterns)
{
_patterns = Guard.NotNull(patterns);
MatchBehaviour = matchBehaviour;
MatchOperator = matchOperator;
Value = patterns;
}
/// <inheritdoc />
public MatchResult IsMatch(string? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
// Convert a single input string to a Queryable string-list with 1 entry.
IQueryable queryable = new[] { input }.AsQueryable();
try
{
// Use the Any(...) method to check if the result matches
score = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator);
}
catch (Exception e)
{
error = e;
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public MatchResult IsMatch(object? input)
{
var score = MatchScores.Mismatch;
Exception? error = null;
JArray jArray;
try
{
jArray = new JArray { input };
}
catch
{
jArray = input == null ? new JArray() : new JArray { JToken.FromObject(input) };
}
// Convert a single object to a Queryable JObject-list with 1 entry.
var queryable = jArray.ToDynamicClassArray().AsQueryable();
try
{
var patternsAsStringArray = _patterns.Select(p => p.GetPattern()).ToArray();
var scores = patternsAsStringArray.Select(p => queryable.Any(p)).ToArray();
score = MatchScores.ToScore(scores, MatchOperator);
}
catch (Exception e)
{
error = e;
}
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
}
/// <inheritdoc />
public AnyOf<string, StringPattern>[] GetPatterns()
{
return _patterns;
}
/// <inheritdoc />
public MatchOperator MatchOperator { get; }
/// <inheritdoc />
public string Name => nameof(LinqMatcher);
/// <inheritdoc />
public string GetCSharpCodeArguments()
{
return $"new {Name}" +
$"(" +
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
$")";
}
}

Some files were not shown because too many files have changed in this diff Show More