mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-02-15 06:47:41 +01:00
Compare commits
58 Commits
ws2
...
version-2.
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
334675f39c | ||
|
|
385450a3a8 | ||
|
|
be9298a2e2 | ||
|
|
60eb3980f6 | ||
|
|
a5d2bf2496 | ||
|
|
989f3b760e | ||
|
|
d82a273801 | ||
|
|
78d8d6a3da | ||
|
|
aab167e79c | ||
|
|
71c500deee | ||
|
|
15393bb2b1 | ||
|
|
6980468356 | ||
|
|
6094fa4c8b | ||
|
|
80aa55b2df | ||
|
|
c24f2396ff | ||
|
|
b172f700e0 | ||
|
|
6cc18e796c | ||
|
|
99f42fb255 | ||
|
|
0a612b17df | ||
|
|
67f764e41e | ||
|
|
d46bae655b | ||
|
|
425fb05c14 | ||
|
|
8b27da95a8 | ||
|
|
df85649b67 | ||
|
|
dff55e175b | ||
|
|
88df9af9df | ||
|
|
93ee9454a2 | ||
|
|
ff26f95ded | ||
|
|
276f329eed | ||
|
|
3b3f3604f7 | ||
|
|
d311813851 | ||
|
|
c8e1c66bf2 | ||
|
|
76d6f92be2 | ||
|
|
3f349cca4c | ||
|
|
19b85c7856 | ||
|
|
da912be37e | ||
|
|
ca9fceab67 | ||
|
|
c662bb7ad5 | ||
|
|
7d6fd35716 | ||
|
|
1b0b42d538 | ||
|
|
5f7b50a5b8 | ||
|
|
2e37e822a8 | ||
|
|
1bc693512f | ||
|
|
398dfe3eff | ||
|
|
02228e5f8a | ||
|
|
27d1a4b494 | ||
|
|
3e170778c8 | ||
|
|
9fa1f4081e | ||
|
|
37e140b342 | ||
|
|
4fd3ee1dfd | ||
|
|
5b43a4f341 | ||
|
|
0960d7cebd | ||
|
|
b111b019bc | ||
|
|
bb561c94d0 | ||
|
|
5c221ff4fa | ||
|
|
3077e7bee1 | ||
|
|
ec54599827 | ||
|
|
034766a2d6 |
4
.github/copilot-instructions.md
vendored
Normal file
4
.github/copilot-instructions.md
vendored
Normal file
@@ -0,0 +1,4 @@
|
|||||||
|
# Copilot Instructions
|
||||||
|
|
||||||
|
## Project Guidelines
|
||||||
|
- All new byte[xx] calls should use using var data = ArrayPool<byte>.Shared.Lease(xx); instead of directly allocating byte arrays
|
||||||
33
.github/workflows/ci.yml
vendored
33
.github/workflows/ci.yml
vendored
@@ -19,17 +19,22 @@ jobs:
|
|||||||
steps:
|
steps:
|
||||||
- uses: actions/checkout@v4
|
- uses: actions/checkout@v4
|
||||||
|
|
||||||
|
- name: Setup .NET 8
|
||||||
|
uses: actions/setup-dotnet@v4
|
||||||
|
with:
|
||||||
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
|
# - name: 'WireMock.Net.TUnitTests'
|
||||||
|
# run: dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release
|
||||||
|
|
||||||
- name: 'WireMock.Net.Tests'
|
- name: 'WireMock.Net.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test --project './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
- name: 'WireMock.Net.Tests.UsingNuGet'
|
- name: 'WireMock.Net.Tests.UsingNuGet'
|
||||||
run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
|
run: dotnet test --project './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
|
|
||||||
|
|
||||||
- name: 'WireMock.Net.Middleware.Tests'
|
- name: 'WireMock.Net.Middleware.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test --project './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release
|
||||||
|
|
||||||
linux-build-and-run:
|
linux-build-and-run:
|
||||||
name: Run Tests on Linux
|
name: Run Tests on Linux
|
||||||
@@ -46,20 +51,20 @@ jobs:
|
|||||||
with:
|
with:
|
||||||
dotnet-version: '8.0.x'
|
dotnet-version: '8.0.x'
|
||||||
|
|
||||||
|
- name: 'WireMock.Net.TUnitTests'
|
||||||
|
run: dotnet test --project './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release
|
||||||
|
|
||||||
- name: 'WireMock.Net.Tests'
|
- name: 'WireMock.Net.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test --project './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||||
|
|
||||||
- name: 'WireMock.Net.Tests.UsingNuGet'
|
- name: 'WireMock.Net.Tests.UsingNuGet'
|
||||||
run: dotnet test './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj' -c Release
|
run: dotnet test --project './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
|
|
||||||
|
|
||||||
- name: 'WireMock.Net.Middleware.Tests'
|
- name: 'WireMock.Net.Middleware.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
run: dotnet test --project './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release
|
||||||
|
|
||||||
- name: Install .NET Aspire workload
|
- name: Install .NET Aspire workload
|
||||||
run: dotnet workload install aspire
|
run: dotnet workload install aspire
|
||||||
|
|
||||||
- name: 'WireMock.Net.Aspire.Tests'
|
- name: 'WireMock.Net.Aspire.Tests'
|
||||||
run: dotnet test './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release
|
run: dotnet test --project './test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj' -c Release
|
||||||
2
.gitignore
vendored
2
.gitignore
vendored
@@ -254,6 +254,6 @@ paket-files/
|
|||||||
./report/coverlet/
|
./report/coverlet/
|
||||||
/test/WireMock.Net.Tests/coverage.opencover.xml
|
/test/WireMock.Net.Tests/coverage.opencover.xml
|
||||||
/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
||||||
/test/WireMock.Net.Tests/coverage.net5.0.opencover.xml
|
/test/WireMock.Net.Tests/coverage.net8.0.opencover.xml
|
||||||
|
|
||||||
*.received.*
|
*.received.*
|
||||||
14
CHANGELOG.md
14
CHANGELOG.md
@@ -475,7 +475,7 @@
|
|||||||
# 1.5.30 (28 June 2023)
|
# 1.5.30 (28 June 2023)
|
||||||
- [#959](https://github.com/wiremock/WireMock.Net/pull/959) - Fixed logic for FluentAssertions WithHeader [bug] contributed by [StefH](https://github.com/StefH)
|
- [#959](https://github.com/wiremock/WireMock.Net/pull/959) - Fixed logic for FluentAssertions WithHeader [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#962](https://github.com/wiremock/WireMock.Net/pull/962) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.Console.Net472.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#962](https://github.com/wiremock/WireMock.Net/pull/962) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.Console.Net472.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#963](https://github.com/wiremock/WireMock.Net/pull/963) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#963](https://github.com/wiremock/WireMock.Net/pull/963) - Bump System.Linq.Dynamic.Core from 1.2.23 to 1.3.0 in /examples/WireMock.Net.StandAlone.net462 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#958](https://github.com/wiremock/WireMock.Net/issues/958) - [FluentAssertions] Should().HaveReceivedACall().WithHeader() only checks the first header with the matching key. [bug]
|
- [#958](https://github.com/wiremock/WireMock.Net/issues/958) - [FluentAssertions] Should().HaveReceivedACall().WithHeader() only checks the first header with the matching key. [bug]
|
||||||
|
|
||||||
# 1.5.29 (22 June 2023)
|
# 1.5.29 (22 June 2023)
|
||||||
@@ -587,7 +587,7 @@
|
|||||||
- [#828](https://github.com/wiremock/WireMock.Net/pull/828) - Add setting to skip saving the string-response in the logging when using WithBody(Func...) [feature] contributed by [StefH](https://github.com/StefH)
|
- [#828](https://github.com/wiremock/WireMock.Net/pull/828) - Add setting to skip saving the string-response in the logging when using WithBody(Func...) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#832](https://github.com/wiremock/WireMock.Net/pull/832) - Fixes for WireMock.Net.FluentAssertions (callcount behaviour) [feature] contributed by [StefH](https://github.com/StefH)
|
- [#832](https://github.com/wiremock/WireMock.Net/pull/832) - Fixes for WireMock.Net.FluentAssertions (callcount behaviour) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#834](https://github.com/wiremock/WireMock.Net/pull/834) - Support deleting / resetting a single scenario [feature] contributed by [StefH](https://github.com/StefH)
|
- [#834](https://github.com/wiremock/WireMock.Net/pull/834) - Support deleting / resetting a single scenario [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#837](https://github.com/wiremock/WireMock.Net/pull/837) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.7 to 2.1.25 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#837](https://github.com/wiremock/WireMock.Net/pull/837) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.7 to 2.1.25 in /examples/WireMock.Net.StandAlone.net462 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#838](https://github.com/wiremock/WireMock.Net/pull/838) - Add option to ProxySettings to append guid to mapping file contributed by [StefH](https://github.com/StefH)
|
- [#838](https://github.com/wiremock/WireMock.Net/pull/838) - Add option to ProxySettings to append guid to mapping file contributed by [StefH](https://github.com/StefH)
|
||||||
- [#826](https://github.com/wiremock/WireMock.Net/issues/826) - Dynamic Body not to be cached when a Func is used to created the body [feature]
|
- [#826](https://github.com/wiremock/WireMock.Net/issues/826) - Dynamic Body not to be cached when a Func is used to created the body [feature]
|
||||||
|
|
||||||
@@ -635,14 +635,14 @@
|
|||||||
- [#776](https://github.com/wiremock/WireMock.Net/issues/776) - Update Scriban.Signed to support more functions, e.g math.random [feature]
|
- [#776](https://github.com/wiremock/WireMock.Net/issues/776) - Update Scriban.Signed to support more functions, e.g math.random [feature]
|
||||||
|
|
||||||
# 1.5.2 (24 July 2022)
|
# 1.5.2 (24 July 2022)
|
||||||
- [#769](https://github.com/wiremock/WireMock.Net/pull/769) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.3 to 2.1.7 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#769](https://github.com/wiremock/WireMock.Net/pull/769) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.3 to 2.1.7 in /examples/WireMock.Net.StandAlone.net462 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#771](https://github.com/wiremock/WireMock.Net/pull/771) - JsonPartialMatcher - support Regex [feature] contributed by [StefH](https://github.com/StefH)
|
- [#771](https://github.com/wiremock/WireMock.Net/pull/771) - JsonPartialMatcher - support Regex [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
# 1.5.1 (08 July 2022)
|
# 1.5.1 (08 July 2022)
|
||||||
- [#762](https://github.com/wiremock/WireMock.Net/pull/762) - Bump Newtonsoft.Json from 11.0.2 to 13.0.1 in /examples/WireMock.Net.WebApplication.NETCore2 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#762](https://github.com/wiremock/WireMock.Net/pull/762) - Bump Newtonsoft.Json from 11.0.2 to 13.0.1 in /examples/WireMock.Net.WebApplication.NETCore2 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#763](https://github.com/wiremock/WireMock.Net/pull/763) - Bump Newtonsoft.Json from 6.0.1 to 13.0.1 in /examples/WireMock.Net.Client.Net472 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#763](https://github.com/wiremock/WireMock.Net/pull/763) - Bump Newtonsoft.Json from 6.0.1 to 13.0.1 in /examples/WireMock.Net.Client.Net472 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#765](https://github.com/wiremock/WireMock.Net/pull/765) - Update WireMock.Org.Abstractions and WireMock.Org.RestClient [feature] contributed by [StefH](https://github.com/StefH)
|
- [#765](https://github.com/wiremock/WireMock.Net/pull/765) - Update WireMock.Org.Abstractions and WireMock.Org.RestClient [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#766](https://github.com/wiremock/WireMock.Net/pull/766) - Bump Microsoft.AspNetCore.Http from 2.1.1 to 2.1.22 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#766](https://github.com/wiremock/WireMock.Net/pull/766) - Bump Microsoft.AspNetCore.Http from 2.1.1 to 2.1.22 in /examples/WireMock.Net.StandAlone.net462 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#767](https://github.com/wiremock/WireMock.Net/pull/767) - Rename (WireMock.Pact.Models.V2)-Request to PactRequest and -Response to PactResponse [feature] contributed by [StefH](https://github.com/StefH)
|
- [#767](https://github.com/wiremock/WireMock.Net/pull/767) - Rename (WireMock.Pact.Models.V2)-Request to PactRequest and -Response to PactResponse [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#764](https://github.com/wiremock/WireMock.Net/issues/764) - Wrong mapping of method GetAdminMappingsAsync from IWireMockOrgApi [bug]
|
- [#764](https://github.com/wiremock/WireMock.Net/issues/764) - Wrong mapping of method GetAdminMappingsAsync from IWireMockOrgApi [bug]
|
||||||
|
|
||||||
@@ -794,7 +794,7 @@
|
|||||||
- [#612](https://github.com/wiremock/WireMock.Net/pull/612) - Don't run SonarCloud tasks for PullRequests [feature] contributed by [StefH](https://github.com/StefH)
|
- [#612](https://github.com/wiremock/WireMock.Net/pull/612) - Don't run SonarCloud tasks for PullRequests [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
# 1.4.13 (26 April 2021)
|
# 1.4.13 (26 April 2021)
|
||||||
- [#607](https://github.com/wiremock/WireMock.Net/pull/607) - Bump System.Text.Encodings.Web from 4.5.0 to 4.5.1 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#607](https://github.com/wiremock/WireMock.Net/pull/607) - Bump System.Text.Encodings.Web from 4.5.0 to 4.5.1 in /examples/WireMock.Net.StandAlone.net462 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#609](https://github.com/wiremock/WireMock.Net/pull/609) - Add possibility to use settings to generate MappingModel models with wildcard path parameters. [feature] contributed by [StefH](https://github.com/StefH)
|
- [#609](https://github.com/wiremock/WireMock.Net/pull/609) - Add possibility to use settings to generate MappingModel models with wildcard path parameters. [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#608](https://github.com/wiremock/WireMock.Net/issues/608) - Import from OpenApi generates model with path parameter narrowed in range (example value=42 instead of '*') [feature]
|
- [#608](https://github.com/wiremock/WireMock.Net/issues/608) - Import from OpenApi generates model with path parameter narrowed in range (example value=42 instead of '*') [feature]
|
||||||
|
|
||||||
@@ -838,7 +838,7 @@
|
|||||||
- [#570](https://github.com/wiremock/WireMock.Net/pull/570) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.StandAlone.NETCoreApp [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#570](https://github.com/wiremock/WireMock.Net/pull/570) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.StandAlone.NETCoreApp [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#571](https://github.com/wiremock/WireMock.Net/pull/571) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.NETCoreApp2 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#571](https://github.com/wiremock/WireMock.Net/pull/571) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.NETCoreApp2 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#572](https://github.com/wiremock/WireMock.Net/pull/572) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.NETCoreApp [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#572](https://github.com/wiremock/WireMock.Net/pull/572) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.NETCoreApp [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#573](https://github.com/wiremock/WireMock.Net/pull/573) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.Net461.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#573](https://github.com/wiremock/WireMock.Net/pull/573) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.net462.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#574](https://github.com/wiremock/WireMock.Net/pull/574) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.Net452.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#574](https://github.com/wiremock/WireMock.Net/pull/574) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Console.Net452.Classic [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#575](https://github.com/wiremock/WireMock.Net/pull/575) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.StandAlone.Net452 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#575](https://github.com/wiremock/WireMock.Net/pull/575) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.StandAlone.Net452 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
- [#576](https://github.com/wiremock/WireMock.Net/pull/576) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Service [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
- [#576](https://github.com/wiremock/WireMock.Net/pull/576) - Bump log4net from 2.0.8 to 2.0.10 in /examples/WireMock.Net.Service [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
@@ -1434,7 +1434,7 @@
|
|||||||
- [#72](https://github.com/wiremock/WireMock.Net/issues/72) - Matching WithParam on OData End Points
|
- [#72](https://github.com/wiremock/WireMock.Net/issues/72) - Matching WithParam on OData End Points
|
||||||
|
|
||||||
# 1.0.2.10 (12 December 2017)
|
# 1.0.2.10 (12 December 2017)
|
||||||
- [#70](https://github.com/wiremock/WireMock.Net/issues/70) - Proxy/Intercept pattern is throwing a keep alive header error with net461
|
- [#70](https://github.com/wiremock/WireMock.Net/issues/70) - Proxy/Intercept pattern is throwing a keep alive header error with net462
|
||||||
|
|
||||||
# 1.0.2.9 (07 December 2017)
|
# 1.0.2.9 (07 December 2017)
|
||||||
- [#71](https://github.com/wiremock/WireMock.Net/pull/71) - Fixed restricted headers on response contributed by [StefH](https://github.com/StefH)
|
- [#71](https://github.com/wiremock/WireMock.Net/pull/71) - Fixed restricted headers on response contributed by [StefH](https://github.com/StefH)
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.25.0</VersionPrefix>
|
<VersionPrefix>2.0.0-preview-02</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/wiremock/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
@@ -13,8 +13,9 @@
|
|||||||
<RepositoryUrl>https://github.com/wiremock/WireMock.Net</RepositoryUrl>
|
<RepositoryUrl>https://github.com/wiremock/WireMock.Net</RepositoryUrl>
|
||||||
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
||||||
<PackageReadmeFile>PackageReadme.md</PackageReadmeFile>
|
<PackageReadmeFile>PackageReadme.md</PackageReadmeFile>
|
||||||
<LangVersion>12.0</LangVersion>
|
<LangVersion>latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
|
<ImplicitUsings>enable</ImplicitUsings>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
||||||
@@ -45,23 +46,20 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<NuGetAudit>true</NuGetAudit>
|
<NuGetAudit>true</NuGetAudit>
|
||||||
<!--<NuGetAuditLevel>low</NuGetAuditLevel>-->
|
<NuGetAuditLevel>low</NuGetAuditLevel>
|
||||||
<NuGetAuditMode>all</NuGetAuditMode>
|
<NuGetAuditMode>all</NuGetAuditMode>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- CVE-2019-0820 -->
|
<PackageReference Include="JetBrains.Annotations" Version="2025.2.4" PrivateAssets="All" />
|
||||||
<PackageReference Include="System.Text.RegularExpressions" Version="4.3.1" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="10.0.103" PrivateAssets="All" />
|
||||||
|
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2024.3.0" PrivateAssets="All" />
|
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="10.15.0.120848">
|
<!--<PackageReference Include="SonarAnalyzer.CSharp" Version="10.15.0.120848">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>-->
|
||||||
<!-- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
|
<!-- <PackageReference Include="StyleCop.Analyzers" Version="1.2.0-beta.556">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
|||||||
@@ -58,9 +58,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Actions", "Actions", "{1DAE
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure Pipelines", "Azure Pipelines", "{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E}"
|
Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Azure Pipelines", "Azure Pipelines", "{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E}"
|
||||||
ProjectSection(SolutionItems) = preProject
|
ProjectSection(SolutionItems) = preProject
|
||||||
azure-pipelines-ci-linux.yml = azure-pipelines-ci-linux.yml
|
|
||||||
azure-pipelines-ci.yml = azure-pipelines-ci.yml
|
azure-pipelines-ci.yml = azure-pipelines-ci.yml
|
||||||
azure-pipelines-linux.yml = azure-pipelines-linux.yml
|
|
||||||
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
|
azure-pipelines-nuget.yml = azure-pipelines-nuget.yml
|
||||||
EndProjectSection
|
EndProjectSection
|
||||||
EndProject
|
EndProject
|
||||||
@@ -68,14 +66,10 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.RestClient", "
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.Abstractions", "src\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj", "{3BA5109E-5F30-4CC2-B699-02EC82560AA6}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Org.Abstractions", "src\WireMock.Org.Abstractions\WireMock.Org.Abstractions.csproj", "{3BA5109E-5F30-4CC2-B699-02EC82560AA6}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NET6", "examples\WireMock.Net.WebApplication.NET6\WireMock.Net.WebApplication.NET6.csproj", "{3F7AA023-6833-4856-A08A-4B5717B592B8}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.NETCoreApp", "examples\WireMock.Net.Console.Proxy.NETCoreApp\WireMock.Net.Console.Proxy.NETCoreApp.csproj", "{670C7562-C154-442E-A249-7D26849BCD13}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.Proxy.NETCoreApp", "examples\WireMock.Net.Console.Proxy.NETCoreApp\WireMock.Net.Console.Proxy.NETCoreApp.csproj", "{670C7562-C154-442E-A249-7D26849BCD13}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.xUnit", "src\WireMock.Net.xUnit\WireMock.Net.xUnit.csproj", "{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET6.WithCertificate", "examples\WireMock.Net.Console.NET6.WithCertificate\WireMock.Net.Console.NET6.WithCertificate.csproj", "{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueExample", "examples\WireMockAzureQueueExample\WireMockAzureQueueExample.csproj", "{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMockAzureQueueExample", "examples\WireMockAzureQueueExample\WireMockAzureQueueExample.csproj", "{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Testcontainers", "src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj", "{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Testcontainers", "src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj", "{12B016A5-9D8B-4EFE-96C2-CA51BE43367D}"
|
||||||
@@ -118,8 +112,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.AspNetCore.Middleware", "src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A13}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.AspNetCore.Middleware", "src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A13}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TestWebApplication", "test\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj", "{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}"
|
|
||||||
EndProject
|
|
||||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Middleware.Tests", "test\WireMock.Net.Middleware.Tests\WireMock.Net.Middleware.Tests.csproj", "{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}"
|
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Middleware.Tests", "test\WireMock.Net.Middleware.Tests\WireMock.Net.Middleware.Tests.csproj", "{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}"
|
||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.AwesomeAssertions", "src\WireMock.Net.AwesomeAssertions\WireMock.Net.AwesomeAssertions.csproj", "{7753670F-7C7F-44BF-8BC7-08325588E60C}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.AwesomeAssertions", "src\WireMock.Net.AwesomeAssertions\WireMock.Net.AwesomeAssertions.csproj", "{7753670F-7C7F-44BF-8BC7-08325588E60C}"
|
||||||
@@ -154,6 +146,16 @@ Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.OpenTelemetryD
|
|||||||
EndProject
|
EndProject
|
||||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.MimePart", "examples\WireMock.Net.Console.MimePart\WireMock.Net.Console.MimePart.csproj", "{4005E20C-D42B-138A-79BE-B3F5420C563F}"
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.MimePart", "examples\WireMock.Net.Console.MimePart\WireMock.Net.Console.MimePart.csproj", "{4005E20C-D42B-138A-79BE-B3F5420C563F}"
|
||||||
EndProject
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.NET8.WithCertificate", "examples\WireMock.Net.Console.NET8.WithCertificate\WireMock.Net.Console.NET8.WithCertificate.csproj", "{2D86546D-8A24-0A55-C962-2071BD299E05}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.WebApplication.IIS", "examples\WireMock.Net.WebApplication.IIS\WireMock.Net.WebApplication.IIS.csproj", "{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.WebSocketExamples", "examples\WireMock.Net.WebSocketExamples\WireMock.Net.WebSocketExamples.csproj", "{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.TestWebApplication", "examples\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj", "{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}"
|
||||||
|
EndProject
|
||||||
|
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.TestWebApplication", "test\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj", "{3B05CC76-C3CB-8667-6B65-3129DFB25681}"
|
||||||
|
EndProject
|
||||||
Global
|
Global
|
||||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||||
Debug|Any CPU = Debug|Any CPU
|
Debug|Any CPU = Debug|Any CPU
|
||||||
@@ -332,18 +334,6 @@ Global
|
|||||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x64.Build.0 = Release|Any CPU
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.ActiveCfg = Release|Any CPU
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.Build.0 = Release|Any CPU
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{670C7562-C154-442E-A249-7D26849BCD13}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
@@ -368,18 +358,6 @@ Global
|
|||||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x64.Build.0 = Release|Any CPU
|
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.ActiveCfg = Release|Any CPU
|
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.Build.0 = Release|Any CPU
|
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
@@ -608,18 +586,6 @@ Global
|
|||||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x64.Build.0 = Release|Any CPU
|
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.ActiveCfg = Release|Any CPU
|
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.Build.0 = Release|Any CPU
|
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|x86.Build.0 = Release|Any CPU
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x64.ActiveCfg = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x64.Build.0 = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x86.ActiveCfg = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Debug|x86.Build.0 = Debug|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.Build.0 = Release|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x64.ActiveCfg = Release|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x64.Build.0 = Release|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x86.ActiveCfg = Release|Any CPU
|
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|x86.Build.0 = Release|Any CPU
|
|
||||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
@@ -824,6 +790,66 @@ Global
|
|||||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x64.Build.0 = Release|Any CPU
|
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x64.Build.0 = Release|Any CPU
|
||||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.ActiveCfg = Release|Any CPU
|
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.Build.0 = Release|Any CPU
|
{4005E20C-D42B-138A-79BE-B3F5420C563F}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652}.Release|x86.Build.0 = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|x64.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|x64.Build.0 = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|x86.ActiveCfg = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Debug|x86.Build.0 = Debug|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|x64.ActiveCfg = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|x64.Build.0 = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|x86.ActiveCfg = Release|Any CPU
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681}.Release|x86.Build.0 = Release|Any CPU
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(SolutionProperties) = preSolution
|
GlobalSection(SolutionProperties) = preSolution
|
||||||
HideSolutionNode = FALSE
|
HideSolutionNode = FALSE
|
||||||
@@ -845,10 +871,8 @@ Global
|
|||||||
{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
{5B64F6CA-BF6B-4F67-BB2A-9C47E441703E} = {7EFB2C5B-1BB2-4AAF-BC9F-216ED80C594D}
|
||||||
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{08B29DB1-FEFE-408A-AD0A-6BA6DDC8D70F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{3BA5109E-5F30-4CC2-B699-02EC82560AA6} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{3BA5109E-5F30-4CC2-B699-02EC82560AA6} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{3F7AA023-6833-4856-A08A-4B5717B592B8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
|
||||||
{670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{670C7562-C154-442E-A249-7D26849BCD13} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{0DE0954F-8C00-4E8D-B94A-4361FC1CBE44} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{7C2A9DE8-C89F-4841-9058-6B9BF81E5E34} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
|
||||||
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{BAA9EC2A-874B-45CE-8E51-A73622DC7F3D} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{12B016A5-9D8B-4EFE-96C2-CA51BE43367D} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{56A38798-C48B-4A4A-B805-071E05C02CE1} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{56A38798-C48B-4A4A-B805-071E05C02CE1} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
@@ -868,7 +892,6 @@ Global
|
|||||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE} = {0BB8B634-407A-4610-A91F-11586990767A}
|
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{B6269AAC-170A-4346-8B9A-579DED3D9A13} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE} = {0BB8B634-407A-4610-A91F-11586990767A}
|
|
||||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5} = {0BB8B634-407A-4610-A91F-11586990767A}
|
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||||
{7753670F-7C7F-44BF-8BC7-08325588E60C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{7753670F-7C7F-44BF-8BC7-08325588E60C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{E5B03EEF-822C-4295-952B-4479AD30082B} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{E5B03EEF-822C-4295-952B-4479AD30082B} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
@@ -886,6 +909,11 @@ Global
|
|||||||
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
{C8F4E6D2-9A3B-4F1C-8D5E-7A2B3C4D5E6F} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||||
{9957038D-F9C3-CA5D-E8AE-BE188E512635} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{9957038D-F9C3-CA5D-E8AE-BE188E512635} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
{4005E20C-D42B-138A-79BE-B3F5420C563F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
{4005E20C-D42B-138A-79BE-B3F5420C563F} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{2D86546D-8A24-0A55-C962-2071BD299E05} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{5E6E9FA7-9135-7B82-2CCD-8CA87AC8043C} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{2CE8E3A6-59CC-FE9C-9399-AD54E1FA862B} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{2EA75541-E63A-37B7-DA0A-BEA82ECD7652} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||||
|
{3B05CC76-C3CB-8667-6B65-3129DFB25681} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||||
EndGlobalSection
|
EndGlobalSection
|
||||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||||
|
|||||||
@@ -47,25 +47,25 @@ jobs:
|
|||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml"
|
dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-xunit.xml"
|
||||||
displayName: 'WireMock.Net.Tests with Coverage'
|
displayName: 'WireMock.Net.Tests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-tunit.xml"
|
dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-tunit.xml"
|
||||||
displayName: 'WireMock.Net.TUnitTests with Coverage'
|
displayName: 'WireMock.Net.TUnitTests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-middleware.xml"
|
dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-middleware.xml"
|
||||||
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
inputs:
|
inputs:
|
||||||
script: |
|
script: |
|
||||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml"
|
dotnet-coverage collect "dotnet test --project ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-aspire.xml"
|
||||||
displayName: 'WireMock.Net.Aspire.Tests with Coverage'
|
displayName: 'WireMock.Net.Aspire.Tests with Coverage'
|
||||||
|
|
||||||
- task: CmdLine@2
|
- task: CmdLine@2
|
||||||
@@ -95,7 +95,7 @@ jobs:
|
|||||||
- task: PublishBuildArtifacts@1
|
- task: PublishBuildArtifacts@1
|
||||||
displayName: Publish coverage files
|
displayName: Publish coverage files
|
||||||
inputs:
|
inputs:
|
||||||
PathtoPublish: './test/WireMock.Net.Tests/coverage.net8.0.opencover.xml'
|
PathtoPublish: './test/wiremock-coverage.xml'
|
||||||
|
|
||||||
- job: Windows_Build_Test
|
- job: Windows_Build_Test
|
||||||
|
|
||||||
@@ -109,33 +109,25 @@ jobs:
|
|||||||
packageType: 'sdk'
|
packageType: 'sdk'
|
||||||
version: '8.0.x'
|
version: '8.0.x'
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: CmdLine@2
|
||||||
displayName: 'WireMock.Net.Tests.UsingNuGet'
|
displayName: 'WireMock.Net.Tests.UsingNuGet'
|
||||||
inputs:
|
inputs:
|
||||||
command: 'test'
|
script: 'dotnet test ./test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj --configuration Release'
|
||||||
projects: './test/WireMock.Net.Tests.UsingNuGet/WireMock.Net.Tests.UsingNuGet.csproj'
|
|
||||||
arguments: '--configuration Release'
|
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: CmdLine@2
|
||||||
displayName: 'WireMock.Net.Tests with Coverage'
|
displayName: 'WireMock.Net.Tests with Coverage'
|
||||||
inputs:
|
inputs:
|
||||||
command: 'test'
|
script: 'dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
|
||||||
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
# - task: CmdLine@2
|
||||||
displayName: 'WireMock.Net.TUnitTests with Coverage'
|
# displayName: 'WireMock.Net.TUnitTests with Coverage'
|
||||||
inputs:
|
# inputs:
|
||||||
command: 'test'
|
# script: 'dotnet test --project ./test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj --configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
projects: './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj'
|
|
||||||
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
|
||||||
|
|
||||||
- task: DotNetCoreCLI@2
|
- task: CmdLine@2
|
||||||
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
displayName: 'WireMock.Net.Middleware.Tests with Coverage'
|
||||||
inputs:
|
inputs:
|
||||||
command: 'test'
|
script: 'dotnet test ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
||||||
projects: './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj'
|
|
||||||
arguments: '--configuration Debug --framework net8.0 --collect:"XPlat Code Coverage" --logger trx'
|
|
||||||
|
|
||||||
- job: Windows_Release_to_MyGet
|
- job: Windows_Release_to_MyGet
|
||||||
dependsOn: Windows_Build_Test
|
dependsOn: Windows_Build_Test
|
||||||
|
|||||||
@@ -376,9 +376,9 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
|
PreWireMockMiddlewareInit = app => { System.Console.WriteLine($"PreWireMockMiddlewareInit : {app.GetType()}"); },
|
||||||
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
|
PostWireMockMiddlewareInit = app => { System.Console.WriteLine($"PostWireMockMiddlewareInit : {app.GetType()}"); },
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
//#if USE_ASPNETCORE
|
||||||
AdditionalServiceRegistration = services => { System.Console.WriteLine($"AdditionalServiceRegistration : {services.GetType()}"); },
|
AdditionalServiceRegistration = services => { System.Console.WriteLine($"AdditionalServiceRegistration : {services.GetType()}"); },
|
||||||
#endif
|
//#endif
|
||||||
Logger = new WireMockConsoleLogger(),
|
Logger = new WireMockConsoleLogger(),
|
||||||
|
|
||||||
HandlebarsRegistrationCallback = (handlebarsContext, fileSystemHandler) =>
|
HandlebarsRegistrationCallback = (handlebarsContext, fileSystemHandler) =>
|
||||||
@@ -399,7 +399,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
//var response = await http.GetAsync($"{_wireMockServer.Url}/pricing");
|
//var response = await http.GetAsync($"{_wireMockServer.Url}/pricing");
|
||||||
//var value = await response.Content.ReadAsStringAsync();
|
//var value = await response.Content.ReadAsStringAsync();
|
||||||
|
|
||||||
#if PROTOBUF
|
//#if PROTOBUF
|
||||||
var protoBufJsonMatcher = new JsonPartialWildcardMatcher(new { name = "*" });
|
var protoBufJsonMatcher = new JsonPartialWildcardMatcher(new { name = "*" });
|
||||||
server
|
server
|
||||||
.Given(Request.Create()
|
.Given(Request.Create()
|
||||||
@@ -478,9 +478,9 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
.WithTrailingHeader("grpc-status", "0")
|
.WithTrailingHeader("grpc-status", "0")
|
||||||
.WithTransformer()
|
.WithTransformer()
|
||||||
);
|
);
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
#if GRAPHQL
|
//#if GRAPHQL
|
||||||
var customScalars = new Dictionary<string, Type> { { "MyCustomScalar", typeof(int) } };
|
var customScalars = new Dictionary<string, Type> { { "MyCustomScalar", typeof(int) } };
|
||||||
server
|
server
|
||||||
.Given(Request.Create()
|
.Given(Request.Create()
|
||||||
@@ -554,7 +554,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
}
|
}
|
||||||
""")
|
""")
|
||||||
);
|
);
|
||||||
#endif
|
//#endif
|
||||||
|
|
||||||
// 400 ms
|
// 400 ms
|
||||||
server
|
server
|
||||||
|
|||||||
@@ -1,34 +1,34 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net8.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF</DefineConstants>
|
<!--<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF</DefineConstants>-->
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Content Include="__admin\mappings\*.json">
|
<Content Include="__admin\mappings\*.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</Content>
|
</Content>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<Compile Remove="__admin\mappings\1.cs" />
|
<Compile Remove="__admin\mappings\1.cs" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
<PackageReference Include="log4net" Version="2.0.15" />
|
<PackageReference Include="log4net" Version="2.0.15" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="log4net.config">
|
<None Update="log4net.config">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="nlog.config">
|
<None Update="nlog.config">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
|
|||||||
@@ -7,16 +7,16 @@
|
|||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<!--<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>-->
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Update="SonarAnalyzer.CSharp" Version="10.12.0.118525" />
|
<PackageReference Update="SonarAnalyzer.CSharp" Version="10.12.0.118525" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="WireMock.Net" Version="1.8.11" />
|
<PackageReference Include="WireMock.Net" Version="1.12.0" />
|
||||||
</ItemGroup>-->
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -6,6 +6,8 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.OpenApi.YamlReader" Version="2.3.0" />
|
||||||
|
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net.OpenApiParser\WireMock.Net.OpenApiParser.csproj" />
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
|
|||||||
@@ -115,10 +115,10 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="log4net">
|
<PackageReference Include="log4net">
|
||||||
<Version>3.0.3</Version>
|
<Version>3.2.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
<PackageReference Include="WireMock.Net">
|
<PackageReference Include="WireMock.Net">
|
||||||
<Version>1.8.11</Version>
|
<Version>1.12.0</Version>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
<Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" />
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<!--<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>-->
|
<!--<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>-->
|
||||||
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
|
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
|
||||||
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
|
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
|
||||||
@@ -11,7 +11,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="8.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
678
examples/WireMock.Net.WebSocketExamples/Program.cs
Normal file
678
examples/WireMock.Net.WebSocketExamples/Program.cs
Normal file
@@ -0,0 +1,678 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System.Net.WebSockets;
|
||||||
|
using System.Text;
|
||||||
|
using WireMock.Logging;
|
||||||
|
using WireMock.RequestBuilders;
|
||||||
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.Server;
|
||||||
|
using WireMock.Settings;
|
||||||
|
|
||||||
|
namespace WireMock.Net.WebSocketExamples;
|
||||||
|
|
||||||
|
public static class Program
|
||||||
|
{
|
||||||
|
public static async Task Main(string[] args)
|
||||||
|
{
|
||||||
|
Console.WriteLine("WireMock.Net WebSocket Examples");
|
||||||
|
Console.WriteLine("================================\n");
|
||||||
|
|
||||||
|
Console.WriteLine("Choose an example to run:");
|
||||||
|
Console.WriteLine("1. Echo Server");
|
||||||
|
Console.WriteLine("2. Custom Message Handler");
|
||||||
|
Console.WriteLine("3. ...");
|
||||||
|
Console.WriteLine("4. Scenario/State Machine");
|
||||||
|
Console.WriteLine("5. WebSocket Proxy");
|
||||||
|
Console.WriteLine("6. Multiple WebSocket Endpoints");
|
||||||
|
Console.WriteLine("7. All Examples (runs all endpoints)");
|
||||||
|
Console.WriteLine("0. Exit\n");
|
||||||
|
|
||||||
|
Console.Write("Enter choice: ");
|
||||||
|
var choice = Console.ReadLine();
|
||||||
|
|
||||||
|
switch (choice)
|
||||||
|
{
|
||||||
|
case "1":
|
||||||
|
await RunEchoServerExample();
|
||||||
|
break;
|
||||||
|
case "2":
|
||||||
|
await RunCustomMessageHandlerExample();
|
||||||
|
break;
|
||||||
|
case "3":
|
||||||
|
await RunBroadcastExample();
|
||||||
|
break;
|
||||||
|
case "4":
|
||||||
|
await RunScenarioExample();
|
||||||
|
break;
|
||||||
|
case "5":
|
||||||
|
await RunProxyExample();
|
||||||
|
break;
|
||||||
|
case "6":
|
||||||
|
await RunMultipleEndpointsExample();
|
||||||
|
break;
|
||||||
|
case "7":
|
||||||
|
await RunAllExamples();
|
||||||
|
break;
|
||||||
|
case "0":
|
||||||
|
return;
|
||||||
|
default:
|
||||||
|
Console.WriteLine("Invalid choice");
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 1: Simple Echo Server
|
||||||
|
/// Echoes back all messages received from the client
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunEchoServerExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== Echo Server Example ===");
|
||||||
|
Console.WriteLine("Starting WebSocket echo server...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger()
|
||||||
|
});
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/echo")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithEcho()
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"Echo server listening at: {server.Urls[0]}/ws/echo");
|
||||||
|
Console.WriteLine("\nTest with a WebSocket client:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/echo");
|
||||||
|
Console.WriteLine("\nPress any key to test or CTRL+C to exit...");
|
||||||
|
Console.ReadKey();
|
||||||
|
|
||||||
|
// Test the echo server
|
||||||
|
await TestWebSocketEcho(server.Urls[0]);
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 2: Custom Message Handler
|
||||||
|
/// Processes messages and sends custom responses
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunCustomMessageHandlerExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== Custom Message Handler Example ===");
|
||||||
|
Console.WriteLine("Starting WebSocket server with custom message handler...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger()
|
||||||
|
});
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/chat")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (message, context) =>
|
||||||
|
{
|
||||||
|
if (message.MessageType == WebSocketMessageType.Text)
|
||||||
|
{
|
||||||
|
var text = message.Text ?? string.Empty;
|
||||||
|
|
||||||
|
// Handle different commands
|
||||||
|
if (text.StartsWith("/help"))
|
||||||
|
{
|
||||||
|
await context.SendAsync("Available commands: /help, /time, /echo <text>, /upper <text>, /reverse <text>");
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("/time"))
|
||||||
|
{
|
||||||
|
await context.SendAsync($"Server time: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC");
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("/echo "))
|
||||||
|
{
|
||||||
|
await context.SendAsync(text.Substring(6));
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("/upper "))
|
||||||
|
{
|
||||||
|
await context.SendAsync(text.Substring(7).ToUpper());
|
||||||
|
}
|
||||||
|
else if (text.StartsWith("/reverse "))
|
||||||
|
{
|
||||||
|
var toReverse = text.Substring(9);
|
||||||
|
var reversed = new string(toReverse.Reverse().ToArray());
|
||||||
|
await context.SendAsync(reversed);
|
||||||
|
}
|
||||||
|
else if (text == "/quit")
|
||||||
|
{
|
||||||
|
await context.SendAsync("Goodbye!");
|
||||||
|
await context.CloseAsync(WebSocketCloseStatus.NormalClosure, "Client requested disconnect");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await context.SendAsync($"Unknown command: {text}. Type /help for available commands.");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"Chat server listening at: {server.Urls[0]}/ws/chat");
|
||||||
|
Console.WriteLine("\nTest with:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/chat");
|
||||||
|
Console.WriteLine("\nThen try commands: /help, /time, /echo hello, /upper hello, /reverse hello");
|
||||||
|
Console.WriteLine("\nPress any key to test or CTRL+C to exit...");
|
||||||
|
Console.ReadKey();
|
||||||
|
|
||||||
|
await TestWebSocketChat(server.Urls[0]);
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 3: Broadcast Server
|
||||||
|
/// Broadcasts messages to all connected clients
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunBroadcastExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== Broadcast Server Example ===");
|
||||||
|
Console.WriteLine("Starting WebSocket broadcast server...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger()
|
||||||
|
});
|
||||||
|
|
||||||
|
var broadcastMappingGuid = Guid.NewGuid();
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/broadcast")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.WithGuid(broadcastMappingGuid)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithBroadcast()
|
||||||
|
.WithMessageHandler(async (message, context) =>
|
||||||
|
{
|
||||||
|
if (message.MessageType == WebSocketMessageType.Text)
|
||||||
|
{
|
||||||
|
var text = message.Text ?? string.Empty;
|
||||||
|
var timestamp = DateTime.UtcNow.ToString("HH:mm:ss");
|
||||||
|
var broadcastMessage = $"[{timestamp}] Broadcast: {text}";
|
||||||
|
|
||||||
|
// Broadcast to all connected clients
|
||||||
|
await context.BroadcastTextAsync(broadcastMessage);
|
||||||
|
|
||||||
|
Console.WriteLine($"Broadcasted to {server.GetWebSocketConnections(broadcastMappingGuid).Count} clients: {text}");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"Broadcast server listening at: {server.Urls[0]}/ws/broadcast");
|
||||||
|
Console.WriteLine("\nConnect multiple clients:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/broadcast");
|
||||||
|
Console.WriteLine("\nMessages sent from any client will be broadcast to all clients");
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 4: Scenario/State Machine
|
||||||
|
/// Demonstrates state transitions during WebSocket session
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunScenarioExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== Scenario/State Machine Example ===");
|
||||||
|
Console.WriteLine("Starting WebSocket server with scenario support...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger()
|
||||||
|
});
|
||||||
|
|
||||||
|
// Initial state: Waiting for players
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/game")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.InScenario("GameSession")
|
||||||
|
.WillSetStateTo("Lobby")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("Welcome to the game lobby! Type 'ready' to start or 'quit' to leave.");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Lobby state: Waiting for ready
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/game")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.InScenario("GameSession")
|
||||||
|
.WhenStateIs("Lobby")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
var text = msg.Text?.ToLower() ?? string.Empty;
|
||||||
|
|
||||||
|
if (text == "ready")
|
||||||
|
{
|
||||||
|
ctx.SetScenarioState("Playing");
|
||||||
|
await ctx.SendAsync("Game started! Type 'attack' to attack, 'defend' to defend, or 'quit' to exit.");
|
||||||
|
}
|
||||||
|
else if (text == "quit")
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("You left the lobby. Goodbye!");
|
||||||
|
await ctx.CloseAsync(WebSocketCloseStatus.NormalClosure, "Player quit");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("In lobby. Type 'ready' to start or 'quit' to leave.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Playing state: Game is active
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/game")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.InScenario("GameSession")
|
||||||
|
.WhenStateIs("Playing")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
var text = msg.Text?.ToLower() ?? string.Empty;
|
||||||
|
|
||||||
|
if (text == "attack")
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("You attacked! Critical hit! 💥");
|
||||||
|
}
|
||||||
|
else if (text == "defend")
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("You defended! Shield up! 🛡️");
|
||||||
|
}
|
||||||
|
else if (text == "quit")
|
||||||
|
{
|
||||||
|
ctx.SetScenarioState("GameOver");
|
||||||
|
await ctx.SendAsync("Game over! Thanks for playing.");
|
||||||
|
await ctx.CloseAsync(WebSocketCloseStatus.NormalClosure, "Game ended");
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("Unknown action. Type 'attack', 'defend', or 'quit'.");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"Game server listening at: {server.Urls[0]}/ws/game");
|
||||||
|
Console.WriteLine("\nConnect and follow the game flow:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/game");
|
||||||
|
Console.WriteLine("\nGame flow: Lobby -> Type 'ready' -> Playing -> Type 'attack'/'defend' -> Type 'quit'");
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 5: WebSocket Proxy
|
||||||
|
/// Proxies WebSocket connections to another server
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunProxyExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== WebSocket Proxy Example ===");
|
||||||
|
Console.WriteLine("Starting WebSocket proxy server...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger()
|
||||||
|
});
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/proxy")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocketProxy("ws://echo.websocket.org")
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine($"Proxy server listening at: {server.Urls[0]}/ws/proxy");
|
||||||
|
Console.WriteLine("Proxying to: ws://echo.websocket.org");
|
||||||
|
Console.WriteLine("\nTest with:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/proxy");
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 6: Multiple WebSocket Endpoints
|
||||||
|
/// Demonstrates running multiple WebSocket endpoints simultaneously
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunMultipleEndpointsExample()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== Multiple WebSocket Endpoints Example ===");
|
||||||
|
Console.WriteLine("Starting server with multiple WebSocket endpoints...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger(),
|
||||||
|
WebSocketSettings = new WebSocketSettings
|
||||||
|
{
|
||||||
|
MaxConnections = 100,
|
||||||
|
KeepAliveIntervalSeconds = 30
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
// Endpoint 1: Echo
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/echo")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws.WithEcho())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Endpoint 2: Time service
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/time")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
await ctx.SendAsync($"Server time: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Endpoint 4: Protocol-specific
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/protocol")
|
||||||
|
.WithWebSocketUpgrade("chat", "superchat")
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithAcceptProtocol("chat")
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
await ctx.SendAsync($"Using protocol: chat. Message: {msg.Text}");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
Console.WriteLine("Available WebSocket endpoints:");
|
||||||
|
Console.WriteLine($" 1. Echo: {server.Urls[0]}/ws/echo");
|
||||||
|
Console.WriteLine($" 2. Time: {server.Urls[0]}/ws/time");
|
||||||
|
Console.WriteLine($" 3. JSON: {server.Urls[0]}/ws/json");
|
||||||
|
Console.WriteLine($" 4. Protocol: {server.Urls[0]}/ws/protocol");
|
||||||
|
Console.WriteLine("\nTest with wscat:");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/echo");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/time");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/json");
|
||||||
|
Console.WriteLine(" wscat -c ws://localhost:9091/ws/protocol -s chat");
|
||||||
|
Console.WriteLine("\nPress any key to stop server...");
|
||||||
|
Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Example 7: Run All Examples
|
||||||
|
/// Starts a server with all example endpoints
|
||||||
|
/// </summary>
|
||||||
|
private static async Task RunAllExamples()
|
||||||
|
{
|
||||||
|
Console.WriteLine("\n=== All Examples Running ===");
|
||||||
|
Console.WriteLine("Starting server with all WebSocket endpoints...\n");
|
||||||
|
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
Logger = new WireMockConsoleLogger(),
|
||||||
|
WebSocketSettings = new WebSocketSettings
|
||||||
|
{
|
||||||
|
MaxConnections = 200
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
SetupAllEndpoints(server);
|
||||||
|
|
||||||
|
Console.WriteLine("All WebSocket endpoints are running:");
|
||||||
|
Console.WriteLine($" Echo: {server.Urls[0]}/ws/echo");
|
||||||
|
Console.WriteLine($" Chat: {server.Urls[0]}/ws/chat");
|
||||||
|
Console.WriteLine($" Broadcast: {server.Urls[0]}/ws/broadcast");
|
||||||
|
Console.WriteLine($" Game: {server.Urls[0]}/ws/game");
|
||||||
|
Console.WriteLine($" Time: {server.Urls[0]}/ws/time");
|
||||||
|
Console.WriteLine($" JSON: {server.Urls[0]}/ws/json");
|
||||||
|
Console.WriteLine("\nServer statistics:");
|
||||||
|
Console.WriteLine($" Total mappings: {server.Mappings.Count}");
|
||||||
|
|
||||||
|
Console.WriteLine("\nPress any key to view connection stats or CTRL+C to exit...");
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.ReadKey(true);
|
||||||
|
var connections = server.GetWebSocketConnections();
|
||||||
|
Console.WriteLine($"\nActive WebSocket connections: {connections.Count}");
|
||||||
|
foreach (var conn in connections)
|
||||||
|
{
|
||||||
|
Console.WriteLine($" - {conn.ConnectionId}: {conn.RequestMessage.Path} (State: {conn.WebSocket.State})");
|
||||||
|
}
|
||||||
|
Console.WriteLine("\nPress any key to refresh or CTRL+C to exit...");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupAllEndpoints(WireMockServer server)
|
||||||
|
{
|
||||||
|
// Echo endpoint
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/echo")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws.WithEcho())
|
||||||
|
);
|
||||||
|
|
||||||
|
// Chat endpoint
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/chat")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (message, context) =>
|
||||||
|
{
|
||||||
|
if (message.MessageType == WebSocketMessageType.Text)
|
||||||
|
{
|
||||||
|
await context.SendAsync($"Echo: {message.Text}");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Broadcast endpoint
|
||||||
|
var broadcastGuid = Guid.NewGuid();
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/broadcast")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.WithGuid(broadcastGuid)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithBroadcast()
|
||||||
|
.WithMessageHandler(async (message, context) =>
|
||||||
|
{
|
||||||
|
if (message.MessageType == WebSocketMessageType.Text)
|
||||||
|
{
|
||||||
|
await context.BroadcastTextAsync($"[Broadcast] {message.Text}");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// Game scenario endpoint
|
||||||
|
SetupGameScenario(server);
|
||||||
|
|
||||||
|
// Time endpoint
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/time")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
await ctx.SendAsync($"Server time: {DateTime.UtcNow:yyyy-MM-dd HH:mm:ss} UTC");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetupGameScenario(WireMockServer server)
|
||||||
|
{
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/game")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.InScenario("GameSession")
|
||||||
|
.WillSetStateTo("Lobby")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
await ctx.SendAsync("Welcome! Type 'ready' to start.");
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/ws/game")
|
||||||
|
.WithWebSocketUpgrade()
|
||||||
|
)
|
||||||
|
.InScenario("GameSession")
|
||||||
|
.WhenStateIs("Lobby")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithWebSocket(ws => ws
|
||||||
|
.WithMessageHandler(async (msg, ctx) =>
|
||||||
|
{
|
||||||
|
if (msg.Text?.ToLower() == "ready")
|
||||||
|
{
|
||||||
|
ctx.SetScenarioState("Playing");
|
||||||
|
await ctx.SendAsync("Game started!");
|
||||||
|
}
|
||||||
|
})
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods for testing
|
||||||
|
private static async Task TestWebSocketEcho(string baseUrl)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var client = new ClientWebSocket();
|
||||||
|
var uri = new Uri($"{baseUrl.Replace("http://", "ws://")}/ws/echo");
|
||||||
|
|
||||||
|
Console.WriteLine($"\nConnecting to {uri}...");
|
||||||
|
await client.ConnectAsync(uri, CancellationToken.None);
|
||||||
|
Console.WriteLine("Connected!");
|
||||||
|
|
||||||
|
var testMessages = new[] { "Hello", "World", "WebSocket", "Test" };
|
||||||
|
|
||||||
|
foreach (var testMessage in testMessages)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\nSending: {testMessage}");
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(testMessage);
|
||||||
|
await client.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||||
|
|
||||||
|
var buffer = new byte[1024];
|
||||||
|
var result = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||||
|
var received = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
||||||
|
Console.WriteLine($"Received: {received}");
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", CancellationToken.None);
|
||||||
|
Console.WriteLine("\nTest completed successfully!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\nTest failed: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task TestWebSocketChat(string baseUrl)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
using var client = new ClientWebSocket();
|
||||||
|
var uri = new Uri($"{baseUrl.Replace("http://", "ws://")}/ws/chat");
|
||||||
|
|
||||||
|
Console.WriteLine($"\nConnecting to {uri}...");
|
||||||
|
await client.ConnectAsync(uri, CancellationToken.None);
|
||||||
|
Console.WriteLine("Connected!");
|
||||||
|
|
||||||
|
var commands = new[] { "/help", "/time", "/echo Hello", "/upper test", "/reverse hello" };
|
||||||
|
|
||||||
|
foreach (var command in commands)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\nSending: {command}");
|
||||||
|
var bytes = Encoding.UTF8.GetBytes(command);
|
||||||
|
await client.SendAsync(new ArraySegment<byte>(bytes), WebSocketMessageType.Text, true, CancellationToken.None);
|
||||||
|
|
||||||
|
var buffer = new byte[1024];
|
||||||
|
var result = await client.ReceiveAsync(new ArraySegment<byte>(buffer), CancellationToken.None);
|
||||||
|
var received = Encoding.UTF8.GetString(buffer, 0, result.Count);
|
||||||
|
Console.WriteLine($"Received: {received}");
|
||||||
|
|
||||||
|
await Task.Delay(500);
|
||||||
|
}
|
||||||
|
|
||||||
|
await client.CloseAsync(WebSocketCloseStatus.NormalClosure, "Test complete", CancellationToken.None);
|
||||||
|
Console.WriteLine("\nTest completed successfully!");
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"\nTest failed: {ex.Message}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
156
examples/WireMock.Net.WebSocketExamples/README.md
Normal file
156
examples/WireMock.Net.WebSocketExamples/README.md
Normal file
@@ -0,0 +1,156 @@
|
|||||||
|
# WireMock.Net WebSocket Examples
|
||||||
|
|
||||||
|
This project demonstrates all the WebSocket capabilities of WireMock.Net.
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
- .NET 8.0 SDK
|
||||||
|
- Optional: `wscat` for manual testing (`npm install -g wscat`)
|
||||||
|
|
||||||
|
## Running the Examples
|
||||||
|
|
||||||
|
```bash
|
||||||
|
cd examples/WireMock.Net.WebSocketExamples
|
||||||
|
dotnet run
|
||||||
|
```
|
||||||
|
|
||||||
|
## Available Examples
|
||||||
|
|
||||||
|
### 1. Echo Server
|
||||||
|
Simple WebSocket echo server that returns all messages back to the client.
|
||||||
|
|
||||||
|
**Test with:**
|
||||||
|
```bash
|
||||||
|
wscat -c ws://localhost:9091/ws/echo
|
||||||
|
```
|
||||||
|
|
||||||
|
### 2. Custom Message Handler
|
||||||
|
Chat server with commands: `/help`, `/time`, `/echo`, `/upper`, `/reverse`, `/quit`
|
||||||
|
|
||||||
|
**Test with:**
|
||||||
|
```bash
|
||||||
|
wscat -c ws://localhost:9091/ws/chat
|
||||||
|
> /help
|
||||||
|
> /time
|
||||||
|
> /echo Hello World
|
||||||
|
> /upper test
|
||||||
|
> /reverse hello
|
||||||
|
```
|
||||||
|
|
||||||
|
### 3. Broadcast Server
|
||||||
|
Messages sent by any client are broadcast to all connected clients.
|
||||||
|
|
||||||
|
**Test with multiple terminals:**
|
||||||
|
```bash
|
||||||
|
# Terminal 1
|
||||||
|
wscat -c ws://localhost:9091/ws/broadcast
|
||||||
|
|
||||||
|
# Terminal 2
|
||||||
|
wscat -c ws://localhost:9091/ws/broadcast
|
||||||
|
|
||||||
|
# Terminal 3
|
||||||
|
wscat -c ws://localhost:9091/ws/broadcast
|
||||||
|
```
|
||||||
|
|
||||||
|
Type messages in any terminal and see them appear in all terminals.
|
||||||
|
|
||||||
|
### 4. Scenario/State Machine
|
||||||
|
Game server with state transitions: Lobby -> Playing -> GameOver
|
||||||
|
|
||||||
|
**Test with:**
|
||||||
|
```bash
|
||||||
|
wscat -c ws://localhost:9091/ws/game
|
||||||
|
> ready
|
||||||
|
> attack
|
||||||
|
> defend
|
||||||
|
> quit
|
||||||
|
```
|
||||||
|
|
||||||
|
### 5. WebSocket Proxy
|
||||||
|
Proxies WebSocket connections to echo.websocket.org
|
||||||
|
|
||||||
|
**Test with:**
|
||||||
|
```bash
|
||||||
|
wscat -c ws://localhost:9091/ws/proxy
|
||||||
|
```
|
||||||
|
|
||||||
|
### 6. Multiple Endpoints
|
||||||
|
Runs multiple WebSocket endpoints simultaneously:
|
||||||
|
- `/ws/echo` - Echo server
|
||||||
|
- `/ws/time` - Returns server time
|
||||||
|
- `/ws/json` - Returns JSON responses
|
||||||
|
- `/ws/protocol` - Protocol-specific endpoint
|
||||||
|
|
||||||
|
### 7. All Examples
|
||||||
|
Runs all endpoints at once with connection statistics.
|
||||||
|
|
||||||
|
## Features Demonstrated
|
||||||
|
|
||||||
|
- ✅ **Echo Server** - Simple message echo
|
||||||
|
- ✅ **Custom Handlers** - Complex message processing
|
||||||
|
- ✅ **Broadcast** - Multi-client communication
|
||||||
|
- ✅ **Scenarios** - State machine patterns
|
||||||
|
- ✅ **Proxy** - Forwarding to real WebSocket servers
|
||||||
|
- ✅ **Protocol Negotiation** - Sec-WebSocket-Protocol support
|
||||||
|
- ✅ **JSON Messaging** - Structured data exchange
|
||||||
|
- ✅ **Connection Management** - Track and manage connections
|
||||||
|
- ✅ **Configuration** - Custom WebSocket settings
|
||||||
|
|
||||||
|
## Testing with wscat
|
||||||
|
|
||||||
|
Install wscat globally:
|
||||||
|
```bash
|
||||||
|
npm install -g wscat
|
||||||
|
```
|
||||||
|
|
||||||
|
Basic usage:
|
||||||
|
```bash
|
||||||
|
# Connect to endpoint
|
||||||
|
wscat -c ws://localhost:9091/ws/echo
|
||||||
|
|
||||||
|
# Connect with protocol
|
||||||
|
wscat -c ws://localhost:9091/ws/protocol -s chat
|
||||||
|
|
||||||
|
# Connect with headers
|
||||||
|
wscat -c ws://localhost:9091/ws/echo -H "X-Custom-Header: value"
|
||||||
|
```
|
||||||
|
|
||||||
|
## Testing with C# Client
|
||||||
|
|
||||||
|
The examples include built-in C# WebSocket clients for automated testing.
|
||||||
|
Select options 1 or 2 and press any key to run the automated tests.
|
||||||
|
|
||||||
|
## Configuration
|
||||||
|
|
||||||
|
WebSocket settings can be configured:
|
||||||
|
|
||||||
|
```csharp
|
||||||
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
|
{
|
||||||
|
Port = 9091,
|
||||||
|
WebSocketSettings = new WebSocketSettings
|
||||||
|
{
|
||||||
|
MaxConnections = 100,
|
||||||
|
ReceiveBufferSize = 8192,
|
||||||
|
MaxMessageSize = 1048576,
|
||||||
|
KeepAliveInterval = TimeSpan.FromSeconds(30),
|
||||||
|
CloseTimeout = TimeSpan.FromMinutes(10),
|
||||||
|
EnableCompression = true
|
||||||
|
}
|
||||||
|
});
|
||||||
|
```
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
When running "All Examples" (option 7), press any key to view:
|
||||||
|
- Active connection count
|
||||||
|
- Connection IDs
|
||||||
|
- Request paths
|
||||||
|
- WebSocket states
|
||||||
|
|
||||||
|
## Notes
|
||||||
|
|
||||||
|
- All examples run on port 9091 by default
|
||||||
|
- Press CTRL+C to stop the server
|
||||||
|
- Multiple clients can connect simultaneously
|
||||||
|
- Connection states are tracked and can be queried
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
|
<PropertyGroup>
|
||||||
|
<OutputType>Exe</OutputType>
|
||||||
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
|
<AssemblyName>WireMock.Net.WebSocketExamples</AssemblyName>
|
||||||
|
<RootNamespace>WireMock.Net.WebSocketExamples</RootNamespace>
|
||||||
|
</PropertyGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup>
|
||||||
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="8.0.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
</Project>
|
||||||
@@ -1,25 +1,25 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
<AzureFunctionsVersion>v4</AzureFunctionsVersion>
|
||||||
<UserSecretsId>bb7d8355-68c4-4f81-8c2d-6cdd80cd7602</UserSecretsId>
|
<UserSecretsId>bb7d8355-68c4-4f81-8c2d-6cdd80cd7602</UserSecretsId>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
<PackageReference Include="Azure.Storage.Blobs" Version="12.14.1" />
|
||||||
<PackageReference Include="Azure.Storage.Files.Shares" Version="12.12.1" />
|
<PackageReference Include="Azure.Storage.Files.Shares" Version="12.12.1" />
|
||||||
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
|
<PackageReference Include="Azure.Storage.Queues" Version="12.12.0" />
|
||||||
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.5" />
|
<PackageReference Include="Microsoft.Azure.WebJobs.Extensions.Storage" Version="4.0.5" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Azure" Version="1.0.0" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="6.0.1" />
|
||||||
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
|
<PackageReference Include="Microsoft.NET.Sdk.Functions" Version="4.1.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Update="host.json">
|
<None Update="host.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
</None>
|
</None>
|
||||||
<None Update="local.settings.json">
|
<None Update="local.settings.json">
|
||||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||||
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
<CopyToPublishDirectory>Never</CopyToPublishDirectory>
|
||||||
</None>
|
</None>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
5
global.json
Normal file
5
global.json
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
{
|
||||||
|
"test": {
|
||||||
|
"runner": "Microsoft.Testing.Platform"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -32,7 +32,7 @@ public class ResponseModel
|
|||||||
public object? BodyAsJson { get; set; }
|
public object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
/// Gets or sets a value indicating whether the Json Body String needs to be indented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? BodyAsJsonIndented { get; set; }
|
public bool? BodyAsJsonIndented { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Text.RegularExpressions;
|
using System.Text.RegularExpressions;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
@@ -123,7 +122,6 @@ public class SettingsModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Dictionary<string, string[]>? ProtoDefinitions { get; set; }
|
public Dictionary<string, string[]>? ProtoDefinitions { get; set; }
|
||||||
|
|
||||||
#if NETSTANDARD1_3_OR_GREATER || NET461
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Server client certificate mode
|
/// Server client certificate mode
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -133,5 +131,9 @@ public class SettingsModel
|
|||||||
/// Whether to accept any client certificate
|
/// Whether to accept any client certificate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AcceptAnyClientCertificate { get; set; }
|
public bool AcceptAnyClientCertificate { get; set; }
|
||||||
#endif
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets or sets the WebSocket settings.
|
||||||
|
/// </summary>
|
||||||
|
public WebSocketSettingsModel? WebSocketSettings { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
namespace WireMock.Admin.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket Settings Model
|
||||||
|
/// </summary>
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class WebSocketSettingsModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum number of concurrent WebSocket connections (default: 100)
|
||||||
|
/// </summary>
|
||||||
|
public int MaxConnections { get; set; } = 100;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default receive buffer size in bytes (default: 4096)
|
||||||
|
/// </summary>
|
||||||
|
public int ReceiveBufferSize { get; set; } = 4096;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default keep-alive interval in seconds (default: 30)
|
||||||
|
/// </summary>
|
||||||
|
public int KeepAliveIntervalSeconds { get; set; } = 30;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Maximum message size in bytes (default: 1048576 - 1 MB)
|
||||||
|
/// </summary>
|
||||||
|
public int MaxMessageSize { get; set; } = 1048576;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enable WebSocket compression (default: true)
|
||||||
|
/// </summary>
|
||||||
|
public bool EnableCompression { get; set; } = true;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default close timeout in minutes (default: 10)
|
||||||
|
/// </summary>
|
||||||
|
public int CloseTimeoutMinutes { get; set; } = 10;
|
||||||
|
}
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
namespace WireMock.Constants;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket constants
|
||||||
|
/// </summary>
|
||||||
|
public static class WebSocketConstants
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Default receive buffer size for WebSocket messages (4 KB)
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultReceiveBufferSize = 4096;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default keep-alive interval in seconds
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultKeepAliveIntervalSeconds = 30;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default close timeout in minutes
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultCloseTimeoutMinutes = 10;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Minimum buffer size for WebSocket operations (1 KB)
|
||||||
|
/// </summary>
|
||||||
|
public const int MinimumBufferSize = 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default maximum message size (1 MB)
|
||||||
|
/// </summary>
|
||||||
|
public const int DefaultMaxMessageSize = 1024 * 1024;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Proxy forward buffer size (4 KB)
|
||||||
|
/// </summary>
|
||||||
|
public const int ProxyForwardBufferSize = 4096;
|
||||||
|
}
|
||||||
@@ -2,9 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
#if NETSTANDARD1_3_OR_GREATER || NET461
|
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using System.Security.Cryptography.X509Certificates;
|
||||||
#endif
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -118,13 +116,11 @@ public interface IRequestMessage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
byte[]? BodyAsBytes { get; }
|
byte[]? BodyAsBytes { get; }
|
||||||
|
|
||||||
#if MIMEKIT
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The original body as MimeMessage.
|
/// The original body as MimeMessage.
|
||||||
/// Convenience getter for Handlebars and WireMockAssertions.
|
/// Convenience getter for Handlebars and WireMockAssertions.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Models.Mime.IMimeMessageData? BodyAsMimeMessage { get; }
|
Models.Mime.IMimeMessageData? BodyAsMimeMessage { get; }
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The detected body type. Convenience getter for Handlebars.
|
/// The detected body type. Convenience getter for Handlebars.
|
||||||
@@ -169,10 +165,8 @@ public interface IRequestMessage
|
|||||||
/// <returns>The query parameter value as WireMockList or null when not found.</returns>
|
/// <returns>The query parameter value as WireMockList or null when not found.</returns>
|
||||||
WireMockList<string>? GetParameter(string key, bool ignoreCase = false);
|
WireMockList<string>? GetParameter(string key, bool ignoreCase = false);
|
||||||
|
|
||||||
#if NETSTANDARD1_3_OR_GREATER || NET461
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the connection's client certificate
|
/// Gets the connection's client certificate
|
||||||
/// </summary>
|
/// </summary>
|
||||||
X509Certificate2? ClientCertificate { get; }
|
X509Certificate2? ClientCertificate { get; }
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
@@ -37,7 +37,7 @@ public interface IBodyData
|
|||||||
object? BodyAsJson { get; set; }
|
object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
/// Gets or sets a value indicating whether the Json Body String needs to be indented.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool? BodyAsJsonIndented { get; set; }
|
bool? BodyAsJsonIndented { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -2,7 +2,6 @@
|
|||||||
|
|
||||||
namespace WireMock.Types;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
#if NETSTANDARD1_3_OR_GREATER || NET461
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Describes the client certificate requirements for a HTTPS connection.
|
/// Describes the client certificate requirements for a HTTPS connection.
|
||||||
/// This enum is the same as https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.https.clientcertificatemode
|
/// This enum is the same as https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.https.clientcertificatemode
|
||||||
@@ -29,5 +28,4 @@ public enum ClientCertificateMode
|
|||||||
/// It may be requested by the application later.
|
/// It may be requested by the application later.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
DelayCertificate,
|
DelayCertificate,
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WireMock.Types;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
[Flags]
|
[Flags]
|
||||||
@@ -13,5 +11,11 @@ public enum HostingScheme
|
|||||||
|
|
||||||
Https = 0x2,
|
Https = 0x2,
|
||||||
|
|
||||||
HttpAndHttps = Http | Https
|
HttpAndHttps = Http | Https,
|
||||||
|
|
||||||
|
Ws = 0x4,
|
||||||
|
|
||||||
|
Wss = 0x8,
|
||||||
|
|
||||||
|
WsAndWss = Ws | Wss
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Description>Commonly used interfaces, models, enumerations and types.</Description>
|
<Description>Commonly used interfaces, models, enumerations and types.</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net45;net451;net461;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<NoWarn>$(NoWarn);1591;8603</NoWarn>
|
<NoWarn>$(NoWarn);1591;8603</NoWarn>
|
||||||
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
||||||
@@ -33,32 +33,31 @@
|
|||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1'">
|
<!--<ItemGroup Condition=" '$(TargetFramework)' == 'net48' ">
|
||||||
<DefineConstants>$(DefineConstants);GRAPHQL;MIMEKIT;PROTOBUF</DefineConstants>
|
--><!-- CVE-2018-8292 / https://github.com/advisories/GHSA-7jgj-8wvc-jh57 --><!--
|
||||||
</PropertyGroup>
|
<PackageReference Include="System.Net.Http" Version="4.3.4" />
|
||||||
|
</ItemGroup>-->
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<!-- CVE-2018-8292 / https://github.com/advisories/GHSA-7jgj-8wvc-jh57 -->
|
<PackageReference Include="FluentBuilder" Version="0.13.0">
|
||||||
<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.15.0">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard')) and '$(TargetFramework)' != 'netstandard1.0'">
|
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' or '$(TargetFramework)' == 'netstandard2.1' ">
|
||||||
<PackageReference Include="System.Security.Cryptography.X509Certificates" Version="4.3.0" />
|
<PackageReference Include="Required" Version="1.0.0">
|
||||||
</ItemGroup>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'netstandard1.3' or '$(TargetFramework)' == 'net45' or '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net461'">
|
<PackageReference Include="IsExternalInit" Version="1.0.3">
|
||||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
|
<PackageReference Include="Nullable" Version="1.3.1">
|
||||||
|
<PrivateAssets>all</PrivateAssets>
|
||||||
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -38,7 +38,7 @@
|
|||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.2" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace WireMock.AwesomeAssertions;
|
namespace WireMock.AwesomeAssertions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using WireMock.Constants;
|
using WireMock.Constants;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace WireMock.AwesomeAssertions;
|
namespace WireMock.AwesomeAssertions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|
||||||
|
|||||||
@@ -3,21 +3,20 @@
|
|||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace WireMock.AwesomeAssertions
|
namespace WireMock.AwesomeAssertions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Contains extension methods for custom assertions in unit tests.
|
||||||
|
/// </summary>
|
||||||
|
public static class WireMockExtensions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Contains extension methods for custom assertions in unit tests.
|
/// Returns a <see cref="WireMockReceivedAssertions"/> object that can be used to assert the current <see cref="IWireMockServer"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public static class WireMockExtensions
|
/// <param name="instance">The WireMockServer</param>
|
||||||
|
/// <returns><see cref="WireMockReceivedAssertions"/></returns>
|
||||||
|
public static WireMockReceivedAssertions Should(this IWireMockServer instance)
|
||||||
{
|
{
|
||||||
/// <summary>
|
return new WireMockReceivedAssertions(instance, AssertionChain.GetOrCreate());
|
||||||
/// Returns a <see cref="WireMockReceivedAssertions"/> object that can be used to assert the current <see cref="IWireMockServer"/>.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="instance">The WireMockServer</param>
|
|
||||||
/// <returns><see cref="WireMockReceivedAssertions"/></returns>
|
|
||||||
public static WireMockReceivedAssertions Should(this IWireMockServer instance)
|
|
||||||
{
|
|
||||||
return new WireMockReceivedAssertions(instance, AssertionChain.GetOrCreate());
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Description>AwesomeAssertions extensions for WireMock.Net</Description>
|
<Description>AwesomeAssertions extensions for WireMock.Net</Description>
|
||||||
<AssemblyTitle>WireMock.Net.AwesomeAssertions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.AwesomeAssertions</AssemblyTitle>
|
||||||
<Authors>Francesco Venturoli;Mahmoud Ali;Stef Heyenrath</Authors>
|
<Authors>Francesco Venturoli;Mahmoud Ali;Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net47;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<AssemblyName>WireMock.Net.AwesomeAssertions</AssemblyName>
|
<AssemblyName>WireMock.Net.AwesomeAssertions</AssemblyName>
|
||||||
<PackageId>WireMock.Net.AwesomeAssertions</PackageId>
|
<PackageId>WireMock.Net.AwesomeAssertions</PackageId>
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="AwesomeAssertions" Version="9.0.0" />
|
<PackageReference Include="AwesomeAssertions" Version="9.1.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -21,4 +21,4 @@ public sealed class WireMockRequestInfo<TBody> : WireMockRequestInfo
|
|||||||
/// Gets or initializes the deserialized request body.
|
/// Gets or initializes the deserialized request body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public TBody? Body { get; init; }
|
public TBody? Body { get; init; }
|
||||||
}
|
}
|
||||||
@@ -1,8 +1,8 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description>
|
<Description>WireMock.Net.Routing extends WireMock.Net with modern, minimal-API-style routing for .NET</Description>
|
||||||
<Authors>Gennadii Saltyshchak</Authors>
|
<Authors>Gennadii Saltyshchak</Authors>
|
||||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
<TargetFramework>net8.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>tdd;mock;http;wiremock;test;server;unittest;routing;minimalapi</PackageTags>
|
<PackageTags>tdd;mock;http;wiremock;test;server;unittest;routing;minimalapi</PackageTags>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
@@ -25,10 +25,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.7.0" />
|
<PackageReference Include="JsonConverter.Abstractions" Version="0.8.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
|
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace WireMock.FluentAssertions;
|
namespace WireMock.FluentAssertions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using WireMock.Constants;
|
using WireMock.Constants;
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
// ReSharper disable once CheckNamespace
|
||||||
namespace WireMock.FluentAssertions;
|
namespace WireMock.FluentAssertions;
|
||||||
|
|
||||||
|
|||||||
@@ -1,8 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#pragma warning disable CS1591
|
#pragma warning disable CS1591
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
||||||
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
||||||
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net451;net47;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
||||||
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
||||||
@@ -31,12 +31,8 @@
|
|||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
|
<ItemGroup>
|
||||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
<PackageReference Include="FluentAssertions" Version="7.2.1" />
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
|
|
||||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>GraphQL support for WireMock.Net</Description>
|
<Description>GraphQL support for WireMock.Net</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Matchers.GraphQL</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Matchers.GraphQL</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0;net6.0;net8.0</TargetFrameworks>
|
<TargetFrameworks>net462;netstandard2.1;net8.0</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>wiremock;matchers;matcher;graphql</PackageTags>
|
<PackageTags>wiremock;matchers;matcher;graphql</PackageTags>
|
||||||
<RootNamespace>WireMock</RootNamespace>
|
<RootNamespace>WireMock</RootNamespace>
|
||||||
@@ -26,22 +26,11 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="GraphQL.NewtonsoftJson" Version="8.2.1" />
|
<PackageReference Include="GraphQL.NewtonsoftJson" Version="8.5.0" />
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
|
||||||
<PackageReference Include="System.Reflection.Emit" Version="4.3.0" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WireMock.Net.Shared\WireMock.Net.Shared.csproj" />
|
<ProjectReference Include="..\WireMock.Net.Shared\WireMock.Net.Shared.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard2.0' ">
|
|
||||||
<PackageReference Include="Nullable" Version="1.3.1">
|
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,7 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
@@ -106,74 +104,6 @@ public class CSharpCodeMatcher : ICSharpCodeMatcher
|
|||||||
var inputValue = isMatchWithString ? input : JObject.FromObject(input);
|
var inputValue = isMatchWithString ? input : JObject.FromObject(input);
|
||||||
var source = GetSourceForIsMatchWithString(pattern, isMatchWithString);
|
var source = GetSourceForIsMatchWithString(pattern, isMatchWithString);
|
||||||
|
|
||||||
object? result;
|
|
||||||
|
|
||||||
#if (NET451 || NET452)
|
|
||||||
var compilerParams = new System.CodeDom.Compiler.CompilerParameters
|
|
||||||
{
|
|
||||||
GenerateInMemory = true,
|
|
||||||
GenerateExecutable = false,
|
|
||||||
ReferencedAssemblies =
|
|
||||||
{
|
|
||||||
"System.dll",
|
|
||||||
"System.Core.dll",
|
|
||||||
"Microsoft.CSharp.dll",
|
|
||||||
"Newtonsoft.Json.dll"
|
|
||||||
}
|
|
||||||
};
|
|
||||||
|
|
||||||
using (var codeProvider = new Microsoft.CSharp.CSharpCodeProvider())
|
|
||||||
{
|
|
||||||
var compilerResults = codeProvider.CompileAssemblyFromSource(compilerParams, source);
|
|
||||||
|
|
||||||
if (compilerResults.Errors.Count != 0)
|
|
||||||
{
|
|
||||||
var errors = from System.CodeDom.Compiler.CompilerError er in compilerResults.Errors select er.ToString();
|
|
||||||
throw new WireMockException(string.Join(", ", errors));
|
|
||||||
}
|
|
||||||
|
|
||||||
var helper = compilerResults.CompiledAssembly?.CreateInstance("CodeHelper");
|
|
||||||
if (helper == null)
|
|
||||||
{
|
|
||||||
throw new WireMockException("CSharpCodeMatcher: Unable to create instance from WireMock.CodeHelper");
|
|
||||||
}
|
|
||||||
|
|
||||||
var methodInfo = helper.GetType().GetMethod("IsMatch");
|
|
||||||
if (methodInfo == null)
|
|
||||||
{
|
|
||||||
throw new WireMockException("CSharpCodeMatcher: Unable to find method 'IsMatch' in WireMock.CodeHelper");
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = methodInfo.Invoke(helper, new[] { inputValue });
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new WireMockException("CSharpCodeMatcher: Unable to call method 'IsMatch' in WireMock.CodeHelper", ex);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#elif (NET46 || NET461)
|
|
||||||
dynamic script;
|
|
||||||
try
|
|
||||||
{
|
|
||||||
script = CSScriptLibrary.CSScript.Evaluator.CompileCode(source).CreateObject("*");
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new WireMockException("CSharpCodeMatcher: Unable to create compiler for WireMock.CodeHelper", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
result = script.IsMatch(inputValue);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
|
|
||||||
}
|
|
||||||
|
|
||||||
#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0_OR_GREATER)
|
|
||||||
Assembly assembly;
|
Assembly assembly;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -194,6 +124,7 @@ public class CSharpCodeMatcher : ICSharpCodeMatcher
|
|||||||
throw new WireMockException("CSharpCodeMatcher: Unable to create object from assembly", ex);
|
throw new WireMockException("CSharpCodeMatcher: Unable to create object from assembly", ex);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
object? result;
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
result = script.IsMatch(inputValue);
|
result = script.IsMatch(inputValue);
|
||||||
@@ -202,9 +133,7 @@ public class CSharpCodeMatcher : ICSharpCodeMatcher
|
|||||||
{
|
{
|
||||||
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
|
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
|
||||||
}
|
}
|
||||||
#else
|
|
||||||
throw new NotSupportedException("The 'CSharpCodeMatcher' cannot be used in netstandard 1.3");
|
|
||||||
#endif
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
return (bool)result;
|
return (bool)result;
|
||||||
|
|||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code.</Description>
|
<Description>A CSharpCodeMatcher which can be used to match WireMock.Net Requests using C# code.</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Matchers.CSharpCode</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Matchers.CSharpCode</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<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>
|
<TargetFramework>netstandard2.0</TargetFramework>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>wiremock;matchers;matcher;csharp;csharpcode</PackageTags>
|
<PackageTags>wiremock;matchers;matcher;csharp;csharpcode</PackageTags>
|
||||||
<RootNamespace>WireMock</RootNamespace>
|
<RootNamespace>WireMock</RootNamespace>
|
||||||
@@ -37,16 +37,8 @@
|
|||||||
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
|
<ProjectReference Include="..\WireMock.Net.Minimal\WireMock.Net.Minimal.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'net452' ">
|
<ItemGroup>
|
||||||
<PackageReference Include="Microsoft.CodeDom.Providers.DotNetCompilerPlatform" Version="3.6.0" />
|
<PackageReference Include="CS-Script" Version="4.13.2" />
|
||||||
</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>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -135,6 +135,6 @@ internal class MimeMessageDataWrapper : IMimeMessageData
|
|||||||
/// <inheritdoc/>
|
/// <inheritdoc/>
|
||||||
public override string ToString()
|
public override string ToString()
|
||||||
{
|
{
|
||||||
return _message.ToString();
|
return _message.ToString() ?? string.Empty;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>MultiPart Mime support for WireMock.Net using MimeKitLite</Description>
|
<Description>MultiPart Mime support for WireMock.Net using MimeKitLite</Description>
|
||||||
<AssemblyTitle>WireMock.Net.MimePart</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.MimePart</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>netstandard2.0;netstandard2.1;net462;net47;net48;net6.0;net8.0</TargetFrameworks>
|
<TargetFrameworks>netstandard2.0;net8.0</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>wiremock;matchers;matcher;mime;multipart;mimekit</PackageTags>
|
<PackageTags>wiremock;matchers;matcher;mime;multipart;mimekit</PackageTags>
|
||||||
<RootNamespace>WireMock</RootNamespace>
|
<RootNamespace>WireMock</RootNamespace>
|
||||||
@@ -36,24 +36,16 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Nullable" Version="1.3.1">
|
<PackageReference Include="Stef.Validation" Version="0.2.0" />
|
||||||
<PrivateAssets>all</PrivateAssets>
|
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
|
||||||
</PackageReference>
|
|
||||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--<ItemGroup>
|
|
||||||
<PackageReference Include="MimeKitLite" Version="4.12.0" />
|
|
||||||
</ItemGroup>-->
|
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
<ItemGroup Condition="'$(Configuration)' == 'Debug'">
|
||||||
<PackageReference Include="MimeKitLite" Version="4.12.0" />
|
<PackageReference Include="MimeKitLite" Version="4.13.0" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
<ItemGroup Condition="'$(Configuration)' == 'Release'">
|
||||||
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.40" PrivateAssets="All" />
|
<PackageReference Include="ILRepack.Lib.MSBuild.Task" Version="2.0.43" PrivateAssets="All" />
|
||||||
<PackageReference Include="MimeKitLite" Version="4.12.0" PrivateAssets="All" />
|
<PackageReference Include="MimeKitLite" Version="4.13.0" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#if !NETSTANDARD1_3
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
using System.Diagnostics.CodeAnalysis;
|
||||||
using System.IdentityModel.Tokens.Jwt;
|
using System.IdentityModel.Tokens.Jwt;
|
||||||
@@ -111,5 +110,4 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
|||||||
tenant = null;
|
tenant = null;
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -1,18 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if NET451 || NET452 || NET46 || NET451 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
|
||||||
using System.Text.RegularExpressions;
|
|
||||||
using WireMock.Constants;
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
|
||||||
namespace System;
|
|
||||||
|
|
||||||
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, RegexConstants.DefaultTimeout);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,28 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if NETSTANDARD1_3
|
|
||||||
|
|
||||||
// ReSharper disable once CheckNamespace
|
|
||||||
namespace System.Net;
|
|
||||||
|
|
||||||
internal class WebProxy : IWebProxy
|
|
||||||
{
|
|
||||||
private readonly string _proxy;
|
|
||||||
public ICredentials? Credentials { get; set; }
|
|
||||||
|
|
||||||
public WebProxy(string proxy)
|
|
||||||
{
|
|
||||||
_proxy = proxy;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Uri GetProxy(Uri destination)
|
|
||||||
{
|
|
||||||
return new Uri(_proxy);
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsBypassed(Uri host)
|
|
||||||
{
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -11,29 +11,18 @@ internal static class HttpClientBuilder
|
|||||||
{
|
{
|
||||||
public static HttpClient Build(HttpClientSettings settings)
|
public static HttpClient Build(HttpClientSettings settings)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
var handler = new HttpClientHandler
|
var handler = new HttpClientHandler
|
||||||
{
|
{
|
||||||
CheckCertificateRevocationList = false,
|
CheckCertificateRevocationList = false,
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
SslProtocols = System.Security.Authentication.SslProtocols.Tls13 | System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
||||||
#else
|
ServerCertificateCustomValidationCallback = (_, _, _, _) => true,
|
||||||
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
|
|
||||||
#endif
|
|
||||||
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
|
|
||||||
|
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||||
};
|
};
|
||||||
#elif NET46
|
#else
|
||||||
var handler = new HttpClientHandler
|
var handler = new HttpClientHandler
|
||||||
{
|
{
|
||||||
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
|
ServerCertificateCustomValidationCallback = (_, _, _, _) => true,
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
|
||||||
};
|
|
||||||
#else
|
|
||||||
var handler = new WebRequestHandler
|
|
||||||
{
|
|
||||||
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
|
|
||||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||||
};
|
};
|
||||||
#endif
|
#endif
|
||||||
@@ -67,13 +56,12 @@ internal static class HttpClientBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NET5_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls13 | SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||||
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
#else
|
||||||
#elif !NETSTANDARD1_3
|
|
||||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||||
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
|
||||||
#endif
|
#endif
|
||||||
|
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
||||||
|
|
||||||
return HttpClientFactory2.Create(handler);
|
return HttpClientFactory2.Create(handler);
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ internal static class HttpClientFactory2
|
|||||||
|
|
||||||
var next = handler;
|
var next = handler;
|
||||||
|
|
||||||
foreach (var delegatingHandler in delegatingHandlers.Reverse())
|
foreach (var delegatingHandler in Enumerable.Reverse(delegatingHandlers))
|
||||||
{
|
{
|
||||||
delegatingHandler.InnerHandler = next;
|
delegatingHandler.InnerHandler = next;
|
||||||
next = delegatingHandler;
|
next = delegatingHandler;
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
#if NET5_0_OR_GREATER
|
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
|
|||||||
@@ -43,11 +43,8 @@ internal static class CertificateLoader
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
#if NETSTANDARD || NET46
|
|
||||||
certStore.Dispose();
|
certStore.Dispose();
|
||||||
#else
|
|
||||||
certStore.Close();
|
certStore.Close();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -56,7 +53,7 @@ internal static class CertificateLoader
|
|||||||
if (options.X509CertificateFilePath.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
|
// PEM logic based on: https://www.scottbrady91.com/c-sharp/pem-loading-in-dotnet-core-and-dotnet
|
||||||
#if NET5_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
if (!string.IsNullOrEmpty(options.X509CertificatePassword))
|
if (!string.IsNullOrEmpty(options.X509CertificatePassword))
|
||||||
{
|
{
|
||||||
var certPem = File.ReadAllText(options.X509CertificateFilePath);
|
var certPem = File.ReadAllText(options.X509CertificateFilePath);
|
||||||
@@ -66,18 +63,8 @@ internal static class CertificateLoader
|
|||||||
return new X509Certificate2(cert.Export(X509ContentType.Pfx, defaultPasswordPem), defaultPasswordPem);
|
return new X509Certificate2(cert.Export(X509ContentType.Pfx, defaultPasswordPem), defaultPasswordPem);
|
||||||
}
|
}
|
||||||
return X509Certificate2.CreateFromPemFile(options.X509CertificateFilePath);
|
return X509Certificate2.CreateFromPemFile(options.X509CertificateFilePath);
|
||||||
|
|
||||||
#elif NETCOREAPP3_1
|
|
||||||
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(options.X509CertificatePassword), out _);
|
|
||||||
return cert.CopyWithPrivateKey(key);
|
|
||||||
}
|
|
||||||
return cert;
|
|
||||||
#else
|
#else
|
||||||
throw new InvalidOperationException("Loading a PEM Certificate is only supported for .NET Core App 3.1, .NET 5.0 and higher.");
|
throw new InvalidOperationException("Loading a PEM Certificate is only supported for .NET 8.0 and higher.");
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -123,11 +110,8 @@ internal static class CertificateLoader
|
|||||||
}
|
}
|
||||||
finally
|
finally
|
||||||
{
|
{
|
||||||
#if NETSTANDARD || NET46
|
|
||||||
certStore.Dispose();
|
certStore.Dispose();
|
||||||
#else
|
|
||||||
certStore.Close();
|
certStore.Close();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
@@ -145,9 +146,9 @@ public class Mapping : IMapping
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(IRequestMessage requestMessage)
|
public Task<(IResponseMessage Message, IMapping? Mapping)> ProvideResponseAsync(HttpContext context, IRequestMessage requestMessage)
|
||||||
{
|
{
|
||||||
return Provider.ProvideResponseAsync(this, requestMessage, Settings);
|
return Provider.ProvideResponseAsync(this, context, requestMessage, Settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -1,9 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Linq;
|
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Matchers.Request;
|
using WireMock.Matchers.Request;
|
||||||
@@ -164,8 +161,8 @@ public class MappingBuilder : IMappingBuilder
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static string ToJson(object value)
|
private string ToJson(object value)
|
||||||
{
|
{
|
||||||
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault);
|
return _settings.DefaultJsonSerializer.Serialize(value, JsonSerializationConstants.JsonConverterOptionsDefault);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
86
src/WireMock.Net.Minimal/Matchers/FuncMatcher.cs
Normal file
86
src/WireMock.Net.Minimal/Matchers/FuncMatcher.cs
Normal file
@@ -0,0 +1,86 @@
|
|||||||
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using Stef.Validation;
|
||||||
|
using WireMock.Extensions;
|
||||||
|
|
||||||
|
namespace WireMock.Matchers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// FuncMatcher - matches using a custom function
|
||||||
|
/// </summary>
|
||||||
|
/// <inheritdoc cref="IFuncMatcher"/>
|
||||||
|
public class FuncMatcher : IFuncMatcher
|
||||||
|
{
|
||||||
|
private readonly Func<string?, bool>? _stringFunc;
|
||||||
|
private readonly Func<byte[]?, bool>? _bytesFunc;
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MatchBehaviour MatchBehaviour { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="FuncMatcher"/> class for string matching.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func">The function to check if a string is a match.</param>
|
||||||
|
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||||
|
public FuncMatcher(Func<string?, bool> func, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
|
{
|
||||||
|
_stringFunc = Guard.NotNull(func);
|
||||||
|
MatchBehaviour = matchBehaviour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="FuncMatcher"/> class for byte array matching.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func">The function to check if a byte[] is a match.</param>
|
||||||
|
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||||
|
public FuncMatcher(Func<byte[]?, bool> func, MatchBehaviour matchBehaviour = MatchBehaviour.AcceptOnMatch)
|
||||||
|
{
|
||||||
|
_bytesFunc = Guard.NotNull(func);
|
||||||
|
MatchBehaviour = matchBehaviour;
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MatchResult IsMatch(object? value)
|
||||||
|
{
|
||||||
|
if (value is string stringValue && _stringFunc != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return MatchResult.From(Name, MatchBehaviour, _stringFunc(stringValue));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return MatchResult.From(Name, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (value is byte[] bytesValue && _bytesFunc != null)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return MatchResult.From(Name, MatchBehaviour, _bytesFunc(bytesValue));
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
return MatchResult.From(Name, ex);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return MatchResult.From(Name, MatchScores.Mismatch);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string Name => nameof(FuncMatcher);
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string GetCSharpCodeArguments()
|
||||||
|
{
|
||||||
|
var funcType = _stringFunc != null ? "Func<string?, bool>" : "Func<byte[]?, bool>";
|
||||||
|
return $"new {Name}" +
|
||||||
|
$"(" +
|
||||||
|
$"/* {funcType} function */, " +
|
||||||
|
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}" +
|
||||||
|
$")";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -11,9 +11,7 @@ using WireMock.Models;
|
|||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
#if !NETSTANDARD1_3
|
|
||||||
using Wmhelp.XPath2;
|
using Wmhelp.XPath2;
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Matchers;
|
namespace WireMock.Matchers;
|
||||||
|
|
||||||
@@ -135,7 +133,7 @@ public class XPathMatcher : IStringMatcher
|
|||||||
}
|
}
|
||||||
catch
|
catch
|
||||||
{
|
{
|
||||||
_xmlDocument = default;
|
_xmlDocument = null;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -151,25 +149,17 @@ public class XPathMatcher : IStringMatcher
|
|||||||
var xmlNamespaceManager = GetXmlNamespaceManager(xmlNamespaceMap);
|
var xmlNamespaceManager = GetXmlNamespaceManager(xmlNamespaceMap);
|
||||||
if (xmlNamespaceManager == null)
|
if (xmlNamespaceManager == null)
|
||||||
{
|
{
|
||||||
#if NETSTANDARD1_3
|
|
||||||
return navigator.Evaluate(xpath);
|
|
||||||
#else
|
|
||||||
return navigator.XPath2Evaluate(xpath);
|
return navigator.XPath2Evaluate(xpath);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#if NETSTANDARD1_3
|
|
||||||
return navigator.Evaluate(xpath, xmlNamespaceManager);
|
|
||||||
#else
|
|
||||||
return navigator.XPath2Evaluate(xpath, xmlNamespaceManager);
|
return navigator.XPath2Evaluate(xpath, xmlNamespaceManager);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private XmlNamespaceManager? GetXmlNamespaceManager(IEnumerable<XmlNamespace>? xmlNamespaceMap)
|
private XmlNamespaceManager? GetXmlNamespaceManager(IEnumerable<XmlNamespace>? xmlNamespaceMap)
|
||||||
{
|
{
|
||||||
if (_xpathNavigator == null || xmlNamespaceMap == null)
|
if (_xpathNavigator == null || xmlNamespaceMap == null)
|
||||||
{
|
{
|
||||||
return default;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
var nsManager = new XmlNamespaceManager(_xpathNavigator.NameTable);
|
var nsManager = new XmlNamespaceManager(_xpathNavigator.NameTable);
|
||||||
|
|||||||
@@ -1,38 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
|
|
||||||
namespace WireMock.Owin.ActivityTracing;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Options for controlling activity tracing in WireMock.Net middleware.
|
|
||||||
/// These options control the creation of System.Diagnostics.Activity objects
|
|
||||||
/// but do not require any OpenTelemetry exporter dependencies.
|
|
||||||
/// </summary>
|
|
||||||
public class ActivityTracingOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether to exclude admin interface requests from tracing.
|
|
||||||
/// Default is <c>true</c>.
|
|
||||||
/// </summary>
|
|
||||||
public bool ExcludeAdminRequests { get; set; } = true;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether to record request body in trace attributes.
|
|
||||||
/// Default is <c>false</c> due to potential PII concerns.
|
|
||||||
/// </summary>
|
|
||||||
public bool RecordRequestBody { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether to record response body in trace attributes.
|
|
||||||
/// Default is <c>false</c> due to potential PII concerns.
|
|
||||||
/// </summary>
|
|
||||||
public bool RecordResponseBody { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets a value indicating whether to record mapping match details in trace attributes.
|
|
||||||
/// Default is <c>true</c>.
|
|
||||||
/// </summary>
|
|
||||||
public bool RecordMatchDetails { get; set; } = true;
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,34 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if !ACTIVITY_TRACING_SUPPORTED
|
|
||||||
using System;
|
|
||||||
#endif
|
|
||||||
using WireMock.Settings;
|
|
||||||
|
|
||||||
namespace WireMock.Owin.ActivityTracing;
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Validator for Activity Tracing configuration.
|
|
||||||
/// </summary>
|
|
||||||
internal static class ActivityTracingValidator
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Validates that Activity Tracing is supported on the current framework.
|
|
||||||
/// Throws an exception if ActivityTracingOptions is configured on an unsupported framework.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="settings">The WireMock server settings to validate.</param>
|
|
||||||
/// <exception cref="System.InvalidOperationException">
|
|
||||||
/// Thrown when ActivityTracingOptions is configured but the current framework does not support System.Diagnostics.Activity.
|
|
||||||
/// </exception>
|
|
||||||
public static void ValidateActivityApiPresence(WireMockServerSettings settings)
|
|
||||||
{
|
|
||||||
#if !ACTIVITY_TRACING_SUPPORTED
|
|
||||||
if (settings.ActivityTracingOptions is not null)
|
|
||||||
{
|
|
||||||
throw new InvalidOperationException(
|
|
||||||
"Activity Tracing is not supported on this target framework. " +
|
|
||||||
"It requires .NET 5.0 or higher which includes System.Diagnostics.Activity support.");
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,9 +1,9 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
using System;
|
using System;
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
|
using WireMock.Settings;
|
||||||
|
|
||||||
namespace WireMock.Owin.ActivityTracing;
|
namespace WireMock.Owin.ActivityTracing;
|
||||||
|
|
||||||
@@ -196,5 +196,4 @@ public static class WireMockActivitySource
|
|||||||
activity.SetTag("exception.message", exception.Message);
|
activity.SetTag("exception.message", exception.Message);
|
||||||
activity.SetTag("exception.stacktrace", exception.ToString());
|
activity.SetTag("exception.stacktrace", exception.ToString());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
|
#if NET8_0
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
@@ -9,6 +9,8 @@ namespace WireMock.Owin;
|
|||||||
|
|
||||||
internal partial class AspNetCoreSelfHost
|
internal partial class AspNetCoreSelfHost
|
||||||
{
|
{
|
||||||
|
private const string CorsPolicyName = "WireMock.Net - Policy";
|
||||||
|
|
||||||
public void AddCors(IServiceCollection services)
|
public void AddCors(IServiceCollection services)
|
||||||
{
|
{
|
||||||
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
if (_wireMockMiddlewareOptions.CorsPolicyOptions > CorsPolicyOptions.None)
|
||||||
@@ -1,12 +1,10 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#if USE_ASPNETCORE && !NETSTANDARD1_3
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using CertificateLoader = WireMock.HttpsCertificate.CertificateLoader;
|
using CertificateLoader = WireMock.HttpsCertificate.CertificateLoader;
|
||||||
@@ -38,7 +36,7 @@ internal partial class AspNetCoreSelfHost
|
|||||||
options.ServerCertificate = CertificateLoader.LoadCertificate(wireMockMiddlewareOptions, urlDetail.Host);
|
options.ServerCertificate = CertificateLoader.LoadCertificate(wireMockMiddlewareOptions, urlDetail.Host);
|
||||||
}
|
}
|
||||||
|
|
||||||
options.ClientCertificateMode = (ClientCertificateMode)wireMockMiddlewareOptions.ClientCertificateMode;
|
options.ClientCertificateMode = wireMockMiddlewareOptions.ClientCertificateMode;
|
||||||
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
|
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
|
||||||
{
|
{
|
||||||
options.ClientCertificateValidation = (_, _, _) => true;
|
options.ClientCertificateValidation = (_, _, _) => true;
|
||||||
@@ -47,7 +45,7 @@ internal partial class AspNetCoreSelfHost
|
|||||||
|
|
||||||
if (urlDetail.IsHttp2)
|
if (urlDetail.IsHttp2)
|
||||||
{
|
{
|
||||||
listenOptions.Protocols = HttpProtocols.Http2;
|
SetHttp2AsProtocolsOnListenOptions(listenOptions);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
continue;
|
continue;
|
||||||
@@ -55,10 +53,7 @@ internal partial class AspNetCoreSelfHost
|
|||||||
|
|
||||||
if (urlDetail.IsHttp2)
|
if (urlDetail.IsHttp2)
|
||||||
{
|
{
|
||||||
Listen(kestrelOptions, urlDetail, listenOptions =>
|
Listen(kestrelOptions, urlDetail, SetHttp2AsProtocolsOnListenOptions);
|
||||||
{
|
|
||||||
listenOptions.Protocols = HttpProtocols.Http2;
|
|
||||||
});
|
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -66,6 +61,15 @@ internal partial class AspNetCoreSelfHost
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void SetHttp2AsProtocolsOnListenOptions(ListenOptions listenOptions)
|
||||||
|
{
|
||||||
|
#if NET8_0_OR_GREATER
|
||||||
|
listenOptions.Protocols = HttpProtocols.Http2;
|
||||||
|
#else
|
||||||
|
throw new NotSupportedException("HTTP/2 is only supported in .NET 8 or greater.");
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
|
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
|
||||||
{
|
{
|
||||||
// Listens on any IP with the given port.
|
// Listens on any IP with the given port.
|
||||||
@@ -111,5 +115,4 @@ internal static class IWebHostBuilderExtensions
|
|||||||
services.Configure<KestrelServerOptions>(context.Configuration.GetSection("Kestrel"));
|
services.Configure<KestrelServerOptions>(context.Configuration.GetSection("Kestrel"));
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
@@ -1,57 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if USE_ASPNETCORE && NETSTANDARD1_3
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.AspNetCore.Hosting;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel;
|
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
|
||||||
using Microsoft.Extensions.Configuration;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
using WireMock.HttpsCertificate;
|
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
|
||||||
|
|
||||||
internal partial class AspNetCoreSelfHost
|
|
||||||
{
|
|
||||||
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
|
|
||||||
{
|
|
||||||
options.Limits.MaxRequestBufferSize = null;
|
|
||||||
options.Limits.MaxRequestHeaderCount = 100;
|
|
||||||
options.Limits.MaxResponseBufferSize = null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
|
||||||
{
|
|
||||||
foreach (var urlDetail in urlDetails)
|
|
||||||
{
|
|
||||||
if (urlDetail.IsHttps)
|
|
||||||
{
|
|
||||||
options.UseHttps(new HttpsConnectionFilterOptions
|
|
||||||
{
|
|
||||||
ServerCertificate = wireMockMiddlewareOptions.CustomCertificateDefined ? CertificateLoader.LoadCertificate(wireMockMiddlewareOptions, urlDetail.Host) : PublicCertificateHelper.GetX509Certificate2(),
|
|
||||||
ClientCertificateMode = (ClientCertificateMode) wireMockMiddlewareOptions.ClientCertificateMode,
|
|
||||||
ClientCertificateValidation = wireMockMiddlewareOptions.AcceptAnyClientCertificate ? (_, _, _) => true : null
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
internal static class IWebHostBuilderExtensions
|
|
||||||
{
|
|
||||||
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder;
|
|
||||||
|
|
||||||
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
|
|
||||||
{
|
|
||||||
var configuration = new ConfigurationBuilder()
|
|
||||||
.AddEnvironmentVariables()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
return builder.ConfigureServices(services =>
|
|
||||||
{
|
|
||||||
services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
#endif
|
|
||||||
@@ -1,16 +1,12 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.IO;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using Microsoft.AspNetCore.Builder;
|
using Microsoft.AspNetCore.Builder;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
using WireMock.Extensions;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Owin.Mappers;
|
using WireMock.Owin.Mappers;
|
||||||
using WireMock.Services;
|
using WireMock.Services;
|
||||||
@@ -18,25 +14,22 @@ using WireMock.Util;
|
|||||||
|
|
||||||
namespace WireMock.Owin;
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
internal partial class AspNetCoreSelfHost
|
||||||
{
|
{
|
||||||
private const string CorsPolicyName = "WireMock.Net - Policy";
|
|
||||||
|
|
||||||
private readonly CancellationTokenSource _cts = new();
|
private readonly CancellationTokenSource _cts = new();
|
||||||
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
|
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
|
||||||
private readonly IWireMockLogger _logger;
|
private readonly IWireMockLogger _logger;
|
||||||
private readonly HostUrlOptions _urlOptions;
|
private readonly HostUrlOptions _urlOptions;
|
||||||
|
|
||||||
private Exception _runningException;
|
|
||||||
private IWebHost _host;
|
private IWebHost _host;
|
||||||
|
|
||||||
public bool IsStarted { get; private set; }
|
public bool IsStarted { get; private set; }
|
||||||
|
|
||||||
public List<string> Urls { get; } = new();
|
public List<string> Urls { get; } = [];
|
||||||
|
|
||||||
public List<int> Ports { get; } = new();
|
public List<int> Ports { get; } = [];
|
||||||
|
|
||||||
public Exception RunningException => _runningException;
|
public Exception? RunningException { get; private set; }
|
||||||
|
|
||||||
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
|
public AspNetCoreSelfHost(IWireMockMiddlewareOptions wireMockMiddlewareOptions, HostUrlOptions urlOptions)
|
||||||
{
|
{
|
||||||
@@ -74,7 +67,7 @@ internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
|||||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||||
services.AddSingleton<IGuidUtils, GuidUtils>();
|
services.AddSingleton<IGuidUtils, GuidUtils>();
|
||||||
|
|
||||||
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
AddCors(services);
|
AddCors(services);
|
||||||
#endif
|
#endif
|
||||||
_wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services);
|
_wireMockMiddlewareOptions.AdditionalServiceRegistration?.Invoke(services);
|
||||||
@@ -83,8 +76,16 @@ internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
|||||||
{
|
{
|
||||||
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
|
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
|
||||||
|
|
||||||
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
|
#if NET8_0_OR_GREATER
|
||||||
UseCors(appBuilder);
|
UseCors(appBuilder);
|
||||||
|
|
||||||
|
var webSocketOptions = new WebSocketOptions();
|
||||||
|
if (_wireMockMiddlewareOptions.WebSocketSettings?.KeepAliveIntervalSeconds != null)
|
||||||
|
{
|
||||||
|
webSocketOptions.KeepAliveInterval = TimeSpan.FromSeconds(_wireMockMiddlewareOptions.WebSocketSettings.KeepAliveIntervalSeconds);
|
||||||
|
}
|
||||||
|
|
||||||
|
appBuilder.UseWebSockets(webSocketOptions);
|
||||||
#endif
|
#endif
|
||||||
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||||
|
|
||||||
@@ -99,73 +100,76 @@ internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
|||||||
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
|
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
|
||||||
})
|
})
|
||||||
.ConfigureKestrelServerOptions()
|
.ConfigureKestrelServerOptions()
|
||||||
|
|
||||||
#if NETSTANDARD1_3
|
|
||||||
.UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray())
|
|
||||||
#endif
|
|
||||||
.Build();
|
.Build();
|
||||||
|
|
||||||
return RunHost(_cts.Token);
|
return RunHost(_cts.Token);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Task RunHost(CancellationToken token)
|
private Task RunHost(CancellationToken token)
|
||||||
|
{
|
||||||
|
try
|
||||||
{
|
{
|
||||||
try
|
#if NET8_0_OR_GREATER
|
||||||
{
|
var appLifetime = _host.Services.GetRequiredService<Microsoft.Extensions.Hosting.IHostApplicationLifetime>();
|
||||||
#if NETCOREAPP3_1 || NET5_0_OR_GREATER
|
|
||||||
var appLifetime = _host.Services.GetRequiredService<Microsoft.Extensions.Hosting.IHostApplicationLifetime>();
|
|
||||||
#else
|
#else
|
||||||
var appLifetime = _host.Services.GetRequiredService<IApplicationLifetime>();
|
var appLifetime = _host.Services.GetRequiredService<IApplicationLifetime>();
|
||||||
#endif
|
#endif
|
||||||
appLifetime.ApplicationStarted.Register(() =>
|
appLifetime.ApplicationStarted.Register(() =>
|
||||||
{
|
{
|
||||||
var addresses = _host.ServerFeatures
|
var addresses = _host.ServerFeatures
|
||||||
.Get<Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature>()!
|
.Get<Microsoft.AspNetCore.Hosting.Server.Features.IServerAddressesFeature>()!
|
||||||
.Addresses;
|
.Addresses
|
||||||
|
.ToArray();
|
||||||
|
|
||||||
|
if (_urlOptions.Urls == null)
|
||||||
|
{
|
||||||
foreach (var address in addresses)
|
foreach (var address in addresses)
|
||||||
{
|
{
|
||||||
Urls.Add(address.Replace("0.0.0.0", "localhost").Replace("[::]", "localhost"));
|
PortUtils.TryExtract(address, out _, out _, out var scheme, out var host, out var port);
|
||||||
|
|
||||||
PortUtils.TryExtract(address, out _, out _, out _, out _, out var port);
|
var replacedHost = ReplaceHostWithLocalhost(host!);
|
||||||
|
var newUrl = $"{scheme}://{replacedHost}:{port}";
|
||||||
|
Urls.Add(newUrl);
|
||||||
Ports.Add(port);
|
Ports.Add(port);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
var urlOptions = _urlOptions.Urls?.ToArray() ?? [];
|
||||||
|
|
||||||
|
for (int i = 0; i < urlOptions.Length; i++)
|
||||||
|
{
|
||||||
|
PortUtils.TryExtract(urlOptions[i], out _, out _, out var originalScheme, out _, out _);
|
||||||
|
if (originalScheme!.StartsWith("grpc", StringComparison.OrdinalIgnoreCase))
|
||||||
|
{
|
||||||
|
// Always replace "grpc" with "http" in the scheme because GrpcChannel needs http or https.
|
||||||
|
originalScheme = originalScheme.Replace("grpc", "http", StringComparison.OrdinalIgnoreCase);
|
||||||
|
}
|
||||||
|
|
||||||
|
PortUtils.TryExtract(addresses[i], out _, out _, out _, out var realHost, out var realPort);
|
||||||
|
|
||||||
|
var replacedHost = ReplaceHostWithLocalhost(realHost!);
|
||||||
|
var newUrl = $"{originalScheme}://{replacedHost}:{realPort}";
|
||||||
|
|
||||||
|
Urls.Add(newUrl);
|
||||||
|
Ports.Add(realPort);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
IsStarted = true;
|
IsStarted = true;
|
||||||
});
|
});
|
||||||
|
|
||||||
#if NETSTANDARD1_3
|
#if NET8_0
|
||||||
_logger.Info("Server using netstandard1.3");
|
|
||||||
#elif NETSTANDARD2_0
|
|
||||||
_logger.Info("Server using netstandard2.0");
|
|
||||||
#elif NETSTANDARD2_1
|
|
||||||
_logger.Info("Server using netstandard2.1");
|
|
||||||
#elif NETCOREAPP3_1
|
|
||||||
_logger.Info("Server using .NET Core App 3.1");
|
|
||||||
#elif NET5_0
|
|
||||||
_logger.Info("Server using .NET 5.0");
|
|
||||||
#elif NET6_0
|
|
||||||
_logger.Info("Server using .NET 6.0");
|
|
||||||
#elif NET7_0
|
|
||||||
_logger.Info("Server using .NET 7.0");
|
|
||||||
#elif NET8_0
|
|
||||||
_logger.Info("Server using .NET 8.0");
|
_logger.Info("Server using .NET 8.0");
|
||||||
#elif NET46
|
#else
|
||||||
_logger.Info("Server using .NET Framework 4.6.1 or higher");
|
_logger.Info("Server using .NET Standard 2.0");
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#if NETSTANDARD1_3
|
|
||||||
return Task.Run(() =>
|
|
||||||
{
|
|
||||||
_host.Run(token);
|
|
||||||
});
|
|
||||||
#else
|
|
||||||
return _host.RunAsync(token);
|
return _host.RunAsync(token);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
catch (Exception e)
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
_runningException = e;
|
RunningException = e;
|
||||||
_logger.Error(e.ToString());
|
_logger.Error(e.ToString());
|
||||||
|
|
||||||
IsStarted = false;
|
IsStarted = false;
|
||||||
@@ -179,11 +183,11 @@ internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
|||||||
_cts.Cancel();
|
_cts.Cancel();
|
||||||
|
|
||||||
IsStarted = false;
|
IsStarted = false;
|
||||||
#if NETSTANDARD1_3
|
|
||||||
return Task.CompletedTask;
|
|
||||||
#else
|
|
||||||
return _host.StopAsync();
|
return _host.StopAsync();
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
|
||||||
#endif
|
private static string ReplaceHostWithLocalhost(string host)
|
||||||
|
{
|
||||||
|
return host.Replace("0.0.0.0", "localhost").Replace("[::]", "localhost");
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,68 +3,44 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using Microsoft.Owin;
|
|
||||||
using IContext = Microsoft.Owin.IOwinContext;
|
|
||||||
using OwinMiddleware = Microsoft.Owin.OwinMiddleware;
|
|
||||||
using Next = Microsoft.Owin.OwinMiddleware;
|
|
||||||
#else
|
|
||||||
using OwinMiddleware = System.Object;
|
|
||||||
using IContext = Microsoft.AspNetCore.Http.HttpContext;
|
|
||||||
using Next = Microsoft.AspNetCore.Http.RequestDelegate;
|
|
||||||
#endif
|
|
||||||
using WireMock.Owin.Mappers;
|
using WireMock.Owin.Mappers;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
|
|
||||||
namespace WireMock.Owin
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
|
internal class GlobalExceptionMiddleware
|
||||||
{
|
{
|
||||||
internal class GlobalExceptionMiddleware : OwinMiddleware
|
private readonly IWireMockMiddlewareOptions _options;
|
||||||
|
private readonly IOwinResponseMapper _responseMapper;
|
||||||
|
|
||||||
|
public GlobalExceptionMiddleware(RequestDelegate next, IWireMockMiddlewareOptions options, IOwinResponseMapper responseMapper)
|
||||||
{
|
{
|
||||||
private readonly IWireMockMiddlewareOptions _options;
|
Next = next;
|
||||||
private readonly IOwinResponseMapper _responseMapper;
|
_options = Guard.NotNull(options);
|
||||||
|
_responseMapper = Guard.NotNull(responseMapper);
|
||||||
|
}
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
public RequestDelegate? Next { get; }
|
||||||
public GlobalExceptionMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinResponseMapper responseMapper) : base(next)
|
|
||||||
{
|
|
||||||
_options = Guard.NotNull(options);
|
|
||||||
_responseMapper = Guard.NotNull(responseMapper);;
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public GlobalExceptionMiddleware(Next next, IWireMockMiddlewareOptions options, IOwinResponseMapper responseMapper)
|
|
||||||
{
|
|
||||||
Next = next;
|
|
||||||
_options = Guard.NotNull(options);
|
|
||||||
_responseMapper = Guard.NotNull(responseMapper);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
public Task Invoke(HttpContext ctx)
|
||||||
public Next Next { get; }
|
{
|
||||||
#endif
|
return InvokeInternalAsync(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
private async Task InvokeInternalAsync(HttpContext ctx)
|
||||||
public override Task Invoke(IContext ctx)
|
{
|
||||||
#else
|
try
|
||||||
public Task Invoke(IContext ctx)
|
|
||||||
#endif
|
|
||||||
{
|
{
|
||||||
return InvokeInternalAsync(ctx);
|
if (Next != null)
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InvokeInternalAsync(IContext ctx)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
if (Next != null)
|
await Next.Invoke(ctx).ConfigureAwait(false);
|
||||||
{
|
|
||||||
await Next.Invoke(ctx).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
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);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
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);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -23,20 +22,34 @@ internal class HostUrlOptions
|
|||||||
var list = new List<HostUrlDetails>();
|
var list = new List<HostUrlDetails>();
|
||||||
if (Urls == null)
|
if (Urls == null)
|
||||||
{
|
{
|
||||||
if (HostingScheme is HostingScheme.Http or HostingScheme.Https)
|
if (HostingScheme is not HostingScheme.None)
|
||||||
{
|
{
|
||||||
var port = Port > 0 ? Port.Value : FindFreeTcpPort();
|
var scheme = GetSchemeAsString(HostingScheme);
|
||||||
var scheme = HostingScheme == HostingScheme.Https ? "https" : "http";
|
var port = Port > 0 ? Port.Value : 0;
|
||||||
list.Add(new HostUrlDetails { IsHttps = HostingScheme == HostingScheme.Https, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Star}:{port}", Scheme = scheme, Host = Star, Port = port });
|
var isHttps = HostingScheme == HostingScheme.Https || HostingScheme == HostingScheme.Wss;
|
||||||
|
list.Add(new HostUrlDetails { IsHttps = isHttps, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Star}:{port}", Scheme = scheme, Host = Star, Port = port });
|
||||||
}
|
}
|
||||||
|
|
||||||
if (HostingScheme == HostingScheme.HttpAndHttps)
|
if (HostingScheme == HostingScheme.HttpAndHttps)
|
||||||
{
|
{
|
||||||
var httpPort = Port > 0 ? Port.Value : FindFreeTcpPort();
|
var port = Port > 0 ? Port.Value : 0;
|
||||||
list.Add(new HostUrlDetails { IsHttps = false, IsHttp2 = UseHttp2 == true, Url = $"http://{Star}:{httpPort}", Scheme = "http", Host = Star, Port = httpPort });
|
var scheme = GetSchemeAsString(HostingScheme.Http);
|
||||||
|
list.Add(new HostUrlDetails { IsHttps = false, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Star}:{port}", Scheme = scheme, Host = Star, Port = port });
|
||||||
|
|
||||||
var httpsPort = FindFreeTcpPort(); // In this scenario, always get a free port for https.
|
var securePort = 0; // In this scenario, always get a free port for https.
|
||||||
list.Add(new HostUrlDetails { IsHttps = true, IsHttp2 = UseHttp2 == true, Url = $"https://{Star}:{httpsPort}", Scheme = "https", Host = Star, Port = httpsPort });
|
var secureScheme = GetSchemeAsString(HostingScheme.Https);
|
||||||
|
list.Add(new HostUrlDetails { IsHttps = true, IsHttp2 = UseHttp2 == true, Url = $"{secureScheme}://{Star}:{securePort}", Scheme = secureScheme, Host = Star, Port = securePort });
|
||||||
|
}
|
||||||
|
|
||||||
|
if (HostingScheme == HostingScheme.WsAndWss)
|
||||||
|
{
|
||||||
|
var port = Port > 0 ? Port.Value : 0;
|
||||||
|
var scheme = GetSchemeAsString(HostingScheme.Ws);
|
||||||
|
list.Add(new HostUrlDetails { IsHttps = false, IsHttp2 = UseHttp2 == true, Url = $"{scheme}://{Star}:{port}", Scheme = scheme, Host = Star, Port = port });
|
||||||
|
|
||||||
|
var securePort = 0; // In this scenario, always get a free port for https.
|
||||||
|
var secureScheme = GetSchemeAsString(HostingScheme.Wss);
|
||||||
|
list.Add(new HostUrlDetails { IsHttps = true, IsHttp2 = UseHttp2 == true, Url = $"{secureScheme}://{Star}:{securePort}", Scheme = secureScheme, Host = Star, Port = securePort });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
@@ -53,12 +66,19 @@ internal class HostUrlOptions
|
|||||||
return list;
|
return list;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static int FindFreeTcpPort()
|
private string GetSchemeAsString(HostingScheme scheme)
|
||||||
{
|
{
|
||||||
#if USE_ASPNETCORE || NETSTANDARD2_0 || NETSTANDARD2_1
|
return scheme switch
|
||||||
return 0;
|
{
|
||||||
#else
|
HostingScheme.Http => "http",
|
||||||
return PortUtils.FindFreeTcpPort();
|
HostingScheme.Https => "https",
|
||||||
#endif
|
HostingScheme.HttpAndHttps => "http", // Default to http when both are specified, since the https URL will be added separately with a free port.
|
||||||
|
|
||||||
|
HostingScheme.Ws => "ws",
|
||||||
|
HostingScheme.Wss => "wss",
|
||||||
|
HostingScheme.WsAndWss => "ws", // Default to ws when both are specified, since the wss URL will be added separately with a free port.
|
||||||
|
|
||||||
|
_ => throw new NotSupportedException($"Unsupported hosting scheme: {HostingScheme}")
|
||||||
|
};
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,37 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using System;
|
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
|
||||||
|
|
||||||
interface IOwinSelfHost
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this server is started.
|
|
||||||
/// </summary>
|
|
||||||
/// <value>
|
|
||||||
/// <c>true</c> if this server is started; otherwise, <c>false</c>.
|
|
||||||
/// </value>
|
|
||||||
bool IsStarted { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the urls.
|
|
||||||
/// </summary>
|
|
||||||
List<string> Urls { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Gets the ports.
|
|
||||||
/// </summary>
|
|
||||||
List<int> Ports { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// The exception occurred when the host is running.
|
|
||||||
/// </summary>
|
|
||||||
Exception? RunningException { get; }
|
|
||||||
|
|
||||||
Task StartAsync();
|
|
||||||
|
|
||||||
Task StopAsync();
|
|
||||||
}
|
|
||||||
@@ -2,22 +2,17 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Owin.ActivityTracing;
|
using WireMock.Settings;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using WireMock.WebSockets;
|
||||||
|
using ClientCertificateMode = Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode;
|
||||||
using JetBrains.Annotations;
|
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using Owin;
|
|
||||||
#else
|
|
||||||
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
@@ -41,11 +36,10 @@ internal interface IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
int? MaxRequestLogCount { get; set; }
|
int? MaxRequestLogCount { get; set; }
|
||||||
|
|
||||||
Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
|
Action<IApplicationBuilder>? PreWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
|
Action<IApplicationBuilder>? PostWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
|
||||||
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||||
|
|
||||||
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||||
@@ -53,7 +47,6 @@ internal interface IWireMockMiddlewareOptions
|
|||||||
ClientCertificateMode ClientCertificateMode { get; set; }
|
ClientCertificateMode ClientCertificateMode { get; set; }
|
||||||
|
|
||||||
bool AcceptAnyClientCertificate { get; set; }
|
bool AcceptAnyClientCertificate { get; set; }
|
||||||
#endif
|
|
||||||
|
|
||||||
IFileSystemHandler? FileSystemHandler { get; set; }
|
IFileSystemHandler? FileSystemHandler { get; set; }
|
||||||
|
|
||||||
@@ -90,13 +83,21 @@ internal interface IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
|
|
||||||
public bool ProxyAll { get; set; }
|
bool ProxyAll { get; set; }
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the activity tracing options.
|
/// Gets or sets the activity tracing options.
|
||||||
/// When set, System.Diagnostics.Activity objects are created for request tracing.
|
/// When set, System.Diagnostics.Activity objects are created for request tracing.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
||||||
#endif
|
|
||||||
|
/// <summary>
|
||||||
|
/// The WebSocket connection registries per mapping (used for broadcast).
|
||||||
|
/// </summary>
|
||||||
|
ConcurrentDictionary<Guid, WebSocketConnectionRegistry> WebSocketRegistries { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WebSocket settings.
|
||||||
|
/// </summary>
|
||||||
|
WebSocketSettings? WebSocketSettings { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,25 +1,19 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Http;
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using IRequest = Microsoft.Owin.IOwinRequest;
|
|
||||||
#else
|
|
||||||
using IRequest = Microsoft.AspNetCore.Http.HttpRequest;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin.Mappers
|
namespace WireMock.Owin.Mappers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IOwinRequestMapper
|
||||||
|
/// </summary>
|
||||||
|
internal interface IOwinRequestMapper
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// IOwinRequestMapper
|
/// MapAsync IRequest to RequestMessage
|
||||||
/// </summary>
|
/// </summary>
|
||||||
internal interface IOwinRequestMapper
|
/// <param name="context">The HttpContext</param>
|
||||||
{
|
/// <param name="options">The WireMockMiddlewareOptions</param>
|
||||||
/// <summary>
|
/// <returns>RequestMessage</returns>
|
||||||
/// MapAsync IRequest to RequestMessage
|
Task<RequestMessage> MapAsync(HttpContext context, IWireMockMiddlewareOptions options);
|
||||||
/// </summary>
|
|
||||||
/// <param name="request">The OwinRequest/HttpRequest</param>
|
|
||||||
/// <param name="options">The WireMockMiddlewareOptions</param>
|
|
||||||
/// <returns>RequestMessage</returns>
|
|
||||||
Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,11 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Http;
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using IResponse = Microsoft.Owin.IOwinResponse;
|
|
||||||
#else
|
|
||||||
using IResponse = Microsoft.AspNetCore.Http.HttpResponse;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin.Mappers;
|
namespace WireMock.Owin.Mappers;
|
||||||
|
|
||||||
@@ -18,6 +13,6 @@ internal interface IOwinResponseMapper
|
|||||||
/// Map ResponseMessage to IResponse.
|
/// Map ResponseMessage to IResponse.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="responseMessage">The ResponseMessage</param>
|
/// <param name="responseMessage">The ResponseMessage</param>
|
||||||
/// <param name="response">The OwinResponse/HttpResponse</param>
|
/// <param name="response">The HttpResponse</param>
|
||||||
Task MapAsync(IResponseMessage? responseMessage, IResponse response);
|
Task MapAsync(IResponseMessage? responseMessage, HttpResponse response);
|
||||||
}
|
}
|
||||||
@@ -1,18 +1,11 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Threading.Tasks;
|
using Microsoft.AspNetCore.Http;
|
||||||
|
using Microsoft.AspNetCore.Http.Extensions;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using IRequest = Microsoft.Owin.IOwinRequest;
|
|
||||||
#else
|
|
||||||
using Microsoft.AspNetCore.Http.Extensions;
|
|
||||||
using IRequest = Microsoft.AspNetCore.Http.HttpRequest;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin.Mappers;
|
namespace WireMock.Owin.Mappers;
|
||||||
|
|
||||||
@@ -22,8 +15,9 @@ namespace WireMock.Owin.Mappers;
|
|||||||
internal class OwinRequestMapper : IOwinRequestMapper
|
internal class OwinRequestMapper : IOwinRequestMapper
|
||||||
{
|
{
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task<RequestMessage> MapAsync(IRequest request, IWireMockMiddlewareOptions options)
|
public async Task<RequestMessage> MapAsync(HttpContext context, IWireMockMiddlewareOptions options)
|
||||||
{
|
{
|
||||||
|
var request = context.Request;
|
||||||
var (urlDetails, clientIP) = ParseRequest(request);
|
var (urlDetails, clientIP) = ParseRequest(request);
|
||||||
|
|
||||||
var method = request.Method;
|
var method = request.Method;
|
||||||
@@ -73,22 +67,16 @@ internal class OwinRequestMapper : IOwinRequestMapper
|
|||||||
body,
|
body,
|
||||||
headers,
|
headers,
|
||||||
cookies,
|
cookies,
|
||||||
httpVersion
|
httpVersion,
|
||||||
#if USE_ASPNETCORE
|
await request.HttpContext.Connection.GetClientCertificateAsync()
|
||||||
, await request.HttpContext.Connection.GetClientCertificateAsync()
|
)
|
||||||
#endif
|
|
||||||
)
|
|
||||||
{
|
{
|
||||||
DateTime = DateTime.UtcNow
|
DateTime = DateTime.UtcNow
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
|
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(HttpRequest request)
|
||||||
{
|
{
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
var urlDetails = UrlUtils.Parse(request.Uri, request.PathBase);
|
|
||||||
var clientIP = request.RemoteIpAddress;
|
|
||||||
#else
|
|
||||||
var urlDetails = UrlUtils.Parse(new Uri(request.GetEncodedUrl()), request.PathBase);
|
var urlDetails = UrlUtils.Parse(new Uri(request.GetEncodedUrl()), request.PathBase);
|
||||||
|
|
||||||
var connection = request.HttpContext.Connection;
|
var connection = request.HttpContext.Connection;
|
||||||
@@ -105,7 +93,7 @@ internal class OwinRequestMapper : IOwinRequestMapper
|
|||||||
{
|
{
|
||||||
clientIP = connection.RemoteIpAddress.ToString();
|
clientIP = connection.RemoteIpAddress.ToString();
|
||||||
}
|
}
|
||||||
#endif
|
|
||||||
return (urlDetails, clientIP);
|
return (urlDetails, clientIP);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -8,22 +8,17 @@ using System.Net;
|
|||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using RandomDataGenerator.FieldOptions;
|
using RandomDataGenerator.FieldOptions;
|
||||||
using RandomDataGenerator.Randomizers;
|
using RandomDataGenerator.Randomizers;
|
||||||
|
using Stef.Validation;
|
||||||
using WireMock.Http;
|
using WireMock.Http;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.ResponseProviders;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using Stef.Validation;
|
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using IResponse = Microsoft.Owin.IOwinResponse;
|
|
||||||
#else
|
|
||||||
using Microsoft.AspNetCore.Http;
|
|
||||||
using IResponse = Microsoft.AspNetCore.Http.HttpResponse;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin.Mappers
|
namespace WireMock.Owin.Mappers
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
@@ -37,8 +32,8 @@ namespace WireMock.Owin.Mappers
|
|||||||
private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
|
private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
|
||||||
|
|
||||||
// https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
|
// https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
|
||||||
private static readonly IDictionary<string, Action<IResponse, bool, WireMockList<string>>> ResponseHeadersToFix =
|
private static readonly IDictionary<string, Action<HttpResponse, bool, WireMockList<string>>> ResponseHeadersToFix =
|
||||||
new Dictionary<string, Action<IResponse, bool, WireMockList<string>>>(StringComparer.OrdinalIgnoreCase)
|
new Dictionary<string, Action<HttpResponse, bool, WireMockList<string>>>(StringComparer.OrdinalIgnoreCase)
|
||||||
{
|
{
|
||||||
{ HttpKnownHeaderNames.ContentType, (r, _, v) => r.ContentType = v.FirstOrDefault() },
|
{ HttpKnownHeaderNames.ContentType, (r, _, v) => r.ContentType = v.FirstOrDefault() },
|
||||||
{ HttpKnownHeaderNames.ContentLength, (r, hasBody, v) =>
|
{ HttpKnownHeaderNames.ContentLength, (r, hasBody, v) =>
|
||||||
@@ -62,9 +57,9 @@ namespace WireMock.Owin.Mappers
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public async Task MapAsync(IResponseMessage? responseMessage, IResponse response)
|
public async Task MapAsync(IResponseMessage? responseMessage, HttpResponse response)
|
||||||
{
|
{
|
||||||
if (responseMessage == null)
|
if (responseMessage == null || responseMessage is WebSocketHandledResponse)
|
||||||
{
|
{
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
@@ -128,7 +123,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
SetResponseTrailingHeaders(responseMessage, response);
|
SetResponseTrailingHeaders(responseMessage, response);
|
||||||
}
|
}
|
||||||
|
|
||||||
private static async Task HandleSseStringAsync(IResponseMessage responseMessage, IResponse response, IBodyData bodyData)
|
private static async Task HandleSseStringAsync(IResponseMessage responseMessage, HttpResponse response, IBodyData bodyData)
|
||||||
{
|
{
|
||||||
if (bodyData.SseStringQueue == null)
|
if (bodyData.SseStringQueue == null)
|
||||||
{
|
{
|
||||||
@@ -202,7 +197,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
return null;
|
return null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetResponseHeaders(IResponseMessage responseMessage, bool hasBody, IResponse response)
|
private static void SetResponseHeaders(IResponseMessage responseMessage, bool hasBody, HttpResponse response)
|
||||||
{
|
{
|
||||||
// Force setting the Date header (#577)
|
// Force setting the Date header (#577)
|
||||||
AppendResponseHeader(
|
AppendResponseHeader(
|
||||||
@@ -218,7 +213,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
var value = item.Value;
|
var value = item.Value;
|
||||||
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
||||||
{
|
{
|
||||||
action?.Invoke(response, hasBody, value);
|
action.Invoke(response, hasBody, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -231,7 +226,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void SetResponseTrailingHeaders(IResponseMessage responseMessage, IResponse response)
|
private static void SetResponseTrailingHeaders(IResponseMessage responseMessage, HttpResponse response)
|
||||||
{
|
{
|
||||||
if (responseMessage.TrailingHeaders == null)
|
if (responseMessage.TrailingHeaders == null)
|
||||||
{
|
{
|
||||||
@@ -239,13 +234,11 @@ namespace WireMock.Owin.Mappers
|
|||||||
}
|
}
|
||||||
|
|
||||||
#if TRAILINGHEADERS
|
#if TRAILINGHEADERS
|
||||||
foreach (var item in responseMessage.TrailingHeaders)
|
foreach (var (headerName, value) in responseMessage.TrailingHeaders)
|
||||||
{
|
{
|
||||||
var headerName = item.Key;
|
|
||||||
var value = item.Value;
|
|
||||||
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
||||||
{
|
{
|
||||||
action?.Invoke(response, false, value);
|
action.Invoke(response, false, value);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
@@ -259,13 +252,9 @@ namespace WireMock.Owin.Mappers
|
|||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void AppendResponseHeader(IResponse response, string headerName, string[] values)
|
private static void AppendResponseHeader(HttpResponse response, string headerName, string[] values)
|
||||||
{
|
{
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
response.Headers.AppendValues(headerName, values);
|
|
||||||
#else
|
|
||||||
response.Headers.Append(headerName, values);
|
response.Headers.Append(headerName, values);
|
||||||
#endif
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,114 +0,0 @@
|
|||||||
// Copyright © WireMock.Net
|
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using Microsoft.Owin.Hosting;
|
|
||||||
using Owin;
|
|
||||||
using System;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using System.Threading;
|
|
||||||
using System.Threading.Tasks;
|
|
||||||
using JetBrains.Annotations;
|
|
||||||
using WireMock.Logging;
|
|
||||||
using WireMock.Owin.Mappers;
|
|
||||||
using Stef.Validation;
|
|
||||||
using WireMock.Services;
|
|
||||||
using WireMock.Util;
|
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
|
||||||
|
|
||||||
internal class OwinSelfHost : IOwinSelfHost
|
|
||||||
{
|
|
||||||
private readonly IWireMockMiddlewareOptions _options;
|
|
||||||
private readonly CancellationTokenSource _cts = new();
|
|
||||||
private readonly IWireMockLogger _logger;
|
|
||||||
|
|
||||||
private Exception? _runningException;
|
|
||||||
|
|
||||||
public OwinSelfHost(IWireMockMiddlewareOptions options, HostUrlOptions urlOptions)
|
|
||||||
{
|
|
||||||
Guard.NotNull(urlOptions);
|
|
||||||
|
|
||||||
_options = Guard.NotNull(options);
|
|
||||||
_logger = options.Logger ?? new WireMockConsoleLogger();
|
|
||||||
|
|
||||||
foreach (var detail in urlOptions.GetDetails())
|
|
||||||
{
|
|
||||||
Urls.Add(detail.Url);
|
|
||||||
Ports.Add(detail.Port);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
public bool IsStarted { get; private set; }
|
|
||||||
|
|
||||||
public List<string> Urls { get; } = new();
|
|
||||||
|
|
||||||
public List<int> Ports { get; } = new();
|
|
||||||
|
|
||||||
public Exception? RunningException => _runningException;
|
|
||||||
|
|
||||||
[PublicAPI]
|
|
||||||
public Task StartAsync()
|
|
||||||
{
|
|
||||||
return Task.Run(StartServers, _cts.Token);
|
|
||||||
}
|
|
||||||
|
|
||||||
[PublicAPI]
|
|
||||||
public Task StopAsync()
|
|
||||||
{
|
|
||||||
_cts.Cancel();
|
|
||||||
|
|
||||||
return Task.FromResult(true);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void StartServers()
|
|
||||||
{
|
|
||||||
#if NET46
|
|
||||||
_logger.Info("Server using .net 4.6");
|
|
||||||
#else
|
|
||||||
_logger.Info("Server using .net 4.5.x");
|
|
||||||
#endif
|
|
||||||
var servers = new List<IDisposable>();
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var requestMapper = new OwinRequestMapper();
|
|
||||||
var responseMapper = new OwinResponseMapper(_options);
|
|
||||||
var matcher = new MappingMatcher(_options, new RandomizerDoubleBetween0And1());
|
|
||||||
var guidUtils = new GuidUtils();
|
|
||||||
|
|
||||||
Action<IAppBuilder> startup = app =>
|
|
||||||
{
|
|
||||||
app.Use<GlobalExceptionMiddleware>(_options, responseMapper);
|
|
||||||
_options.PreWireMockMiddlewareInit?.Invoke(app);
|
|
||||||
app.Use<WireMockMiddleware>(_options, requestMapper, responseMapper, matcher, guidUtils);
|
|
||||||
_options.PostWireMockMiddlewareInit?.Invoke(app);
|
|
||||||
};
|
|
||||||
|
|
||||||
foreach (var url in Urls)
|
|
||||||
{
|
|
||||||
servers.Add(WebApp.Start(url, startup));
|
|
||||||
}
|
|
||||||
|
|
||||||
IsStarted = true;
|
|
||||||
|
|
||||||
// WaitHandle is signaled when the token is cancelled,
|
|
||||||
// which will be more efficient than Thread.Sleep in while loop
|
|
||||||
_cts.Token.WaitHandle.WaitOne();
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
// Expose exception of starting host, otherwise it's hard to be troubleshooting if keeping quiet
|
|
||||||
// For example, WebApp.Start will fail with System.MissingMemberException if Microsoft.Owin.Host.HttpListener.dll is being located
|
|
||||||
// https://stackoverflow.com/questions/25090211/owin-httplistener-not-located/31369857
|
|
||||||
_runningException = e;
|
|
||||||
_logger.Error(e.ToString());
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
IsStarted = false;
|
|
||||||
// Dispose all servers in finally block to make sure clean up allocated resource on error happening
|
|
||||||
servers.ForEach(s => s.Dispose());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
@@ -1,415 +1,354 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Threading.Tasks;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Microsoft.AspNetCore.Http;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Logging;
|
|
||||||
using WireMock.Matchers;
|
|
||||||
using WireMock.Http;
|
|
||||||
using WireMock.Owin.Mappers;
|
|
||||||
using WireMock.Serialization;
|
|
||||||
using WireMock.ResponseBuilders;
|
|
||||||
using WireMock.Settings;
|
|
||||||
using System.Collections.Generic;
|
|
||||||
using WireMock.Constants;
|
using WireMock.Constants;
|
||||||
using WireMock.Exceptions;
|
using WireMock.Exceptions;
|
||||||
|
using WireMock.Http;
|
||||||
|
using WireMock.Logging;
|
||||||
|
using WireMock.Matchers;
|
||||||
|
using WireMock.Owin.Mappers;
|
||||||
|
using WireMock.ResponseBuilders;
|
||||||
|
using WireMock.Serialization;
|
||||||
|
using WireMock.Settings;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
using System.Diagnostics;
|
using System.Diagnostics;
|
||||||
using WireMock.Owin.ActivityTracing;
|
using WireMock.Owin.ActivityTracing;
|
||||||
#endif
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using IContext = Microsoft.Owin.IOwinContext;
|
|
||||||
using OwinMiddleware = Microsoft.Owin.OwinMiddleware;
|
|
||||||
using Next = Microsoft.Owin.OwinMiddleware;
|
|
||||||
#else
|
|
||||||
using OwinMiddleware = System.Object;
|
|
||||||
using IContext = Microsoft.AspNetCore.Http.HttpContext;
|
|
||||||
using Next = Microsoft.AspNetCore.Http.RequestDelegate;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
|
internal class WireMockMiddleware
|
||||||
{
|
{
|
||||||
internal class WireMockMiddleware : OwinMiddleware
|
private readonly object _lock = new();
|
||||||
|
|
||||||
|
private readonly IWireMockMiddlewareOptions _options;
|
||||||
|
private readonly IOwinRequestMapper _requestMapper;
|
||||||
|
private readonly IOwinResponseMapper _responseMapper;
|
||||||
|
private readonly IMappingMatcher _mappingMatcher;
|
||||||
|
private readonly LogEntryMapper _logEntryMapper;
|
||||||
|
private readonly IGuidUtils _guidUtils;
|
||||||
|
|
||||||
|
public WireMockMiddleware(
|
||||||
|
RequestDelegate next,
|
||||||
|
IWireMockMiddlewareOptions options,
|
||||||
|
IOwinRequestMapper requestMapper,
|
||||||
|
IOwinResponseMapper responseMapper,
|
||||||
|
IMappingMatcher mappingMatcher,
|
||||||
|
IGuidUtils guidUtils
|
||||||
|
)
|
||||||
{
|
{
|
||||||
private readonly object _lock = new();
|
_options = Guard.NotNull(options);
|
||||||
private static readonly Task CompletedTask = Task.FromResult(false);
|
_requestMapper = Guard.NotNull(requestMapper);
|
||||||
|
_responseMapper = Guard.NotNull(responseMapper);
|
||||||
|
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
||||||
|
_logEntryMapper = new LogEntryMapper(options);
|
||||||
|
_guidUtils = Guard.NotNull(guidUtils);
|
||||||
|
}
|
||||||
|
|
||||||
private readonly IWireMockMiddlewareOptions _options;
|
public Task Invoke(HttpContext ctx)
|
||||||
private readonly IOwinRequestMapper _requestMapper;
|
{
|
||||||
private readonly IOwinResponseMapper _responseMapper;
|
if (_options.HandleRequestsSynchronously.GetValueOrDefault(false))
|
||||||
private readonly IMappingMatcher _mappingMatcher;
|
|
||||||
private readonly LogEntryMapper _logEntryMapper;
|
|
||||||
private readonly IGuidUtils _guidUtils;
|
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
public WireMockMiddleware(
|
|
||||||
Next next,
|
|
||||||
IWireMockMiddlewareOptions options,
|
|
||||||
IOwinRequestMapper requestMapper,
|
|
||||||
IOwinResponseMapper responseMapper,
|
|
||||||
IMappingMatcher mappingMatcher,
|
|
||||||
IGuidUtils guidUtils
|
|
||||||
) : base(next)
|
|
||||||
{
|
{
|
||||||
_options = Guard.NotNull(options);
|
lock (_lock)
|
||||||
_requestMapper = Guard.NotNull(requestMapper);
|
|
||||||
_responseMapper = Guard.NotNull(responseMapper);
|
|
||||||
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
|
||||||
_logEntryMapper = new LogEntryMapper(options);
|
|
||||||
_guidUtils = Guard.NotNull(guidUtils);
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
public WireMockMiddleware(
|
|
||||||
Next next,
|
|
||||||
IWireMockMiddlewareOptions options,
|
|
||||||
IOwinRequestMapper requestMapper,
|
|
||||||
IOwinResponseMapper responseMapper,
|
|
||||||
IMappingMatcher mappingMatcher,
|
|
||||||
IGuidUtils guidUtils
|
|
||||||
)
|
|
||||||
{
|
|
||||||
_options = Guard.NotNull(options);
|
|
||||||
_requestMapper = Guard.NotNull(requestMapper);
|
|
||||||
_responseMapper = Guard.NotNull(responseMapper);
|
|
||||||
_mappingMatcher = Guard.NotNull(mappingMatcher);
|
|
||||||
_logEntryMapper = new LogEntryMapper(options);
|
|
||||||
_guidUtils = Guard.NotNull(guidUtils);
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
|
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
public override Task Invoke(IContext ctx)
|
|
||||||
#else
|
|
||||||
public Task Invoke(IContext ctx)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
if (_options.HandleRequestsSynchronously.GetValueOrDefault(false))
|
|
||||||
{
|
{
|
||||||
lock (_lock)
|
return InvokeInternalAsync(ctx);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return InvokeInternalAsync(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
private async Task InvokeInternalAsync(HttpContext ctx)
|
||||||
|
{
|
||||||
|
// Store options in HttpContext for providers to access (e.g., WebSocketResponseProvider)
|
||||||
|
ctx.Items[nameof(WireMockMiddlewareOptions)] = _options;
|
||||||
|
|
||||||
|
var request = await _requestMapper.MapAsync(ctx, _options).ConfigureAwait(false);
|
||||||
|
|
||||||
|
var logRequest = false;
|
||||||
|
IResponseMessage? response = null;
|
||||||
|
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
|
||||||
|
|
||||||
|
var tracingEnabled = _options.ActivityTracingOptions is not null;
|
||||||
|
var excludeAdmin = _options.ActivityTracingOptions?.ExcludeAdminRequests ?? true;
|
||||||
|
Activity? activity = null;
|
||||||
|
|
||||||
|
// Check if we should trace this request (optionally exclude admin requests)
|
||||||
|
var shouldTrace = tracingEnabled && !(excludeAdmin && request.Path.StartsWith("/__admin/"));
|
||||||
|
|
||||||
|
if (shouldTrace)
|
||||||
|
{
|
||||||
|
activity = WireMockActivitySource.StartRequestActivity(request.Method, request.Path);
|
||||||
|
WireMockActivitySource.EnrichWithRequest(activity, request, _options.ActivityTracingOptions);
|
||||||
|
}
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
foreach (var mapping in _options.Mappings.Values)
|
||||||
|
{
|
||||||
|
if (mapping.Scenario is null)
|
||||||
{
|
{
|
||||||
return InvokeInternalAsync(ctx);
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Set scenario start
|
||||||
|
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
||||||
|
{
|
||||||
|
_options.Scenarios.TryAdd(mapping.Scenario, new ScenarioState
|
||||||
|
{
|
||||||
|
Name = mapping.Scenario
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return InvokeInternalAsync(ctx);
|
result = _mappingMatcher.FindBestMatch(request);
|
||||||
}
|
|
||||||
|
|
||||||
private async Task InvokeInternalAsync(IContext ctx)
|
var targetMapping = result.Match?.Mapping;
|
||||||
{
|
if (targetMapping == null)
|
||||||
var request = await _requestMapper.MapAsync(ctx.Request, _options).ConfigureAwait(false);
|
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
// Start activity if ActivityTracingOptions is configured
|
|
||||||
var tracingEnabled = _options.ActivityTracingOptions is not null;
|
|
||||||
var excludeAdmin = _options.ActivityTracingOptions?.ExcludeAdminRequests ?? true;
|
|
||||||
Activity? activity = null;
|
|
||||||
|
|
||||||
// Check if we should trace this request (optionally exclude admin requests)
|
|
||||||
var shouldTrace = tracingEnabled && !(excludeAdmin && request.Path.StartsWith("/__admin/"));
|
|
||||||
|
|
||||||
if (shouldTrace)
|
|
||||||
{
|
{
|
||||||
activity = WireMockActivitySource.StartRequestActivity(request.Method, request.Path);
|
logRequest = true;
|
||||||
WireMockActivitySource.EnrichWithRequest(activity, request, _options.ActivityTracingOptions);
|
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
|
||||||
|
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
||||||
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
try
|
logRequest = targetMapping.LogMapping;
|
||||||
{
|
|
||||||
await InvokeInternalCoreAsync(ctx, request, activity).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
activity?.Dispose();
|
|
||||||
}
|
|
||||||
#else
|
|
||||||
await InvokeInternalCoreAsync(ctx, request).ConfigureAwait(false);
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null)
|
||||||
private async Task InvokeInternalCoreAsync(IContext ctx, RequestMessage request, Activity? activity)
|
|
||||||
#else
|
|
||||||
private async Task InvokeInternalCoreAsync(IContext ctx, RequestMessage request)
|
|
||||||
#endif
|
|
||||||
{
|
|
||||||
var logRequest = false;
|
|
||||||
IResponseMessage? response = null;
|
|
||||||
(MappingMatcherResult? Match, MappingMatcherResult? Partial) result = (null, null);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
{
|
||||||
foreach (var mapping in _options.Mappings.Values)
|
var authorizationHeaderPresent = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out var authorization);
|
||||||
|
if (!authorizationHeaderPresent)
|
||||||
{
|
{
|
||||||
if (mapping.Scenario is null)
|
_options.Logger.Error("HttpStatusCode set to 401, authorization header is missing.");
|
||||||
{
|
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
||||||
continue;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Set scenario start
|
|
||||||
if (!_options.Scenarios.ContainsKey(mapping.Scenario) && mapping.IsStartState)
|
|
||||||
{
|
|
||||||
_options.Scenarios.TryAdd(mapping.Scenario, new ScenarioState
|
|
||||||
{
|
|
||||||
Name = mapping.Scenario
|
|
||||||
});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
result = _mappingMatcher.FindBestMatch(request);
|
|
||||||
|
|
||||||
var targetMapping = result.Match?.Mapping;
|
|
||||||
if (targetMapping == null)
|
|
||||||
{
|
|
||||||
logRequest = true;
|
|
||||||
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
|
|
||||||
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
logRequest = targetMapping.LogMapping;
|
var authorizationHeaderMatchResult = _options.AuthenticationMatcher.IsMatch(authorization!.ToString());
|
||||||
|
if (!MatchScores.IsPerfect(authorizationHeaderMatchResult.Score))
|
||||||
if (targetMapping.IsAdminInterface && _options.AuthenticationMatcher != null && request.Headers != null)
|
|
||||||
{
|
{
|
||||||
var authorizationHeaderPresent = request.Headers.TryGetValue(HttpKnownHeaderNames.Authorization, out var authorization);
|
_options.Logger.Error("HttpStatusCode set to 401, authentication failed.", authorizationHeaderMatchResult.Exception ?? throw new WireMockException("Authentication failed"));
|
||||||
if (!authorizationHeaderPresent)
|
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
||||||
{
|
return;
|
||||||
_options.Logger.Error("HttpStatusCode set to 401, authorization header is missing.");
|
}
|
||||||
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
}
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
var authorizationHeaderMatchResult = _options.AuthenticationMatcher.IsMatch(authorization!.ToString());
|
if (!targetMapping.IsAdminInterface && _options.RequestProcessingDelay > TimeSpan.Zero)
|
||||||
if (!MatchScores.IsPerfect(authorizationHeaderMatchResult.Score))
|
{
|
||||||
{
|
await Task.Delay(_options.RequestProcessingDelay.Value).ConfigureAwait(false);
|
||||||
_options.Logger.Error("HttpStatusCode set to 401, authentication failed.", authorizationHeaderMatchResult.Exception ?? throw new WireMockException("Authentication failed"));
|
}
|
||||||
response = ResponseMessageBuilder.Create(HttpStatusCode.Unauthorized, null);
|
|
||||||
return;
|
var (theResponse, theOptionalNewMapping) = await targetMapping.ProvideResponseAsync(ctx, request).ConfigureAwait(false);
|
||||||
}
|
response = theResponse;
|
||||||
|
|
||||||
|
if (targetMapping.Provider is Response responseBuilder && !targetMapping.IsAdminInterface && theOptionalNewMapping != null)
|
||||||
|
{
|
||||||
|
if (responseBuilder?.ProxyAndRecordSettings?.SaveMapping == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMapping == true)
|
||||||
|
{
|
||||||
|
_options.Mappings.TryAdd(theOptionalNewMapping.Guid, theOptionalNewMapping);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!targetMapping.IsAdminInterface && _options.RequestProcessingDelay > TimeSpan.Zero)
|
if (responseBuilder?.ProxyAndRecordSettings?.SaveMappingToFile == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMappingToFile == true)
|
||||||
{
|
{
|
||||||
await Task.Delay(_options.RequestProcessingDelay.Value).ConfigureAwait(false);
|
var matcherMapper = new MatcherMapper(targetMapping.Settings);
|
||||||
|
var mappingConverter = new MappingConverter(matcherMapper);
|
||||||
|
var mappingToFileSaver = new MappingToFileSaver(targetMapping.Settings, mappingConverter);
|
||||||
|
|
||||||
|
mappingToFileSaver.SaveMappingToFile(theOptionalNewMapping);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var (theResponse, theOptionalNewMapping) = await targetMapping.ProvideResponseAsync(request).ConfigureAwait(false);
|
if (targetMapping.Scenario != null)
|
||||||
response = theResponse;
|
{
|
||||||
|
UpdateScenarioState(targetMapping);
|
||||||
|
}
|
||||||
|
|
||||||
var responseBuilder = targetMapping.Provider as Response;
|
if (!targetMapping.IsAdminInterface && targetMapping.Webhooks?.Length > 0)
|
||||||
|
{
|
||||||
|
await SendToWebhooksAsync(targetMapping, request, response).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
|
||||||
|
WireMockActivitySource.RecordException(activity, ex);
|
||||||
|
|
||||||
if (!targetMapping.IsAdminInterface && theOptionalNewMapping != null)
|
response = ResponseMessageBuilder.Create(500, ex.Message);
|
||||||
|
}
|
||||||
|
finally
|
||||||
|
{
|
||||||
|
var log = new LogEntry
|
||||||
|
{
|
||||||
|
Guid = _guidUtils.NewGuid(),
|
||||||
|
RequestMessage = request,
|
||||||
|
ResponseMessage = response,
|
||||||
|
|
||||||
|
MappingGuid = result.Match?.Mapping?.Guid,
|
||||||
|
MappingTitle = result.Match?.Mapping?.Title,
|
||||||
|
RequestMatchResult = result.Match?.RequestMatchResult,
|
||||||
|
|
||||||
|
PartialMappingGuid = result.Partial?.Mapping?.Guid,
|
||||||
|
PartialMappingTitle = result.Partial?.Mapping?.Title,
|
||||||
|
PartialMatchResult = result.Partial?.RequestMatchResult
|
||||||
|
};
|
||||||
|
|
||||||
|
WireMockActivitySource.EnrichWithLogEntry(activity, log, _options.ActivityTracingOptions);
|
||||||
|
activity?.Dispose();
|
||||||
|
|
||||||
|
LogRequest(log, logRequest);
|
||||||
|
|
||||||
|
try
|
||||||
|
{
|
||||||
|
if (_options.SaveUnmatchedRequests == true && result.Match?.RequestMatchResult is not { IsPerfectMatch: true })
|
||||||
{
|
{
|
||||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMapping == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMapping == true)
|
var filename = $"{log.Guid}.LogEntry.json";
|
||||||
{
|
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, JsonUtils.Serialize(log));
|
||||||
_options.Mappings.TryAdd(theOptionalNewMapping.Guid, theOptionalNewMapping);
|
|
||||||
}
|
|
||||||
|
|
||||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMappingToFile == true || targetMapping.Settings.ProxyAndRecordSettings?.SaveMappingToFile == true)
|
|
||||||
{
|
|
||||||
var matcherMapper = new MatcherMapper(targetMapping.Settings);
|
|
||||||
var mappingConverter = new MappingConverter(matcherMapper);
|
|
||||||
var mappingToFileSaver = new MappingToFileSaver(targetMapping.Settings, mappingConverter);
|
|
||||||
|
|
||||||
mappingToFileSaver.SaveMappingToFile(theOptionalNewMapping);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Empty catch
|
||||||
|
}
|
||||||
|
|
||||||
if (targetMapping.Scenario != null)
|
try
|
||||||
{
|
{
|
||||||
UpdateScenarioState(targetMapping);
|
await _responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false);
|
||||||
}
|
|
||||||
|
|
||||||
if (!targetMapping.IsAdminInterface && targetMapping.Webhooks?.Length > 0)
|
|
||||||
{
|
|
||||||
await SendToWebhooksAsync(targetMapping, request, response).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
catch (Exception ex)
|
catch (Exception ex)
|
||||||
{
|
{
|
||||||
_options.Logger.Error($"Providing a Response for Mapping '{result.Match?.Mapping.Guid}' failed. HttpStatusCode set to 500. Exception: {ex}");
|
_options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex);
|
||||||
response = ResponseMessageBuilder.Create(500, ex.Message);
|
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
var notFoundResponse = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
||||||
WireMockActivitySource.RecordException(activity, ex);
|
await _responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false);
|
||||||
#endif
|
|
||||||
}
|
|
||||||
finally
|
|
||||||
{
|
|
||||||
var log = new LogEntry
|
|
||||||
{
|
|
||||||
Guid = _guidUtils.NewGuid(),
|
|
||||||
RequestMessage = request,
|
|
||||||
ResponseMessage = response,
|
|
||||||
|
|
||||||
MappingGuid = result.Match?.Mapping?.Guid,
|
|
||||||
MappingTitle = result.Match?.Mapping?.Title,
|
|
||||||
RequestMatchResult = result.Match?.RequestMatchResult,
|
|
||||||
|
|
||||||
PartialMappingGuid = result.Partial?.Mapping?.Guid,
|
|
||||||
PartialMappingTitle = result.Partial?.Mapping?.Title,
|
|
||||||
PartialMatchResult = result.Partial?.RequestMatchResult
|
|
||||||
};
|
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
// Enrich activity with response and mapping info
|
|
||||||
WireMockActivitySource.EnrichWithLogEntry(activity, log, _options.ActivityTracingOptions);
|
|
||||||
#endif
|
|
||||||
|
|
||||||
LogRequest(log, logRequest);
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
if (_options.SaveUnmatchedRequests == true && result.Match?.RequestMatchResult is not { IsPerfectMatch: true })
|
|
||||||
{
|
|
||||||
var filename = $"{log.Guid}.LogEntry.json";
|
|
||||||
_options.FileSystemHandler?.WriteUnmatchedRequest(filename, JsonUtils.Serialize(log));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Empty catch
|
|
||||||
}
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
await _responseMapper.MapAsync(response, ctx.Response).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_options.Logger.Error("HttpStatusCode set to 404 : No matching mapping found", ex);
|
|
||||||
|
|
||||||
var notFoundResponse = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
|
||||||
await _responseMapper.MapAsync(notFoundResponse, ctx.Response).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
await CompletedTask.ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
|
|
||||||
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
|
|
||||||
{
|
|
||||||
var tasks = new List<Func<Task>>();
|
|
||||||
for (int index = 0; index < mapping.Webhooks?.Length; index++)
|
|
||||||
{
|
|
||||||
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
|
|
||||||
var webhookSender = new WebhookSender(mapping.Settings);
|
|
||||||
var webhookRequest = mapping.Webhooks[index].Request;
|
|
||||||
var webHookIndex = index;
|
|
||||||
|
|
||||||
tasks.Add(async () =>
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var result = await webhookSender.SendAsync(httpClientForWebhook, mapping, webhookRequest, request, response).ConfigureAwait(false);
|
|
||||||
if (!result.IsSuccessStatusCode)
|
|
||||||
{
|
|
||||||
var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
|
||||||
_options.Logger.Warn($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. HttpStatusCode: {result.StatusCode} Content: {content}");
|
|
||||||
}
|
|
||||||
}
|
|
||||||
catch (Exception ex)
|
|
||||||
{
|
|
||||||
_options.Logger.Error($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
|
|
||||||
}
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (mapping.UseWebhooksFireAndForget == true)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
// Do not wait
|
|
||||||
await Task.Run(() =>
|
|
||||||
{
|
|
||||||
Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
await Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void UpdateScenarioState(IMapping mapping)
|
|
||||||
{
|
|
||||||
var scenario = _options.Scenarios[mapping.Scenario!];
|
|
||||||
|
|
||||||
// Increase the number of times this state has been executed
|
|
||||||
scenario.Counter++;
|
|
||||||
|
|
||||||
// Only if the number of times this state is executed equals the required StateTimes, proceed to next state and reset the counter to 0
|
|
||||||
if (scenario.Counter == (mapping.TimesInSameState ?? 1))
|
|
||||||
{
|
|
||||||
scenario.NextState = mapping.NextState;
|
|
||||||
scenario.Counter = 0;
|
|
||||||
}
|
|
||||||
|
|
||||||
// Else just update Started and Finished
|
|
||||||
scenario.Started = true;
|
|
||||||
scenario.Finished = mapping.NextState == null;
|
|
||||||
}
|
|
||||||
|
|
||||||
private void LogRequest(LogEntry entry, bool addRequest)
|
|
||||||
{
|
|
||||||
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
|
||||||
|
|
||||||
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
|
||||||
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
|
||||||
{
|
|
||||||
TryAddLogEntry(entry);
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
|
||||||
if (_options.MaxRequestLogCount is > 0)
|
|
||||||
{
|
|
||||||
var logEntries = _options.LogEntries.ToList();
|
|
||||||
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
|
||||||
{
|
|
||||||
TryRemoveLogEntry(logEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
|
||||||
if (_options.RequestLogExpirationDuration is > 0)
|
|
||||||
{
|
|
||||||
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
|
||||||
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
|
||||||
{
|
|
||||||
TryRemoveLogEntry(logEntry);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TryAddLogEntry(LogEntry logEntry)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_options.LogEntries.Add(logEntry);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore exception (can happen during stress testing)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
private void TryRemoveLogEntry(LogEntry logEntry)
|
|
||||||
{
|
|
||||||
try
|
|
||||||
{
|
|
||||||
_options.LogEntries.Remove(logEntry);
|
|
||||||
}
|
|
||||||
catch
|
|
||||||
{
|
|
||||||
// Ignore exception (can happen during stress testing)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
private async Task SendToWebhooksAsync(IMapping mapping, IRequestMessage request, IResponseMessage response)
|
||||||
|
{
|
||||||
|
var tasks = new List<Func<Task>>();
|
||||||
|
for (int index = 0; index < mapping.Webhooks?.Length; index++)
|
||||||
|
{
|
||||||
|
var httpClientForWebhook = HttpClientBuilder.Build(mapping.Settings.WebhookSettings ?? new WebhookSettings());
|
||||||
|
var webhookSender = new WebhookSender(mapping.Settings);
|
||||||
|
var webhookRequest = mapping.Webhooks[index].Request;
|
||||||
|
var webHookIndex = index;
|
||||||
|
|
||||||
|
tasks.Add(async () =>
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
var result = await webhookSender.SendAsync(httpClientForWebhook, mapping, webhookRequest, request, response).ConfigureAwait(false);
|
||||||
|
if (!result.IsSuccessStatusCode)
|
||||||
|
{
|
||||||
|
var content = await result.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
_options.Logger.Warn($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. HttpStatusCode: {result.StatusCode} Content: {content}");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
catch (Exception ex)
|
||||||
|
{
|
||||||
|
_options.Logger.Error($"Sending message to Webhook [{webHookIndex}] from Mapping '{mapping.Guid}' failed. Exception: {ex}");
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if (mapping.UseWebhooksFireAndForget == true)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
// Do not wait
|
||||||
|
await Task.Run(() =>
|
||||||
|
{
|
||||||
|
Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
await Task.WhenAll(tasks.Select(async task => await task.Invoke())).ConfigureAwait(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void UpdateScenarioState(IMapping mapping)
|
||||||
|
{
|
||||||
|
var scenario = _options.Scenarios[mapping.Scenario!];
|
||||||
|
|
||||||
|
// Increase the number of times this state has been executed
|
||||||
|
scenario.Counter++;
|
||||||
|
|
||||||
|
// Only if the number of times this state is executed equals the required StateTimes, proceed to next state and reset the counter to 0
|
||||||
|
if (scenario.Counter == (mapping.TimesInSameState ?? 1))
|
||||||
|
{
|
||||||
|
scenario.NextState = mapping.NextState;
|
||||||
|
scenario.Counter = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Else just update Started and Finished
|
||||||
|
scenario.Started = true;
|
||||||
|
scenario.Finished = mapping.NextState == null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void LogRequest(LogEntry entry, bool addRequest)
|
||||||
|
{
|
||||||
|
_options.Logger.DebugRequestResponse(_logEntryMapper.Map(entry), entry.RequestMessage.Path.StartsWith("/__admin/"));
|
||||||
|
|
||||||
|
// If addRequest is set to true and MaxRequestLogCount is null or does have a value greater than 0, try to add a new request log.
|
||||||
|
if (addRequest && _options.MaxRequestLogCount is null or > 0)
|
||||||
|
{
|
||||||
|
TryAddLogEntry(entry);
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case MaxRequestLogCount has a value greater than 0, try to delete existing request logs based on the count.
|
||||||
|
if (_options.MaxRequestLogCount is > 0)
|
||||||
|
{
|
||||||
|
var logEntries = _options.LogEntries.ToList();
|
||||||
|
foreach (var logEntry in logEntries.OrderBy(le => le.RequestMessage.DateTime).Take(logEntries.Count - _options.MaxRequestLogCount.Value))
|
||||||
|
{
|
||||||
|
TryRemoveLogEntry(logEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// In case RequestLogExpirationDuration has a value greater than 0, try to delete existing request logs based on the date.
|
||||||
|
if (_options.RequestLogExpirationDuration is > 0)
|
||||||
|
{
|
||||||
|
var checkTime = DateTime.UtcNow.AddHours(-_options.RequestLogExpirationDuration.Value);
|
||||||
|
foreach (var logEntry in _options.LogEntries.ToList().Where(le => le.RequestMessage.DateTime < checkTime))
|
||||||
|
{
|
||||||
|
TryRemoveLogEntry(logEntry);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryAddLogEntry(LogEntry logEntry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_options.LogEntries.Add(logEntry);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore exception (can happen during stress testing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private void TryRemoveLogEntry(LogEntry logEntry)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
_options.LogEntries.Remove(logEntry);
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
// Ignore exception (can happen during stress testing)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -2,20 +2,17 @@
|
|||||||
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Concurrent;
|
using System.Collections.Concurrent;
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
using Microsoft.AspNetCore.Builder;
|
||||||
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using WireMock.Owin.ActivityTracing;
|
using WireMock.Settings;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using System.Security.Cryptography.X509Certificates;
|
using WireMock.WebSockets;
|
||||||
|
using ClientCertificateMode = Microsoft.AspNetCore.Server.Kestrel.Https.ClientCertificateMode;
|
||||||
#if !USE_ASPNETCORE
|
|
||||||
using Owin;
|
|
||||||
#else
|
|
||||||
using IAppBuilder = Microsoft.AspNetCore.Builder.IApplicationBuilder;
|
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
|
||||||
#endif
|
|
||||||
|
|
||||||
namespace WireMock.Owin;
|
namespace WireMock.Owin;
|
||||||
|
|
||||||
@@ -39,11 +36,10 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
public int? MaxRequestLogCount { get; set; }
|
public int? MaxRequestLogCount { get; set; }
|
||||||
|
|
||||||
public Action<IAppBuilder>? PreWireMockMiddlewareInit { get; set; }
|
public Action<IApplicationBuilder>? PreWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
public Action<IAppBuilder>? PostWireMockMiddlewareInit { get; set; }
|
public Action<IApplicationBuilder>? PostWireMockMiddlewareInit { get; set; }
|
||||||
|
|
||||||
#if USE_ASPNETCORE
|
|
||||||
public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
public Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||||
|
|
||||||
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
public CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||||
@@ -52,7 +48,6 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool AcceptAnyClientCertificate { get; set; }
|
public bool AcceptAnyClientCertificate { get; set; }
|
||||||
#endif
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
|
/// <inheritdoc cref="IWireMockMiddlewareOptions.FileSystemHandler"/>
|
||||||
public IFileSystemHandler? FileSystemHandler { get; set; }
|
public IFileSystemHandler? FileSystemHandler { get; set; }
|
||||||
@@ -108,8 +103,11 @@ internal class WireMockMiddlewareOptions : IWireMockMiddlewareOptions
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool ProxyAll { get; set; }
|
public bool ProxyAll { get; set; }
|
||||||
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
public ActivityTracingOptions? ActivityTracingOptions { get; set; }
|
||||||
#endif
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public ConcurrentDictionary<Guid, WebSocketConnectionRegistry> WebSocketRegistries { get; } = new();
|
||||||
|
|
||||||
|
public WebSocketSettings? WebSocketSettings { get; set; }
|
||||||
}
|
}
|
||||||
@@ -19,6 +19,7 @@ internal static class WireMockMiddlewareOptionsHelper
|
|||||||
|
|
||||||
options ??= new WireMockMiddlewareOptions();
|
options ??= new WireMockMiddlewareOptions();
|
||||||
|
|
||||||
|
options.ActivityTracingOptions = settings.ActivityTracingOptions;
|
||||||
options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
|
options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
|
||||||
options.AllowOnlyDefinedHttpStatusCodeInResponse = settings.AllowOnlyDefinedHttpStatusCodeInResponse;
|
options.AllowOnlyDefinedHttpStatusCodeInResponse = settings.AllowOnlyDefinedHttpStatusCodeInResponse;
|
||||||
options.AllowPartialMapping = settings.AllowPartialMapping;
|
options.AllowPartialMapping = settings.AllowPartialMapping;
|
||||||
@@ -35,20 +36,6 @@ internal static class WireMockMiddlewareOptionsHelper
|
|||||||
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||||
|
|
||||||
// Validate and configure activity tracing
|
|
||||||
ActivityTracingValidator.ValidateActivityApiPresence(settings);
|
|
||||||
#if ACTIVITY_TRACING_SUPPORTED
|
|
||||||
if (settings.ActivityTracingOptions is not null)
|
|
||||||
{
|
|
||||||
options.ActivityTracingOptions = new Owin.ActivityTracing.ActivityTracingOptions
|
|
||||||
{
|
|
||||||
ExcludeAdminRequests = settings.ActivityTracingOptions.ExcludeAdminRequests,
|
|
||||||
RecordRequestBody = settings.ActivityTracingOptions.RecordRequestBody,
|
|
||||||
RecordResponseBody = settings.ActivityTracingOptions.RecordResponseBody,
|
|
||||||
RecordMatchDetails = settings.ActivityTracingOptions.RecordMatchDetails
|
|
||||||
};
|
|
||||||
}
|
|
||||||
#endif
|
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
options.AdditionalServiceRegistration = settings.AdditionalServiceRegistration;
|
||||||
options.CorsPolicyOptions = settings.CorsPolicyOptions;
|
options.CorsPolicyOptions = settings.CorsPolicyOptions;
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
// Copyright © WireMock.Net
|
// Copyright © WireMock.Net
|
||||||
|
|
||||||
using System;
|
using WireMock.Extensions;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Transformers;
|
using WireMock.Transformers;
|
||||||
|
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user