Compare commits

...

15 Commits

Author SHA1 Message Date
Stef Heyenrath fed1c87663 2.7.0 2026-05-24 10:25:30 +02:00
Stef Heyenrath e2e83abeb5 Trusted Publishing (#1465)
* Trusted Publishing

* push:

* "

* pwsh

* pack

* push:

* Trusted Publishing = OK
2026-05-24 10:21:02 +02:00
Stef Heyenrath 3aef0ad7a2 Update Scriban.Signed to latest (#1462) 2026-05-23 21:53:32 +02:00
Stef Heyenrath e68a73c3d5 Remove MultipartUploader project 2026-05-23 21:44:33 +02:00
Stef Heyenrath bd83a630ff WireMock.Net.Service 2026-05-23 21:42:34 +02:00
Michi 52ac7e37dc Update Testcontainers to 4.12.0 (#1461) 2026-05-23 20:46:52 +02:00
Michaël 0eccf43a8e chore: update Handlebars 2.5.2 to 2.5.5 #1458 (#1459) 2026-05-23 20:26:36 +02:00
dependabot[bot] fa423370b1 Update OpenTelemetry.Api from 1.14.0 to 1.15.3 in unit test project (#1457)
* Bump OpenTelemetry.Api from 1.14.0 to 1.15.3

---
updated-dependencies:
- dependency-name: OpenTelemetry.Api
  dependency-version: 1.15.3
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>

* chore: bump additional OpenTelemetry packages in UsingNuGet test project

Agent-Logs-Url: https://github.com/wiremock/WireMock.Net/sessions/bc8104f3-74b0-4a40-ac16-e404cbc230df

Co-authored-by: StefH <249938+StefH@users.noreply.github.com>

---------

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: StefH <249938+StefH@users.noreply.github.com>
2026-05-12 13:23:21 +02:00
Stef Heyenrath 1806ae39f8 2.6.0 2026-05-11 10:31:09 +02:00
Peter Benko 67acdcf1d3 Fix request storing when RequestLogExpirationDuration is set [bug] (#1455)
* Fix response timestamp

* Extracted new interface to own file
2026-05-11 10:28:38 +02:00
Stef Heyenrath 4bb378bdce 2.5.0 2026-05-04 18:52:29 +02:00
Stef Heyenrath f9df0d0ee9 Fix name in RequestMessageHeaderMatcher 2026-05-03 09:41:25 +02:00
Степан f8d3b51fbc Feature/early mismatch (#1451)
* feat(request matchers): Add support for early mismatch in mapping processing

* test(request matchers): Add unit test for early mismatch functionality

* test(grpc): Add test for grpc requests early mismatch and error logging (Issue #1442)

* feat(request matchers): RequestMatcherType

Add `RequestMatcherType` to request matchers for improved type
identification

Closes #1442

* refactor(request matchers): Request

Replace `EarlyMatcherSelector` with `EarlyMatcherType` for improved
clarity and consistency

Closes #1442

* feat(request): conversion

Add EarlyMatcherType support in request models and mapping conversion

Closes #1442

* test(mapping): new tests

add unit tests for EarlyMatcherType in mapping conversion and
serialization

Closes #1442

* refactor(request matchers): RequestMessageEarlyMatcher

Replaced inline `EarlyMatcherType` logic with the new
`RequestMessageEarlyMatcher` class to support cases when several
matchers of the same type are present. For instance - Header, Cookie,
Param

Closes #1442

* test(request matchers): Early Mismatch

add unit tests for early mismatch scenarios with several matchers of
same type. Currently, headers and parameters

Closes #1442

* refactor(mapping): RequestModel.EarlyMatcherType

use fully qualified enum for EarlyMatcherType in serialization

Closes #1442

* style(review): fixes

- removed unused method
- added missing curly brackets

Closes #1442
2026-05-03 09:27:19 +02:00
Copilot be9864461d Fix CVE-2026-40021: upgrade log4net to 3.3.0 in examples/WireMock.Net.Service/packages.config (#1453)
* Initial plan

* Fix CVE-2026-40021: update log4net to 3.3.0 in packages.config

Agent-Logs-Url: https://github.com/wiremock/WireMock.Net/sessions/a09a4576-1b17-41fe-9912-c1efdf922fed

Co-authored-by: StefH <249938+StefH@users.noreply.github.com>

---------

Co-authored-by: copilot-swe-agent[bot] <198982749+Copilot@users.noreply.github.com>
Co-authored-by: StefH <249938+StefH@users.noreply.github.com>
2026-05-02 19:46:13 +02:00
dependabot[bot] 4bb7e8af45 Bump log4net from 2.0.15 to 3.3.0 (#1452)
---
updated-dependencies:
- dependency-name: log4net
  dependency-version: 3.3.0
  dependency-type: direct:production
...

Signed-off-by: dependabot[bot] <support@github.com>
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
2026-05-02 18:30:43 +02:00
70 changed files with 684 additions and 351 deletions
+40
View File
@@ -0,0 +1,40 @@
name: Publish to NuGet
on:
workflow_dispatch:
jobs:
publish:
name: Build, Pack, and Publish
runs-on: windows-2022
permissions:
id-token: write # enable GitHub OIDC token issuance for this job
steps:
- name: Checkout repository
uses: actions/checkout@v4
- name: Build projects
shell: pwsh
run: |
Get-ChildItem ./src -Recurse -Filter *.csproj |
ForEach-Object {
dotnet build $_.FullName -c Release
}
- name: Pack projects
shell: pwsh
run: |
Get-ChildItem ./src -Recurse -Filter *.csproj |
ForEach-Object {
dotnet pack $_.FullName -c Release --no-build -o ./packages
}
- name: NuGet login (OIDC → temp API key)
uses: NuGet/login@v1
id: login
with:
user: ${{ secrets.NUGET_USER }}
- name: Push to NuGet
run: dotnet nuget push "**/packages/*.nupkg" --api-key ${{steps.login.outputs.NUGET_API_KEY}} --source "https://api.nuget.org/v3/index.json" --skip-duplicate
+18 -1
View File
@@ -1,6 +1,23 @@
# 2.7.0 (24 May 2026)
- [#1457](https://github.com/wiremock/WireMock.Net/pull/1457) - Update OpenTelemetry.Api from 1.14.0 to 1.15.3 in unit test project [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#1459](https://github.com/wiremock/WireMock.Net/pull/1459) - chore: update Handlebars 2.5.2 to 2.5.5 [dependencies] contributed by [kamisoft-fr](https://github.com/kamisoft-fr)
- [#1461](https://github.com/wiremock/WireMock.Net/pull/1461) - Update Testcontainers nuget package to 4.12.0 [dependencies] contributed by [MD-V](https://github.com/MD-V)
- [#1462](https://github.com/wiremock/WireMock.Net/pull/1462) - Update Scriban.Signed to latest [dependencies] contributed by [StefH](https://github.com/StefH)
- [#1458](https://github.com/wiremock/WireMock.Net/issues/1458) - update Handlebars Humanizer package version [feature]
# 2.6.0 (11 May 2026)
- [#1455](https://github.com/wiremock/WireMock.Net/pull/1455) - Fix request storing when RequestLogExpirationDuration is set [bug] [bug] contributed by [pbenko-xitaso](https://github.com/pbenko-xitaso)
- [#1454](https://github.com/wiremock/WireMock.Net/issues/1454) - No requests stored in Standalone when RequestLogExpirationDuration is set [bug]
# 2.5.0 (04 May 2026)
- [#1451](https://github.com/wiremock/WireMock.Net/pull/1451) - Feature/early mismatch [feature] contributed by [Stepami](https://github.com/Stepami)
- [#1452](https://github.com/wiremock/WireMock.Net/pull/1452) - Bump log4net from 2.0.15 to 3.3.0 in example console app [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#1453](https://github.com/wiremock/WireMock.Net/pull/1453) - Fix CVE-2026-40021: upgrade log4net to 3.3.0 in examples/WireMock.Net.Service/packages.config [dependencies] contributed by [Copilot](https://github.com/apps/copilot-swe-agent)
- [#1442](https://github.com/wiremock/WireMock.Net/issues/1442) - Bug: [grpc] WithBodyAsProtoBuf exception on match [bug]
# 2.4.0 (24 April 2026)
- [#1437](https://github.com/wiremock/WireMock.Net/pull/1437) - Added feature to enable and disable mappings [feature] contributed by [jayaraman-venkatesan](https://github.com/jayaraman-venkatesan)
- [#1450](https://github.com/wiremock/WireMock.Net/pull/1450) - Bump OpenTelemetry.Exporter.OpenTelemetryProtocol from 1.14.0 to 1.15.x [dependencies, .NET] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#1450](https://github.com/wiremock/WireMock.Net/pull/1450) - Bump OpenTelemetry.Exporter.OpenTelemetryProtocol from 1.14.0 to 1.15.x [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
- [#1421](https://github.com/wiremock/WireMock.Net/issues/1421) - Deactivate mapping without deleting it [feature]
# 2.3.0 (20 April 2026)
+1 -1
View File
@@ -4,7 +4,7 @@
</PropertyGroup>
<PropertyGroup>
<VersionPrefix>2.4.0</VersionPrefix>
<VersionPrefix>2.7.0</VersionPrefix>
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
+1 -1
View File
@@ -1,6 +1,6 @@
rem https://github.com/StefH/GitHubReleaseNotes
SET version=2.4.0
SET version=2.7.0
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels wontfix test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
+6 -4
View File
@@ -1,6 +1,8 @@
# 2.4.0 (24 April 2026)
- #1437 Added feature to enable and disable mappings [feature]
- #1450 Bump OpenTelemetry.Exporter.OpenTelemetryProtocol from 1.14.0 to 1.15.x [dependencies, .NET]
- #1421 Deactivate mapping without deleting it [feature]
# 2.7.0 (24 May 2026)
- #1457 Update OpenTelemetry.Api from 1.14.0 to 1.15.3 in unit test project [dependencies]
- #1459 chore: update Handlebars 2.5.2 to 2.5.5 [dependencies]
- #1461 Update Testcontainers nuget package to 4.12.0 [dependencies]
- #1462 Update Scriban.Signed to latest [dependencies]
- #1458 update Handlebars Humanizer package version [feature]
The full release notes can be found here: https://github.com/wiremock/WireMock.Net/blob/master/CHANGELOG.md
+15 -32
View File
@@ -38,8 +38,6 @@ 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.Service", "examples\Wiremock.Net.Service\WireMock.Net.Service.csproj", "{7F0B2446-0363-4720-AF46-F47F83B557DC}"
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}"
@@ -76,10 +74,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Testcontainers
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TestcontainersExample", "examples\WireMock.Net.TestcontainersExample\WireMock.Net.TestcontainersExample.csproj", "{56A38798-C48B-4A4A-B805-071E05C02CE1}"
EndProject
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "tools", "tools", "{0147029F-FA4A-44B3-B79A-3C3574054EE4}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "MultipartUploader", "tools\MultipartUploader\MultipartUploader.csproj", "{07C30227-ADEC-4BDE-8CDC-849D85A690BB}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET8", "examples\WireMock.Net.Console.NET8\WireMock.Net.Console.NET8.csproj", "{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}"
EndProject
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueProxy", "examples\WireMockAzureQueueProxy\WireMockAzureQueueProxy.csproj", "{7FC0B409-2682-40EE-B3B9-3930D6769D01}"
@@ -156,6 +150,8 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.TestWebApplica
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.RestClient.AwesomeAssertions", "src\WireMock.Net.RestClient.AwesomeAssertions\WireMock.Net.RestClient.AwesomeAssertions.csproj", "{F4B2B967-98D7-4D93-9A5C-5EF7B84B941A}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Service", "examples\WireMock.Net.Service\WireMock.Net.Service.csproj", "{7F0B2446-0363-4720-AF46-F47F83B557DC}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
@@ -238,18 +234,6 @@ Global
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x64.Build.0 = Release|Any CPU
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x86.ActiveCfg = Release|Any CPU
{74D91AD0-D96D-4FD2-AEC5-CC49D38346C0}.Release|x86.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.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
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.Build.0 = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.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}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -394,18 +378,6 @@ Global
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x64.Build.0 = Release|Any CPU
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x86.ActiveCfg = Release|Any CPU
{56A38798-C48B-4A4A-B805-071E05C02CE1}.Release|x86.Build.0 = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|Any CPU.Build.0 = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x64.ActiveCfg = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x64.Build.0 = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x86.ActiveCfg = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Debug|x86.Build.0 = Debug|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.ActiveCfg = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|Any CPU.Build.0 = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x64.ActiveCfg = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x64.Build.0 = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x86.ActiveCfg = Release|Any CPU
{07C30227-ADEC-4BDE-8CDC-849D85A690BB}.Release|x86.Build.0 = Release|Any CPU
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|Any CPU.Build.0 = Debug|Any CPU
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA}.Debug|x64.ActiveCfg = Debug|Any CPU
@@ -850,6 +822,18 @@ Global
{F4B2B967-98D7-4D93-9A5C-5EF7B84B941A}.Release|x64.Build.0 = Release|Any CPU
{F4B2B967-98D7-4D93-9A5C-5EF7B84B941A}.Release|x86.ActiveCfg = Release|Any CPU
{F4B2B967-98D7-4D93-9A5C-5EF7B84B941A}.Release|x86.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}.Debug|x64.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x64.Build.0 = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.ActiveCfg = Debug|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Debug|x86.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
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x64.Build.0 = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.ActiveCfg = Release|Any CPU
{7F0B2446-0363-4720-AF46-F47F83B557DC}.Release|x86.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
@@ -861,7 +845,6 @@ 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}
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {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}
@@ -876,7 +859,6 @@ Global
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{56A38798-C48B-4A4A-B805-071E05C02CE1} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{07C30227-ADEC-4BDE-8CDC-849D85A690BB} = {0147029F-FA4A-44B3-B79A-3C3574054EE4}
{1EA72C0F-92E9-486B-8FFE-53F992BFC4AA} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{7FC0B409-2682-40EE-B3B9-3930D6769D01} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{B1580A38-84E7-44BE-8FE7-3EE5031D74A1} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
@@ -914,6 +896,7 @@ Global
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
{3B05CC76-C3CB-8667-6B65-3129DFB25681} = {0BB8B634-407A-4610-A91F-11586990767A}
{F4B2B967-98D7-4D93-9A5C-5EF7B84B941A} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
EndGlobalSection
GlobalSection(ExtensibilityGlobals) = postSolution
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
@@ -16,7 +16,7 @@
<ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
<PackageReference Include="log4net" Version="2.0.15" />
<PackageReference Include="log4net" Version="3.3.0" />
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
</ItemGroup>
@@ -16,7 +16,7 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="WireMock.Net" Version="1.25.0" />
<PackageReference Include="WireMock.Net" Version="2.6.0" />
</ItemGroup>
</Project>
@@ -32,6 +32,9 @@
<ErrorReport>prompt</ErrorReport>
<WarningLevel>4</WarningLevel>
</PropertyGroup>
<PropertyGroup>
<StartupObject>Wiremock.Net.Service.Program</StartupObject>
</PropertyGroup>
<ItemGroup>
<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>
@@ -1,6 +1,6 @@
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="log4net" version="2.0.15" targetFramework="net48" />
<package id="log4net" version="3.3.0" targetFramework="net48" />
<package id="Microsoft.AspNet.WebApi.Client" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net452" />
@@ -246,8 +246,8 @@ internal class Program
throw new InvalidOperationException($"The {nameof(TestcontainersSettings.OS.DockerEndpointAuthConfig)} is null. Check if Docker is started.");
}
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
using var dockerClient = dockerClientConfig.CreateClient();
var dockerClientBuilder = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientBuilder();
using var dockerClient = dockerClientBuilder.Build();
var version = await dockerClient.System.GetVersionAsync();
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
@@ -1,5 +1,7 @@
// Copyright © WireMock.Net
using WireMock.Matchers.Request;
namespace WireMock.Admin.Mappings;
/// <summary>
@@ -61,9 +63,15 @@ public class RequestModel
/// Gets or sets the Params.
/// </summary>
public IList<ParamModel>? Params { get; set; }
/// <summary>
/// Gets or sets the body.
/// </summary>
public BodyModel? Body { get; set; }
/// <summary>
/// Type of the request matcher to return an immediate mismatch during mapping processing.
/// Optional.
/// </summary>
public RequestMatcherType? EarlyMatcherType { get; set; }
}
@@ -7,6 +7,11 @@ namespace WireMock.Matchers.Request;
/// </summary>
public interface IRequestMatcher
{
/// <summary>
/// Gets the request matcher's type.
/// </summary>
public RequestMatcherType Type { get; }
/// <summary>
/// Determines whether the specified RequestMessage is match.
/// </summary>
@@ -0,0 +1,84 @@
// Copyright © WireMock.Net
namespace WireMock.Matchers.Request;
/// <summary>
/// List of predefined request matcher types.
/// </summary>
public enum RequestMatcherType
{
/// <summary>
/// RequestMessageBodyMatcher
/// </summary>
Body = 0,
/// <summary>
/// RequestMessageBodyMatcher{T}
/// </summary>
BodyOfT = 1,
/// <summary>
/// RequestMessageClientIPMatcher
/// </summary>
ClientIP = 2,
/// <summary>
/// RequestMessageCookieMatcher
/// </summary>
Cookie = 3,
/// <summary>
/// RequestMessageGraphQLMatcher
/// </summary>
GraphQL = 4,
/// <summary>
/// RequestMessageHeaderMatcher
/// </summary>
Header = 5,
/// <summary>
/// RequestMessageHttpVersionMatcher
/// </summary>
HttpVersion = 6,
/// <summary>
/// RequestMessageMethodMatcher
/// </summary>
Method = 7,
/// <summary>
/// RequestMessageMultiPartMatcher
/// </summary>
MultiPart = 8,
/// <summary>
/// RequestMessageParamMatcher
/// </summary>
Param = 9,
/// <summary>
/// RequestMessagePathMatcher
/// </summary>
Path = 10,
/// <summary>
/// RequestMessageProtoBufMatcher
/// </summary>
ProtoBuf = 11,
/// <summary>
/// RequestMessageScenarioAndStateMatcher
/// </summary>
ScenarioAndState = 12,
/// <summary>
/// RequestMessageUrlMatcher
/// </summary>
Url = 13,
/// <summary>
/// RequestMessageCompositeMatcher
/// </summary>
Composite = 14
}
@@ -0,0 +1,16 @@
// Copyright © WireMock.Net
using System.Net;
namespace WireMock;
internal interface IResponseMessageBuilder
{
ResponseMessage Create(HttpStatusCode statusCode, string? status, Guid? guid = null);
ResponseMessage Create(int statusCode, string? status, Guid? guid = null);
ResponseMessage Create(int statusCode, string? status, string? error, Guid? guid = null);
ResponseMessage Create(HttpStatusCode statusCode);
}
+6 -2
View File
@@ -27,6 +27,7 @@ public class MappingBuilder : IMappingBuilder
private readonly MappingToFileSaver _mappingToFileSaver;
private readonly IGuidUtils _guidUtils;
private readonly IDateTimeUtils _dateTimeUtils;
private readonly IResponseMessageBuilder _responseMessageBuilder;
/// <summary>
/// Create a MappingBuilder
@@ -43,6 +44,7 @@ public class MappingBuilder : IMappingBuilder
_guidUtils = new GuidUtils();
_dateTimeUtils = new DateTimeUtils();
_responseMessageBuilder = new ResponseMessageBuilder(_dateTimeUtils);
}
internal MappingBuilder(
@@ -51,7 +53,8 @@ public class MappingBuilder : IMappingBuilder
MappingConverter mappingConverter,
MappingToFileSaver mappingToFileSaver,
IGuidUtils guidUtils,
IDateTimeUtils dateTimeUtils
IDateTimeUtils dateTimeUtils,
IResponseMessageBuilder responseMessageBuilder
)
{
_settings = Guard.NotNull(settings);
@@ -60,12 +63,13 @@ public class MappingBuilder : IMappingBuilder
_mappingToFileSaver = Guard.NotNull(mappingToFileSaver);
_guidUtils = Guard.NotNull(guidUtils);
_dateTimeUtils = Guard.NotNull(dateTimeUtils);
_responseMessageBuilder = Guard.NotNull(responseMessageBuilder);
}
/// <inheritdoc />
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
{
return new RespondWithAProvider(RegisterMapping, Guard.NotNull(requestMatcher), _settings, _guidUtils, _dateTimeUtils, saveToFile);
return new RespondWithAProvider(RegisterMapping, Guard.NotNull(requestMatcher), _settings, _guidUtils, _dateTimeUtils, _responseMessageBuilder, saveToFile);
}
/// <inheritdoc />
@@ -142,6 +142,9 @@ public class RequestMessageBodyMatcher : IRequestMatcher
MatchOperator = matchOperator;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Body;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -31,6 +31,9 @@ public class RequestMessageBodyMatcher<T> : IRequestMatcher
Func = Guard.NotNull(func);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.BodyOfT;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -74,6 +74,9 @@ public class RequestMessageClientIPMatcher : IRequestMatcher
Funcs = Guard.NotNull(funcs);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ClientIP;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -20,6 +20,11 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
/// </value>
private IEnumerable<IRequestMatcher> RequestMatchers { get; }
/// <summary>
/// Selected type to choose the matcher from <see cref="RequestMatchers"/> which will immediately return a mismatch.
/// </summary>
internal RequestMatcherType? EarlyMatcherType { get; private protected set; }
/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCompositeMatcher"/> class.
/// </summary>
@@ -31,6 +36,9 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
_type = type;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Composite;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -39,6 +47,13 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
return MatchScores.Mismatch;
}
var earlyMatcher = new RequestMessageEarlyMatcher(EarlyMatcherType, RequestMatchers);
var earlyMatchResult = earlyMatcher.GetMatchingScore(requestMessage, requestMatchResult);
if (!MatchScores.IsPerfect(earlyMatchResult))
{
return MatchScores.Mismatch;
}
if (_type == CompositeMatcherType.And)
{
return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
@@ -1,7 +1,6 @@
// Copyright © WireMock.Net
using Stef.Validation;
using System.Linq;
namespace WireMock.Matchers.Request;
@@ -93,6 +92,9 @@ public class RequestMessageCookieMatcher : IRequestMatcher
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Cookie;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -0,0 +1,35 @@
// Copyright © WireMock.Net
namespace WireMock.Matchers.Request;
/// <summary>
/// Return the mismatch if the matching score of matchers is not perfect.
/// </summary>
internal sealed class RequestMessageEarlyMatcher(
RequestMatcherType? earlyMatcherType,
IEnumerable<IRequestMatcher> requestMatchers) : IRequestMatcher
{
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Composite;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
if (earlyMatcherType is null)
{
return MatchScores.Perfect;
}
var earlyMatchers = requestMatchers
.Where(m => m.Type == earlyMatcherType)
.ToList();
if (earlyMatchers.Count is 0)
{
return MatchScores.Perfect;
}
var compositeMatcher = new RequestBuilders.Request(earlyMatchers);
return compositeMatcher.GetMatchingScore(requestMessage, requestMatchResult);
}
}
@@ -1,6 +1,5 @@
// Copyright © WireMock.Net
using System.Linq;
using Stef.Validation;
using WireMock.Types;
@@ -12,7 +11,7 @@ namespace WireMock.Matchers.Request;
/// <inheritdoc cref="IRequestMatcher"/>
public class RequestMessageHeaderMatcher : IRequestMatcher
{
private const string _name = nameof(RequestMessageCookieMatcher);
private const string _name = nameof(RequestMessageHeaderMatcher);
/// <summary>
/// MatchBehaviour
@@ -106,6 +105,9 @@ public class RequestMessageHeaderMatcher : IRequestMatcher
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Header;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -65,6 +65,9 @@ public class RequestMessageHttpVersionMatcher : IRequestMatcher
MatcherOnStringFunc = Guard.NotNull(func);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.HttpVersion;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -46,6 +46,9 @@ internal class RequestMessageMethodMatcher : IRequestMatcher
MatchOperator = matchOperator;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Method;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -55,6 +55,9 @@ public class RequestMessageMultiPartMatcher : IRequestMatcher
MatchOperator = matchOperator;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.MultiPart;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -82,6 +82,9 @@ public class RequestMessageParamMatcher : IRequestMatcher
Funcs = Guard.NotNull(funcs);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Param;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -72,6 +72,9 @@ public class RequestMessagePathMatcher : IRequestMatcher
Funcs = Guard.NotNull(funcs);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Path;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -29,6 +29,9 @@ internal class RequestMessageScenarioAndStateMatcher : IRequestMatcher
_executionConditionState = executionConditionState;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ScenarioAndState;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -72,6 +72,9 @@ public class RequestMessageUrlMatcher : IRequestMatcher
Funcs = Guard.NotNull(funcs);
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Url;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -72,6 +72,7 @@ internal partial class AspNetCoreSelfHost
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
services.AddSingleton<IGuidUtils, GuidUtils>();
services.AddSingleton<IDateTimeUtils, DateTimeUtils>();
services.AddSingleton<IResponseMessageBuilder, ResponseMessageBuilder>();
services.AddSingleton<LogEntryMapper>();
services.AddSingleton<IWireMockMiddlewareLogger, WireMockMiddlewareLogger>();
@@ -11,12 +11,14 @@ internal class GlobalExceptionMiddleware
{
private readonly IWireMockMiddlewareOptions _options;
private readonly IOwinResponseMapper _responseMapper;
private readonly IResponseMessageBuilder _responseMessageBuilder;
public GlobalExceptionMiddleware(RequestDelegate next, IWireMockMiddlewareOptions options, IOwinResponseMapper responseMapper)
public GlobalExceptionMiddleware(RequestDelegate next, IWireMockMiddlewareOptions options, IOwinResponseMapper responseMapper, IResponseMessageBuilder responseMessageBuilder)
{
Next = next;
_options = Guard.NotNull(options);
_responseMapper = Guard.NotNull(responseMapper);
_responseMessageBuilder = Guard.NotNull(responseMessageBuilder);
}
public RequestDelegate Next { get; }
@@ -35,7 +37,7 @@ internal class GlobalExceptionMiddleware
catch (Exception ex)
{
_options.Logger.Error("HttpStatusCode set to 500 {0}", ex);
await _responseMapper.MapAsync(ResponseMessageBuilder.Create(500, JsonConvert.SerializeObject(ex)), ctx.Response).ConfigureAwait(false);
await _responseMapper.MapAsync(_responseMessageBuilder.Create(500, JsonConvert.SerializeObject(ex)), ctx.Response).ConfigureAwait(false);
}
}
}
@@ -26,7 +26,8 @@ internal class WireMockMiddleware(
IMappingMatcher mappingMatcher,
IWireMockMiddlewareLogger logger,
IGuidUtils guidUtils,
IDateTimeUtils dateTimeUtils
IDateTimeUtils dateTimeUtils,
IResponseMessageBuilder responseMessageBuilder
)
{
private readonly object _lock = new();
@@ -97,7 +98,7 @@ internal class WireMockMiddleware(
{
logRequest = true;
options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
response = responseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
return;
}
@@ -109,7 +110,7 @@ internal class WireMockMiddleware(
if (!authorizationHeaderPresent)
{
options.Logger.Error("HttpStatusCode set to 401, authorization header is missing.");
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
response = responseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
return;
}
@@ -117,7 +118,7 @@ internal class WireMockMiddleware(
if (!MatchScores.IsPerfect(authorizationHeaderMatchResult.Score))
{
options.Logger.Error("HttpStatusCode set to 401, authentication failed.", authorizationHeaderMatchResult.Exception ?? throw new WireMockException("Authentication failed"));
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
response = responseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
return;
}
}
@@ -165,7 +166,7 @@ internal class WireMockMiddleware(
options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
WireMockActivitySource.RecordException(activity, ex);
response = ResponseMessageBuilder.Create(500, ex.Message);
response = responseMessageBuilder.Create(500, ex.Message);
}
finally
{
@@ -179,7 +180,7 @@ internal class WireMockMiddleware(
{
options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex);
var notFoundResponse = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
var notFoundResponse = responseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
await responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false);
}
}
@@ -34,7 +34,7 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
/// Initializes a new instance of the <see cref="Request"/> class.
/// </summary>
/// <param name="requestMatchers">The request matchers.</param>
private Request(IList<IRequestMatcher> requestMatchers) : base(requestMatchers)
internal Request(IList<IRequestMatcher> requestMatchers) : base(requestMatchers)
{
_requestMatchers = Guard.NotNull(requestMatchers);
}
@@ -81,6 +81,13 @@ public partial class Request : RequestMessageCompositeMatcher, IRequestBuilder
return this;
}
/// <inheritdoc />
public IRequestBuilder WithEarlyMismatch(RequestMatcherType? earlyMatcherType)
{
EarlyMatcherType = earlyMatcherType;
return this;
}
internal bool TryGetProtoBufMatcher([NotNullWhen(true)] out IProtoBufMatcher? protoBufMatcher)
{
protoBufMatcher = GetRequestMessageMatcher<RequestMessageProtoBufMatcher>()?.Matcher;
@@ -9,29 +9,30 @@ using WireMock.Util;
namespace WireMock;
internal static class ResponseMessageBuilder
internal class ResponseMessageBuilder(IDateTimeUtils dateTimeUtils) : IResponseMessageBuilder
{
private static readonly IDictionary<string, WireMockList<string>> ContentTypeJsonHeaders = new Dictionary<string, WireMockList<string>>
{
{ HttpKnownHeaderNames.ContentType, new WireMockList<string> { WireMockConstants.ContentTypeJson } }
};
internal static ResponseMessage Create(HttpStatusCode statusCode, string? status, Guid? guid = null)
public ResponseMessage Create(HttpStatusCode statusCode, string? status, Guid? guid = null)
{
return Create((int)statusCode, status, guid);
return Create((int)statusCode, status, null, guid);
}
internal static ResponseMessage Create(int statusCode, string? status, Guid? guid = null)
public ResponseMessage Create(int statusCode, string? status, Guid? guid = null)
{
return Create(statusCode, status, null, guid);
}
internal static ResponseMessage Create(int statusCode, string? status, string? error, Guid? guid = null)
public ResponseMessage Create(int statusCode, string? status, string? error, Guid? guid = null)
{
var response = new ResponseMessage
{
StatusCode = statusCode,
Headers = ContentTypeJsonHeaders
Headers = ContentTypeJsonHeaders,
DateTime = dateTimeUtils.UtcNow
};
if (status != null || error != null)
@@ -51,7 +52,7 @@ internal static class ResponseMessageBuilder
return response;
}
internal static ResponseMessage Create(HttpStatusCode statusCode)
public ResponseMessage Create(HttpStatusCode statusCode)
{
return new ResponseMessage
{
@@ -16,7 +16,7 @@ using WireMock.WebSockets;
namespace WireMock.ResponseProviders;
internal class WebSocketResponseProvider(WebSocketBuilder builder, IGuidUtils guidUtils, IDateTimeUtils dateTimeUtils) : IResponseProvider
internal class WebSocketResponseProvider(WebSocketBuilder builder, IGuidUtils guidUtils, IDateTimeUtils dateTimeUtils, IResponseMessageBuilder responseMessageBuilder) : IResponseProvider
{
public async Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(
IMapping mapping,
@@ -27,7 +27,7 @@ internal class WebSocketResponseProvider(WebSocketBuilder builder, IGuidUtils gu
// Check if this is a WebSocket upgrade request
if (!context.WebSockets.IsWebSocketRequest)
{
return (ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Bad Request: Not a WebSocket upgrade request"), null);
return (responseMessageBuilder.Create(HttpStatusCode.BadRequest, "Bad Request: Not a WebSocket upgrade request"), null);
}
if (!context.Items.TryGetValue<IWireMockMiddlewareOptions>(nameof(IWireMockMiddlewareOptions), out var options))
@@ -110,7 +110,7 @@ internal class WebSocketResponseProvider(WebSocketBuilder builder, IGuidUtils gu
// If we haven't upgraded yet, we can return HTTP error
if (!context.Response.HasStarted)
{
return (ResponseMessageBuilder.Create(HttpStatusCode.InternalServerError, $"WebSocket error: {ex.Message}"), null);
return (responseMessageBuilder.Create(HttpStatusCode.InternalServerError, $"WebSocket error: {ex.Message}"), null);
}
// Already upgraded - return marker
@@ -66,6 +66,12 @@ internal class MappingConverter(MatcherMapper mapper)
// Request
sb.AppendLine(" .Given(Request.Create()");
if (request.EarlyMatcherType != null)
{
sb.AppendLine($" .WithEarlyMismatch({request.EarlyMatcherType.Value.GetFullyQualifiedEnumValue()})");
}
sb.AppendLine($" .UsingMethod({To1Or2Or3Arguments(methodMatcher?.MatchBehaviour, methodMatcher?.MatchOperator, methodMatcher?.Methods, HttpRequestMethod.GET)})");
if (pathMatcher?.Matchers != null)
@@ -300,7 +306,9 @@ internal class MappingConverter(MatcherMapper mapper)
IgnoreCase = pm.IgnoreCase ? true : null,
RejectOnMatch = pm.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : null,
Matchers = _mapper.Map(pm.Matchers)
}).ToList() : null
}).ToList() : null,
EarlyMatcherType = request.EarlyMatcherType
},
Response = new ResponseModel()
};
@@ -24,6 +24,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
private readonly WireMockServerSettings _settings;
private readonly IDateTimeUtils _dateTimeUtils;
private readonly IGuidUtils _guidUtils;
private readonly IResponseMessageBuilder _responseMessageBuilder;
private readonly bool _saveToFile;
@@ -56,6 +57,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
WireMockServerSettings settings,
IGuidUtils guidUtils,
IDateTimeUtils dateTimeUtils,
IResponseMessageBuilder responseMessageBuilder,
bool saveToFile = false
)
{
@@ -64,6 +66,7 @@ internal class RespondWithAProvider : IRespondWithAProvider
_settings = Guard.NotNull(settings);
_dateTimeUtils = Guard.NotNull(dateTimeUtils);
_guidUtils = Guard.NotNull(guidUtils);
_responseMessageBuilder = Guard.NotNull(responseMessageBuilder);
_saveToFile = saveToFile;
@@ -79,7 +82,8 @@ internal class RespondWithAProvider : IRespondWithAProvider
provider = new WebSocketResponseProvider(
response.WebSocketBuilder,
_guidUtils,
_dateTimeUtils
_dateTimeUtils,
_responseMessageBuilder
);
}
@@ -350,7 +350,7 @@ public partial class WireMockServer
o.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate;
});
return ResponseMessageBuilder.Create(200, "Settings updated");
return _responseMessageBuilder.Create(200, "Settings updated");
}
#endregion Settings
@@ -361,7 +361,7 @@ public partial class WireMockServer
if (mapping == null)
{
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
var model = _mappingConverter.ToMappingModel(mapping);
@@ -377,14 +377,14 @@ public partial class WireMockServer
if (code is null)
{
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
return ToResponseMessage(code);
}
_settings.Logger.Warn("HttpStatusCode set to 400");
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "GUID is missing");
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, "GUID is missing");
}
private static TEnum GetEnumFromQuery<TEnum>(IRequestMessage requestMessage, TEnum defaultValue)
@@ -411,22 +411,22 @@ public partial class WireMockServer
var mappingModel = DeserializeObject<MappingModel>(requestMessage);
var guidFromPut = ConvertMappingAndRegisterAsRespondProvider(mappingModel, guid);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping added or updated", guidFromPut);
return _responseMessageBuilder.Create(HttpStatusCode.OK, "Mapping added or updated", guidFromPut);
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
private IResponseMessage MappingDelete(HttpContext _, IRequestMessage requestMessage)
{
if (TryParseGuidFromRequestMessage(requestMessage, out var guid) && DeleteMapping(guid))
{
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping removed", guid);
return _responseMessageBuilder.Create(HttpStatusCode.OK, "Mapping removed", guid);
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
private static bool TryParseGuidFromRequestMessage(IRequestMessage requestMessage, out Guid guid)
@@ -452,12 +452,12 @@ public partial class WireMockServer
if (mapping != null)
{
mapping.IsDisabled = false;
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping enabled", guid);
return _responseMessageBuilder.Create(HttpStatusCode.OK, "Mapping enabled", guid);
}
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
private IResponseMessage MappingDisable(HttpContext _, IRequestMessage requestMessage)
@@ -468,12 +468,12 @@ public partial class WireMockServer
if (mapping != null)
{
mapping.IsDisabled = true;
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "Mapping disabled", guid);
return _responseMessageBuilder.Create(HttpStatusCode.OK, "Mapping disabled", guid);
}
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Mapping not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Mapping not found");
}
#endregion Mapping/{guid}
@@ -496,7 +496,7 @@ public partial class WireMockServer
{
SaveStaticMappings();
return ResponseMessageBuilder.Create(200, "Mappings saved to disk");
return _responseMessageBuilder.Create(200, "Mappings saved to disk");
}
private MappingModel[] ToMappingModels()
@@ -526,22 +526,22 @@ public partial class WireMockServer
if (mappingModels.Length == 1)
{
var guid = ConvertMappingAndRegisterAsRespondProvider(mappingModels[0]);
return ResponseMessageBuilder.Create(201, "Mapping added", guid);
return _responseMessageBuilder.Create(201, "Mapping added", guid);
}
ConvertMappingsAndRegisterAsRespondProvider(mappingModels);
return ResponseMessageBuilder.Create(201, "Mappings added");
return _responseMessageBuilder.Create(201, "Mappings added");
}
catch (ArgumentException a)
{
_settings.Logger.Error("HttpStatusCode set to 400 {0}", a);
return ResponseMessageBuilder.Create(400, a.Message);
return _responseMessageBuilder.Create(400, a.Message);
}
catch (Exception e)
{
_settings.Logger.Error("HttpStatusCode set to 500 {0}", e);
return ResponseMessageBuilder.Create(500, e.ToString());
return _responseMessageBuilder.Create(500, e.ToString());
}
}
@@ -552,18 +552,18 @@ public partial class WireMockServer
var deletedGuids = MappingsDeleteMappingFromBody(requestMessage);
if (deletedGuids != null)
{
return ResponseMessageBuilder.Create(200, $"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]");
return _responseMessageBuilder.Create(200, $"Mappings deleted. Affected GUIDs: [{string.Join(", ", deletedGuids.ToArray())}]");
}
// return bad request
return ResponseMessageBuilder.Create(400, "Poorly formed mapping JSON.");
return _responseMessageBuilder.Create(400, "Poorly formed mapping JSON.");
}
ResetMappings();
ResetScenarios();
return ResponseMessageBuilder.Create(200, "Mappings deleted");
return _responseMessageBuilder.Create(200, "Mappings deleted");
}
private IEnumerable<Guid>? MappingsDeleteMappingFromBody(IRequestMessage requestMessage)
@@ -615,14 +615,14 @@ public partial class WireMockServer
message += " and static mappings reloaded";
}
return ResponseMessageBuilder.Create(200, message);
return _responseMessageBuilder.Create(200, message);
}
private IResponseMessage ReloadStaticMappings(HttpContext _, IRequestMessage __)
{
ReadStaticMappings();
return ResponseMessageBuilder.Create(200, "Static Mappings reloaded");
return _responseMessageBuilder.Create(200, "Static Mappings reloaded");
}
#endregion Mappings
@@ -640,18 +640,18 @@ public partial class WireMockServer
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Request not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found");
}
private IResponseMessage RequestDelete(HttpContext _, IRequestMessage requestMessage)
{
if (TryParseGuidFromRequestMessage(requestMessage, out var guid) && DeleteLogEntry(guid))
{
return ResponseMessageBuilder.Create(200, "Request removed");
return _responseMessageBuilder.Create(200, "Request removed");
}
_settings.Logger.Warn("HttpStatusCode set to 404 : Request not found");
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "Request not found");
}
#endregion Request/{guid}
@@ -670,7 +670,7 @@ public partial class WireMockServer
{
ResetLogEntries();
return ResponseMessageBuilder.Create(200, "Requests deleted");
return _responseMessageBuilder.Create(200, "Requests deleted");
}
#endregion Requests
@@ -710,7 +710,7 @@ public partial class WireMockServer
return ToJson(result);
}
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest);
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest);
}
#endregion Requests/find
@@ -733,7 +733,7 @@ public partial class WireMockServer
{
ResetScenarios();
return ResponseMessageBuilder.Create(200, "Scenarios reset");
return _responseMessageBuilder.Create(200, "Scenarios reset");
}
private IResponseMessage ScenarioReset(HttpContext _, IRequestMessage requestMessage)
@@ -743,8 +743,8 @@ public partial class WireMockServer
Enumerable.Reverse(requestMessage.Path.Split('/')).Skip(1).First();
return ResetScenario(name) ?
ResponseMessageBuilder.Create(200, "Scenario reset") :
ResponseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
_responseMessageBuilder.Create(200, "Scenario reset") :
_responseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
}
private IResponseMessage ScenariosSetState(HttpContext _, IRequestMessage requestMessage)
@@ -752,14 +752,14 @@ public partial class WireMockServer
var name = Enumerable.Reverse(requestMessage.Path.Split('/')).Skip(1).First();
if (!_options.ScenarioStateStore.ContainsKey(name))
{
ResponseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
_responseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
}
var update = DeserializeObject<ScenarioStateUpdateModel>(requestMessage);
return SetScenarioState(name, update.State) ?
ResponseMessageBuilder.Create(200, $"Scenario state set to '{update.State}'") :
ResponseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
_responseMessageBuilder.Create(200, $"Scenario state set to '{update.State}'") :
_responseMessageBuilder.Create(HttpStatusCode.NotFound, $"No scenario found by name '{name}'.");
}
#endregion
@@ -18,14 +18,14 @@ public partial class WireMockServer
{
if (requestMessage.Body is null)
{
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
var id = requestMessage.Path.Split('/').Last();
AddProtoDefinition(id, requestMessage.Body);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "ProtoDefinition added");
return _responseMessageBuilder.Create(HttpStatusCode.OK, "ProtoDefinition added");
}
#endregion
@@ -34,7 +34,7 @@ public partial class WireMockServer
{
if (requestMessage.BodyAsBytes is null)
{
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
var filename = GetFileNameFromRequestMessage(requestMessage);
@@ -47,14 +47,14 @@ public partial class WireMockServer
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File created");
return _responseMessageBuilder.Create(HttpStatusCode.OK, "File created");
}
private IResponseMessage FilePut(HttpContext _, IRequestMessage requestMessage)
{
if (requestMessage.BodyAsBytes is null)
{
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, "Body is null");
}
var filename = GetFileNameFromRequestMessage(requestMessage);
@@ -62,12 +62,12 @@ public partial class WireMockServer
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist, updating file will be skipped.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
_settings.FileSystemHandler.WriteFile(filename, requestMessage.BodyAsBytes);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File updated");
return _responseMessageBuilder.Create(HttpStatusCode.OK, "File updated");
}
private IResponseMessage FileGet(HttpContext _, IRequestMessage requestMessage)
@@ -77,7 +77,7 @@ public partial class WireMockServer
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not found");
}
var bytes = _settings.FileSystemHandler.ReadFile(filename);
@@ -112,10 +112,10 @@ public partial class WireMockServer
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound);
return _responseMessageBuilder.Create(HttpStatusCode.NotFound);
}
return ResponseMessageBuilder.Create(HttpStatusCode.NoContent);
return _responseMessageBuilder.Create(HttpStatusCode.NoContent);
}
private IResponseMessage FileDelete(HttpContext _, IRequestMessage requestMessage)
@@ -125,11 +125,11 @@ public partial class WireMockServer
if (!_settings.FileSystemHandler.FileExists(filename))
{
_settings.Logger.Info("The file '{0}' does not exist.", filename);
return ResponseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not deleted");
return _responseMessageBuilder.Create(HttpStatusCode.NotFound, "File is not deleted");
}
_settings.FileSystemHandler.DeleteFile(filename);
return ResponseMessageBuilder.Create(HttpStatusCode.OK, "File deleted.");
return _responseMessageBuilder.Create(HttpStatusCode.OK, "File deleted.");
}
private string GetFileNameFromRequestMessage(IRequestMessage requestMessage)
@@ -268,6 +268,8 @@ public partial class WireMockServer
}
}
requestBuilder = requestBuilder.WithEarlyMismatch(requestModel.EarlyMatcherType);
return requestBuilder;
}
@@ -52,7 +52,7 @@ public partial class WireMockServer
if (mappingModels.Length == 1)
{
var guid = ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModels[0]);
return ResponseMessageBuilder.Create(201, "Mapping added", guid);
return _responseMessageBuilder.Create(201, "Mapping added", guid);
}
foreach (var mappingModel in mappingModels)
@@ -60,17 +60,17 @@ public partial class WireMockServer
ConvertWireMockOrgMappingAndRegisterAsRespondProvider(mappingModel);
}
return ResponseMessageBuilder.Create(201, "Mappings added");
return _responseMessageBuilder.Create(201, "Mappings added");
}
catch (ArgumentException a)
{
_settings.Logger.Error("HttpStatusCode set to 400 {0}", a);
return ResponseMessageBuilder.Create(400, a.Message);
return _responseMessageBuilder.Create(400, a.Message);
}
catch (Exception e)
{
_settings.Logger.Error("HttpStatusCode set to 500 {0}", e);
return ResponseMessageBuilder.Create(500, e.ToString());
return _responseMessageBuilder.Create(500, e.ToString());
}
}
@@ -19,7 +19,7 @@ public partial class WireMockServer
catch (Exception e)
{
_settings.Logger.Error("HttpStatusCode set to {0} {1}", HttpStatusCode.BadRequest, e);
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message);
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message);
}
}
@@ -35,12 +35,12 @@ public partial class WireMockServer
ConvertMappingsAndRegisterAsRespondProvider(mappingModels);
return ResponseMessageBuilder.Create(HttpStatusCode.Created, "OpenApi document converted to Mappings");
return _responseMessageBuilder.Create(HttpStatusCode.Created, "OpenApi document converted to Mappings");
}
catch (Exception e)
{
_settings.Logger.Error("HttpStatusCode set to {0} {1}", HttpStatusCode.BadRequest, e);
return ResponseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message);
return _responseMessageBuilder.Create(HttpStatusCode.BadRequest, e.Message);
}
}
}
@@ -42,6 +42,7 @@ public partial class WireMockServer : IWireMockServer
private readonly MappingBuilder _mappingBuilder;
private readonly IGuidUtils _guidUtils = new GuidUtils();
private readonly IDateTimeUtils _dateTimeUtils = new DateTimeUtils();
private readonly IResponseMessageBuilder _responseMessageBuilder;
private readonly MappingSerializer _mappingSerializer;
/// <inheritdoc />
@@ -354,6 +355,8 @@ public partial class WireMockServer : IWireMockServer
{
_settings = Guard.NotNull(settings);
_responseMessageBuilder = new ResponseMessageBuilder(_dateTimeUtils);
_mappingSerializer = new MappingSerializer(settings.DefaultJsonSerializer ?? new NewtonsoftJsonConverter());
// Set default values if not provided
@@ -407,7 +410,8 @@ public partial class WireMockServer : IWireMockServer
_mappingConverter,
_mappingToFileSaver,
_guidUtils,
_dateTimeUtils
_dateTimeUtils,
_responseMessageBuilder
);
_options.AdditionalServiceRegistration = _settings.AdditionalServiceRegistration;
@@ -471,7 +475,7 @@ public partial class WireMockServer : IWireMockServer
Given(Request.Create().WithPath("/*").UsingAnyMethod())
.WithGuid(Guid.Parse("90008000-0000-4444-a17e-669cd84f1f05"))
.AtPriority(1000)
.RespondWith(new DynamicResponseProvider((_, _) => ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound)));
.RespondWith(new DynamicResponseProvider((_, _) => _responseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound)));
}
/// <inheritdoc cref="IWireMockServer.Reset" />
@@ -43,7 +43,7 @@
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="TinyMapper.Signed" Version="4.0.0" />
<PackageReference Include="Microsoft.IdentityModel.Protocols.OpenIdConnect" Version="6.34.0" />
<PackageReference Include="Scriban.Signed" Version="7.0.6" />
<PackageReference Include="Scriban.Signed" Version="7.2.0" />
</ItemGroup>
<ItemGroup>
@@ -69,6 +69,9 @@ public class RequestMessageGraphQLMatcher : IRequestMatcher
MatchOperator = matchOperator;
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.GraphQL;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -30,6 +30,9 @@ public class RequestMessageProtoBufMatcher : IRequestMatcher
}
}
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ProtoBuf;
/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
@@ -10,7 +10,8 @@ namespace WireMock.RequestBuilders;
public interface IRequestBuilder : IClientIPRequestBuilder
{
/// <summary>
/// Adds a request matcher to the builder.
/// Adds a request matcher to the builder.<br/>
/// If the request matcher is already present, it will be replaced.
/// </summary>
/// <typeparam name="T">The type of the request matcher.</typeparam>
/// <param name="requestMatcher">The request matcher to add.</param>
@@ -21,4 +22,11 @@ public interface IRequestBuilder : IClientIPRequestBuilder
/// The link back to the Mapping.
/// </summary>
IMapping Mapping { get; set; }
/// <summary>
/// Chooses the <see cref="IRequestMatcher"/> which immediately returns a mismatch during mappings enumeration.
/// </summary>
/// <param name="earlyMatcherType">Selected type to choose the matcher from available list.</param>
/// <returns>The current <see cref="IRequestBuilder"/> instance.</returns>
IRequestBuilder WithEarlyMismatch(RequestMatcherType? earlyMatcherType);
}
@@ -34,14 +34,14 @@
</ItemGroup>
<ItemGroup>
<PackageReference Include="Handlebars.Net.Helpers" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers" Version="2.5.5" />
<!--<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.5.2" />-->
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.Xslt" Version="2.5.2" />
<PackageReference Include="Handlebars.Net.Helpers.Humanizer" Version="2.5.5" />
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.5.5" />
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.5.5" />
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.5.5" />
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.5.5" />
<PackageReference Include="Handlebars.Net.Helpers.Xslt" Version="2.5.5" />
</ItemGroup>
<ItemGroup>
@@ -22,8 +22,8 @@ public static class TestcontainersUtils
throw new InvalidOperationException($"The {nameof(TestcontainersSettings.OS.DockerEndpointAuthConfig)} is null. Check if Docker is started.");
}
using var dockerClientConfig = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientConfiguration();
using var dockerClient = dockerClientConfig.CreateClient();
var dockerClientBuilder = TestcontainersSettings.OS.DockerEndpointAuthConfig.GetDockerClientBuilder();
using var dockerClient = dockerClientBuilder.Build();
var version = await dockerClient.System.GetVersionAsync();
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
@@ -39,7 +39,7 @@
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
</PackageReference>
<PackageReference Include="Stef.Validation" Version="0.2.0" />
<PackageReference Include="Testcontainers" Version="4.10.0" />
<PackageReference Include="Testcontainers" Version="4.12.0" />
</ItemGroup>
<ItemGroup>
@@ -30,6 +30,12 @@
<ItemGroup>
<PackageReference Update="JetBrains.Annotations" Version="2025.2.4" />
<PackageReference Include="OpenTelemetry" Version="1.15.3" />
<PackageReference Include="OpenTelemetry.Api" Version="1.15.3" />
<PackageReference Include="OpenTelemetry.Api.ProviderBuilderExtensions" Version="1.15.3" />
<PackageReference Include="OpenTelemetry.Exporter.OpenTelemetryProtocol" Version="1.15.3" />
<PackageReference Include="OpenTelemetry.Extensions.Hosting" Version="1.15.3" />
<PackageReference Include="OpenTelemetry.Instrumentation.AspNetCore" Version="1.15.2" />
<PackageReference Update="SonarAnalyzer.CSharp" Version="10.11.0.117924" />
</ItemGroup>
@@ -8,8 +8,11 @@ using ExampleIntegrationTest.Lookup;
using Google.Protobuf.WellKnownTypes;
using Greet;
using Grpc.Net.Client;
using Moq;
using WireMock.Constants;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Net.Xunit;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
using WireMock.Server;
@@ -78,7 +81,7 @@ import ""google/protobuf/empty.proto"";
service Greeter {
rpc Nothing (google.protobuf.Empty) returns (google.protobuf.Empty);
rpc SayHello (HelloRequest) returns (HelloReply);
rpc SayOther (Other) returns (HelloReply);
@@ -731,6 +734,93 @@ message Other {
Then_ReplyMessage_Should_BeCorrect(reply);
}
[Theory]
[InlineData(true)]
[InlineData(false)]
public async Task WireMockServer_WithBodyAsProtoBuf_WithEarlyMismatch_ErrorLogs_Issue1442(
bool withEarlyMismatch)
{
// Arrange
var greeterId = $"test-greeter-{Guid.NewGuid()}";
var policyId = $"test-policy-{Guid.NewGuid()}";
var ct = TestContext.Current.CancellationToken;
var greeterProtoDefinition = ProtoDefinition;
var policyProtoDefinition = File.ReadAllText("./Grpc/policy.proto");
var mockTestOutputHelper = new Mock<ITestOutputHelper>();
using var server = WireMockServer.Start(new WireMockServerSettings
{
UseHttp2 = true,
Logger = new TestOutputHelperWireMockLogger(mockTestOutputHelper.Object)
});
server
.AddProtoDefinition(greeterId, greeterProtoDefinition)
.Given(Request.Create()
.UsingPost()
.WithHttpVersion("2")
.WithPath("/greet.Greeter/SayHello")
.WithEarlyMismatch(withEarlyMismatch
? RequestMatcherType.Path
: null)
.WithBodyAsProtoBuf("greet.HelloRequest", new JsonMatcher(new { name = "stef" })))
.WithProtoDefinition(greeterId)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithTrailingHeader("grpc-status", "0")
.WithBodyAsProtoBuf("greet.HelloReply",
new
{
message = "hello {{request.BodyAsJson.name}} {{request.method}}"
})
.WithTransformer());
server
.AddProtoDefinition(policyId, policyProtoDefinition)
.Given(Request.Create()
.UsingPost()
.WithHttpVersion("2")
.WithPath("/Policy.PolicyService/GetVersion")
.WithEarlyMismatch(withEarlyMismatch
? RequestMatcherType.Path
: null)
.WithBodyAsProtoBuf("ExampleIntegrationTest.Lookup.GetVersionRequest", new NotNullOrEmptyMatcher()))
.WithProtoDefinition(policyId)
.RespondWith(Response.Create()
.WithHeader("Content-Type", "application/grpc")
.WithTrailingHeader("grpc-status", "0")
.WithBodyAsProtoBuf("ExampleIntegrationTest.Lookup.GetVersionResponse",
new GetVersionResponse
{
Version = "test",
DateHired = new Timestamp
{
Seconds = 1722301323,
Nanos = 12300
},
Client = new ExampleIntegrationTest.Lookup.Client
{
ClientName = ExampleIntegrationTest.Lookup.Client.Types.Clients.Test,
CorrelationId = "correlation"
}
})
.WithTransformer());
// Act
var channel = GrpcChannel.ForAddress(server.Url!);
var policyServiceClient = new PolicyService.PolicyServiceClient(channel);
var greeterClient = new Greeter.GreeterClient(channel);
_ = await policyServiceClient.GetVersionAsync(new GetVersionRequest(), cancellationToken: ct);
_ = await greeterClient.SayHelloAsync(new HelloRequest { Name = "stef" }, cancellationToken: ct);
mockTestOutputHelper.Verify(
x => x.WriteLine(
It.Is<string>(log => log.Contains("[Error]") && log.Contains("Exception"))),
withEarlyMismatch ? Times.Never : Times.AtLeastOnce);
}
private static WireMockServer Given_When_ServerStarted_And_RunningOnHttpAndGrpc()
{
var settings = new WireMockServerSettings
@@ -59,7 +59,8 @@ public class MappingBuilderTests
mappingConverter,
mappingToFileSaver,
guidUtilsMock.Object,
dateTimeUtilsMock.Object
dateTimeUtilsMock.Object,
new ResponseMessageBuilder(dateTimeUtilsMock.Object)
);
_sut.Given(Request.Create()
@@ -5,6 +5,7 @@ using Moq;
using WireMock.Logging;
using WireMock.Owin;
using WireMock.Owin.Mappers;
using WireMock.Util;
namespace WireMock.Net.Tests.Owin;
@@ -12,6 +13,7 @@ public class GlobalExceptionMiddlewareTests
{
private readonly Mock<IWireMockMiddlewareOptions> _optionsMock;
private readonly Mock<IOwinResponseMapper> _responseMapperMock;
private readonly IResponseMessageBuilder _responseMessageBuilder;
private readonly GlobalExceptionMiddleware _sut;
@@ -23,7 +25,9 @@ public class GlobalExceptionMiddlewareTests
_responseMapperMock = new Mock<IOwinResponseMapper>();
_responseMapperMock.Setup(m => m.MapAsync(It.IsAny<ResponseMessage?>(), It.IsAny<HttpResponse>())).Returns(Task.FromResult(true));
_sut = new GlobalExceptionMiddleware(_ => Task.CompletedTask, _optionsMock.Object, _responseMapperMock.Object);
_responseMessageBuilder = new ResponseMessageBuilder(new DateTimeUtils());
_sut = new GlobalExceptionMiddleware(_ => Task.CompletedTask, _optionsMock.Object, _responseMapperMock.Object, _responseMessageBuilder);
}
[Fact]
@@ -37,7 +41,7 @@ public class GlobalExceptionMiddlewareTests
public void GlobalExceptionMiddleware_Invoke_InvalidNext_ShouldCallResponseMapperWith500()
{
// Arrange
var sut = new GlobalExceptionMiddleware(_ => throw new ArgumentException(), _optionsMock.Object, _responseMapperMock.Object);
var sut = new GlobalExceptionMiddleware(_ => throw new ArgumentException(), _optionsMock.Object, _responseMapperMock.Object, _responseMessageBuilder);
// Act
sut.Invoke(Mock.Of<HttpContext>());
@@ -3,6 +3,7 @@
using System.Collections.Concurrent;
using System.Diagnostics;
using System.Linq.Expressions;
using System.Net;
using Microsoft.AspNetCore.Http;
using Moq;
using WireMock.Admin.Mappings;
@@ -38,6 +39,7 @@ public class WireMockMiddlewareTests
private readonly Mock<HttpContext> _contextMock;
private readonly Mock<IGuidUtils> _guidUtilsMock;
private readonly Mock<IDateTimeUtils> _dateTimeUtilsMock;
private readonly IResponseMessageBuilder _responseMessageBuilderMock;
private readonly WireMockMiddleware _sut;
@@ -51,6 +53,8 @@ public class WireMockMiddlewareTests
_dateTimeUtilsMock = new Mock<IDateTimeUtils>();
_dateTimeUtilsMock.Setup(d => d.UtcNow).Returns(UtcNow);
_responseMessageBuilderMock = new ResponseMessageBuilder(_dateTimeUtilsMock.Object);
_optionsMock = new Mock<IWireMockMiddlewareOptions>();
_optionsMock.SetupAllProperties();
_optionsMock.Setup(o => o.Mappings).Returns(_mappings);
@@ -90,7 +94,8 @@ public class WireMockMiddlewareTests
_matcherMock.Object,
wireMockMiddlewareLoggerMock.Object,
_guidUtilsMock.Object,
_dateTimeUtilsMock.Object
_dateTimeUtilsMock.Object,
_responseMessageBuilderMock
);
}
@@ -103,7 +108,10 @@ public class WireMockMiddlewareTests
// Assert and Verify
_optionsMock.Verify(o => o.Logger.Warn(It.IsAny<string>(), It.IsAny<object[]>()), Times.Once);
Expression<Func<ResponseMessage, bool>> match = r => (int)r.StatusCode! == 404 && ((StatusModel)r.BodyData!.BodyAsJson!).Status == "No matching mapping found";
Expression<Func<ResponseMessage, bool>> match = r =>
(int)r.StatusCode! == 404 &&
((StatusModel)r.BodyData!.BodyAsJson!).Status == "No matching mapping found" &&
r.DateTime == UtcNow;
_responseMapperMock.Verify(m => m.MapAsync(It.Is(match), It.IsAny<HttpResponse>()), Times.Once);
}
@@ -1,8 +1,11 @@
// Copyright © WireMock.Net
using Moq;
using WireMock.Constants;
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.RequestBuilders;
namespace WireMock.Net.Tests.RequestMatchers;
@@ -10,8 +13,12 @@ public class RequestMessageCompositeMatcherTests
{
private class Helper : RequestMessageCompositeMatcher
{
public Helper(IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And) : base(requestMatchers, type)
public Helper(
IEnumerable<IRequestMatcher> requestMatchers,
CompositeMatcherType type = CompositeMatcherType.And,
RequestMatcherType? earlyMatcherType = null) : base(requestMatchers, type)
{
EarlyMatcherType = earlyMatcherType;
}
}
@@ -77,4 +84,74 @@ public class RequestMessageCompositeMatcherTests
requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Once);
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_EarlyMismatch()
{
// Assign
var requestMatcher1Mock = new Mock<IRequestMatcher>();
requestMatcher1Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(1.0d);
var requestMatcher2Mock = new Mock<IRequestMatcher>();
requestMatcher2Mock.Setup(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>())).Returns(0.8d);
var postMatcher = new RequestMessageMethodMatcher(HttpRequestMethod.POST);
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), HttpRequestMethod.GET, "127.0.0.1");
var matcher = new Helper(
[requestMatcher1Mock.Object, requestMatcher2Mock.Object, postMatcher],
earlyMatcherType: RequestMatcherType.Method);
// Act
var result = new RequestMatchResult();
double score = matcher.GetMatchingScore(requestMessage, result);
// Assert
score.Should().Be(0.0d);
// Verify
requestMatcher1Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Never);
requestMatcher2Mock.Verify(rm => rm.GetMatchingScore(It.IsAny<RequestMessage>(), It.IsAny<RequestMatchResult>()), Times.Never);
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_SeveralHeadersEarlyMismatch()
{
// Assign
var headers = new Dictionary<string, string[]>
{
{ "teST", new[] { "x" } },
{ "teST2", new[] { "z" } }
};
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", null, headers);
var request = Request.Create()
.WithEarlyMismatch(RequestMatcherType.Header)
.UsingAnyMethod()
.WithHeader("teST", "x")
.WithHeader("teST1", ["xx", "yy"])
.WithHeader("teST2", ["y", "z"], matchOperator: MatchOperator.And);
// Act
var score = request.GetMatchingScore(requestMessage, new RequestMatchResult());
// Assert
score.Should().Be(0.0d);
}
[Fact]
public void RequestMessageCompositeMatcher_GetMatchingScore_SeveralParamEarlyMismatchSuccess()
{
// Assign
var uriWithParams = new Uri("http://localhost?test1=1&test2=2");
var requestMessage = new RequestMessage(new UrlDetails(uriWithParams), "GET", "127.0.0.1");
var request = Request.Create()
.WithEarlyMismatch(RequestMatcherType.Param)
.UsingAnyMethod()
.WithParam("test1", "1")
.WithParam("test2", "2");
// Act
var score = request.GetMatchingScore(requestMessage, new RequestMatchResult());
// Assert
score.Should().Be(1.0d);
}
}
@@ -1,5 +1,6 @@
// Copyright © WireMock.Net
using WireMock.Matchers.Request;
using WireMock.Net.Tests.VerifyExtensions;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
@@ -101,6 +102,7 @@ public partial class MappingConverterTests
var guid = new Guid("8e7b9ab7-e18e-4502-8bc9-11e6679811cc");
var request = Request.Create()
.UsingGet()
.WithEarlyMismatch(RequestMatcherType.Method)
.WithPath("/test_path")
.WithParam("q", "42")
.WithClientIP("112.123.100.99")
@@ -1,5 +1,6 @@
builder
.Given(Request.Create()
.WithEarlyMismatch(WireMock.Matchers.Request.RequestMatcherType.Method)
.UsingMethod("GET")
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/test_path", false, WireMock.Matchers.MatchOperator.Or))
.WithParam("q", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "42"))
@@ -1,6 +1,7 @@
var builder = new MappingBuilder();
builder
.Given(Request.Create()
.WithEarlyMismatch(WireMock.Matchers.Request.RequestMatcherType.Method)
.UsingMethod("GET")
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/test_path", false, WireMock.Matchers.MatchOperator.Or))
.WithParam("q", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "42"))
@@ -1,5 +1,6 @@
server
.Given(Request.Create()
.WithEarlyMismatch(WireMock.Matchers.Request.RequestMatcherType.Method)
.UsingMethod("GET")
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/test_path", false, WireMock.Matchers.MatchOperator.Or))
.WithParam("q", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "42"))
@@ -1,6 +1,7 @@
var server = WireMockServer.Start();
server
.Given(Request.Create()
.WithEarlyMismatch(WireMock.Matchers.Request.RequestMatcherType.Method)
.UsingMethod("GET")
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/test_path", false, WireMock.Matchers.MatchOperator.Or))
.WithParam("q", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "42"))
@@ -19,7 +19,7 @@
id:ID!
firstName:String
lastName:String
fullName:String
fullName:String
}
}
}
@@ -0,0 +1,34 @@
{
Guid: Guid_1,
UpdatedAt: DateTime_1,
Title: ,
Description: ,
Priority: 42,
Request: {
Path: {
Matchers: [
{
Name: WildcardMatcher,
Pattern: 1.2.3.4,
IgnoreCase: false
}
]
},
Headers: [
{
Name: x1,
Matchers: [
{
Name: WildcardMatcher,
Pattern: y,
IgnoreCase: true
}
],
IgnoreCase: true
}
],
EarlyMatcherType: ClientIP
},
Response: {},
UseWebhooksFireAndForget: false
}
@@ -1,6 +1,7 @@
// Copyright © WireMock.Net
using WireMock.Matchers;
using WireMock.Matchers.Request;
using WireMock.Models;
using WireMock.RequestBuilders;
using WireMock.ResponseBuilders;
@@ -538,7 +539,7 @@ message HelloReply {
id:ID!
firstName:String
lastName:String
fullName:String
fullName:String
}";
var request = Request.Create().WithGraphQLSchema(schema);
var response = Response.Create();
@@ -640,4 +641,25 @@ message HelloReply {
// Verify
return Verify(model);
}
[Fact]
public Task ToMappingModel_Request_WithEarlyMismatch_ReturnsCorrectModel()
{
// Arrange
var request = Request.Create().WithEarlyMismatch(RequestMatcherType.ClientIP)
.WithHeader("x1", "y")
.WithClientIP("1.2.3.4");
var response = Response.Create();
var mapping = new Mapping(_guid, _updatedAt, string.Empty, string.Empty, null, _settings, request, response, 42, null, null, null, null, null, false, null, null);
// Act
var model = _sut.ToMappingModel(mapping);
// Assert
model.Should().NotBeNull();
model.Request.EarlyMatcherType.Should().Be(RequestMatcherType.ClientIP);
// Verify
return Verify(model);
}
}
-41
View File
@@ -1,41 +0,0 @@
// Copyright © WireMock.Net
namespace MultipartUploader
{
partial class Form1
{
/// <summary>
/// Required designer variable.
/// </summary>
private System.ComponentModel.IContainer components = null;
/// <summary>
/// Clean up any resources being used.
/// </summary>
/// <param name="disposing">true if managed resources should be disposed; otherwise, false.</param>
protected override void Dispose(bool disposing)
{
if (disposing && (components != null))
{
components.Dispose();
}
base.Dispose(disposing);
}
#region Windows Form Designer generated code
/// <summary>
/// Required method for Designer support - do not modify
/// the contents of this method with the code editor.
/// </summary>
private void InitializeComponent()
{
this.components = new System.ComponentModel.Container();
this.AutoScaleMode = System.Windows.Forms.AutoScaleMode.Font;
this.ClientSize = new System.Drawing.Size(800, 450);
this.Text = "Form1";
}
#endregion
}
}
-12
View File
@@ -1,12 +0,0 @@
// Copyright © WireMock.Net
namespace MultipartUploader
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
}
}
-120
View File
@@ -1,120 +0,0 @@
<?xml version="1.0" encoding="utf-8"?>
<root>
<!--
Microsoft ResX Schema
Version 2.0
The primary goals of this format is to allow a simple XML format
that is mostly human readable. The generation and parsing of the
various data types are done through the TypeConverter classes
associated with the data types.
Example:
... ado.net/XML headers & schema ...
<resheader name="resmimetype">text/microsoft-resx</resheader>
<resheader name="version">2.0</resheader>
<resheader name="reader">System.Resources.ResXResourceReader, System.Windows.Forms, ...</resheader>
<resheader name="writer">System.Resources.ResXResourceWriter, System.Windows.Forms, ...</resheader>
<data name="Name1"><value>this is my long string</value><comment>this is a comment</comment></data>
<data name="Color1" type="System.Drawing.Color, System.Drawing">Blue</data>
<data name="Bitmap1" mimetype="application/x-microsoft.net.object.binary.base64">
<value>[base64 mime encoded serialized .NET Framework object]</value>
</data>
<data name="Icon1" type="System.Drawing.Icon, System.Drawing" mimetype="application/x-microsoft.net.object.bytearray.base64">
<value>[base64 mime encoded string representing a byte array form of the .NET Framework object]</value>
<comment>This is a comment</comment>
</data>
There are any number of "resheader" rows that contain simple
name/value pairs.
Each data row contains a name, and value. The row also contains a
type or mimetype. Type corresponds to a .NET class that support
text/value conversion through the TypeConverter architecture.
Classes that don't support this are serialized and stored with the
mimetype set.
The mimetype is used for serialized objects, and tells the
ResXResourceReader how to depersist the object. This is currently not
extensible. For a given mimetype the value must be set accordingly:
Note - application/x-microsoft.net.object.binary.base64 is the format
that the ResXResourceWriter will generate, however the reader can
read any of the formats listed below.
mimetype: application/x-microsoft.net.object.binary.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Binary.BinaryFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.soap.base64
value : The object must be serialized with
: System.Runtime.Serialization.Formatters.Soap.SoapFormatter
: and then encoded with base64 encoding.
mimetype: application/x-microsoft.net.object.bytearray.base64
value : The object must be serialized into a byte array
: using a System.ComponentModel.TypeConverter
: and then encoded with base64 encoding.
-->
<xsd:schema id="root" xmlns="" xmlns:xsd="http://www.w3.org/2001/XMLSchema" xmlns:msdata="urn:schemas-microsoft-com:xml-msdata">
<xsd:import namespace="http://www.w3.org/XML/1998/namespace" />
<xsd:element name="root" msdata:IsDataSet="true">
<xsd:complexType>
<xsd:choice maxOccurs="unbounded">
<xsd:element name="metadata">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" />
</xsd:sequence>
<xsd:attribute name="name" use="required" type="xsd:string" />
<xsd:attribute name="type" type="xsd:string" />
<xsd:attribute name="mimetype" type="xsd:string" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="assembly">
<xsd:complexType>
<xsd:attribute name="alias" type="xsd:string" />
<xsd:attribute name="name" type="xsd:string" />
</xsd:complexType>
</xsd:element>
<xsd:element name="data">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
<xsd:element name="comment" type="xsd:string" minOccurs="0" msdata:Ordinal="2" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" msdata:Ordinal="1" />
<xsd:attribute name="type" type="xsd:string" msdata:Ordinal="3" />
<xsd:attribute name="mimetype" type="xsd:string" msdata:Ordinal="4" />
<xsd:attribute ref="xml:space" />
</xsd:complexType>
</xsd:element>
<xsd:element name="resheader">
<xsd:complexType>
<xsd:sequence>
<xsd:element name="value" type="xsd:string" minOccurs="0" msdata:Ordinal="1" />
</xsd:sequence>
<xsd:attribute name="name" type="xsd:string" use="required" />
</xsd:complexType>
</xsd:element>
</xsd:choice>
</xsd:complexType>
</xsd:element>
</xsd:schema>
<resheader name="resmimetype">
<value>text/microsoft-resx</value>
</resheader>
<resheader name="version">
<value>2.0</value>
</resheader>
<resheader name="reader">
<value>System.Resources.ResXResourceReader, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
<resheader name="writer">
<value>System.Resources.ResXResourceWriter, System.Windows.Forms, Version=4.0.0.0, Culture=neutral, PublicKeyToken=b77a5c561934e089</value>
</resheader>
</root>
@@ -1,15 +0,0 @@
<Project Sdk="Microsoft.NET.Sdk">
<PropertyGroup>
<OutputType>WinExe</OutputType>
<TargetFramework>net6.0-windows</TargetFramework>
<Nullable>enable</Nullable>
<UseWindowsForms>true</UseWindowsForms>
<ImplicitUsings>enable</ImplicitUsings>
</PropertyGroup>
<ItemGroup>
<PackageReference Include="MimeKitLite" Version="4.1.0.1" />
</ItemGroup>
</Project>
-17
View File
@@ -1,17 +0,0 @@
// Copyright © WireMock.Net
namespace MultipartUploader;
internal static class Program
{
/// <summary>
/// The main entry point for the application.
/// </summary>
[STAThread]
static void Main()
{
// To customize application configuration such as set high DPI settings or default font, see https://aka.ms/applicationconfiguration.
ApplicationConfiguration.Initialize();
Application.Run(new Form1());
}
}