mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Compare commits
30 Commits
feature/11
...
1.6.6
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb7e6c397f | ||
|
|
f56ecf943d | ||
|
|
76ae1466cc | ||
|
|
edbc7aeb5c | ||
|
|
42306d1864 | ||
|
|
c57590b2ba | ||
|
|
dca3fd0260 | ||
|
|
95994421ae | ||
|
|
697411555a | ||
|
|
f89f0fa466 | ||
|
|
b892e85d2a | ||
|
|
836976ca19 | ||
|
|
c845f73dd0 | ||
|
|
2cbbef01ae | ||
|
|
dd80fd7822 | ||
|
|
527278e60c | ||
|
|
7d7f1f8fbb | ||
|
|
af124d556d | ||
|
|
60931f6273 | ||
|
|
b99a80e782 | ||
|
|
07c9aebf44 | ||
|
|
8348a7b9a3 | ||
|
|
9a49e6a1cd | ||
|
|
f82891c996 | ||
|
|
da100298c1 | ||
|
|
95573eeb96 | ||
|
|
487d6d2db1 | ||
|
|
d2b53893db | ||
|
|
088444024f | ||
|
|
7e162a00ab |
10
.github/workflows/ci.yml
vendored
10
.github/workflows/ci.yml
vendored
@@ -20,7 +20,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 'Execute Tests'
|
||||
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||
run: |
|
||||
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
||||
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
||||
|
||||
linux-build-and-run:
|
||||
name: Run Tests on Linux
|
||||
@@ -33,7 +36,10 @@ jobs:
|
||||
- uses: actions/checkout@v4
|
||||
|
||||
- name: 'Execute Tests'
|
||||
run: dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||
run: |
|
||||
dotnet test './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj' -c Release --framework net8.0
|
||||
dotnet test './test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj' -c Release --framework net8.0
|
||||
dotnet test './test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj' -c Release --framework net8.0
|
||||
|
||||
- name: Install .NET Aspire workload
|
||||
run: dotnet workload install aspire
|
||||
|
||||
65
CHANGELOG.md
65
CHANGELOG.md
@@ -1,3 +1,51 @@
|
||||
# 1.6.6 (01 October 2024)
|
||||
- [#1185](https://github.com/WireMock-Net/WireMock.Net/pull/1185) - Throw exception in case WithTransformer is used after WithBodyFromFile [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1187](https://github.com/WireMock-Net/WireMock.Net/pull/1187) - Fix StaticMappingsPath in WireMockContainerBuilder [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1184](https://github.com/WireMock-Net/WireMock.Net/issues/1184) - .WithBodyFromFile() + .WithTransformer(transformContentFromBodyAsFile: true) = empty string [bug]
|
||||
- [#1186](https://github.com/WireMock-Net/WireMock.Net/issues/1186) - WithMappings path is null on Build() call [bug]
|
||||
|
||||
# 1.6.5 (28 September 2024)
|
||||
- [#1175](https://github.com/WireMock-Net/WireMock.Net/pull/1175) - Add WireMock.Net.AspNetCore.Middleware [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1181](https://github.com/WireMock-Net/WireMock.Net/pull/1181) - WireMock.Net.Testcontainers: Use 'sheyenrath/wiremock.net-alpine' image as default for Linux [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1182](https://github.com/WireMock-Net/WireMock.Net/pull/1182) - pass in the request when no matching is found to the warn logger [feature] contributed by [JasonLandbridge](https://github.com/JasonLandbridge)
|
||||
|
||||
# 1.6.4 (25 September 2024)
|
||||
- [#1169](https://github.com/WireMock-Net/WireMock.Net/pull/1169) - Allow mapping without Path or Url [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1170](https://github.com/WireMock-Net/WireMock.Net/pull/1170) - Update the .NET Aspire tests [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1172](https://github.com/WireMock-Net/WireMock.Net/pull/1172) - Fix JSON parsing of text/plain content type [bug] contributed by [ruxo](https://github.com/ruxo)
|
||||
- [#1177](https://github.com/WireMock-Net/WireMock.Net/pull/1177) - Unpin Testcontainers version and upgrade to version 3.10.0 [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1178](https://github.com/WireMock-Net/WireMock.Net/pull/1178) - Upgrade CS-Script to version 4.8.17 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1179](https://github.com/WireMock-Net/WireMock.Net/pull/1179) - Add WireMock.Net.TUnit project [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1146](https://github.com/WireMock-Net/WireMock.Net/issues/1146) - Bump Request CS-Script 4.8.13 to 4.8.17 [feature]
|
||||
- [#1167](https://github.com/WireMock-Net/WireMock.Net/issues/1167) - Admin API fails to create a mapping with Request Header matching using WildCardMatcher [bug]
|
||||
- [#1168](https://github.com/WireMock-Net/WireMock.Net/issues/1168) - Numbers in text/plain content is parsed as JSON. [bug]
|
||||
- [#1176](https://github.com/WireMock-Net/WireMock.Net/issues/1176) - WireMock.NET TestContainer Dependency Constraint Issue [bug]
|
||||
|
||||
# 1.6.3 (07 September 2024)
|
||||
- [#1165](https://github.com/WireMock-Net/WireMock.Net/pull/1165) - Fix listen on AnyIP for url 0.0.0.0 contributed by [cocoon](https://github.com/cocoon)
|
||||
- [#1154](https://github.com/WireMock-Net/WireMock.Net/issues/1154) - Listen on all ips [bug]
|
||||
|
||||
# 1.6.2 (04 September 2024)
|
||||
- [#1152](https://github.com/WireMock-Net/WireMock.Net/pull/1152) - Update MappingConverter to correctly write the Matcher as C# code [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1163](https://github.com/WireMock-Net/WireMock.Net/pull/1163) - Upgrade Aspire to version 8.2.0 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1166](https://github.com/WireMock-Net/WireMock.Net/pull/1166) - Also update IWireMockMiddlewareOptions when settings are updated via admin interface [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1151](https://github.com/WireMock-Net/WireMock.Net/issues/1151) - MappingsToCSharpCode should use RegexMatcher when specified [bug]
|
||||
- [#1164](https://github.com/WireMock-Net/WireMock.Net/issues/1164) - WithParam not working. [bug]
|
||||
|
||||
# 1.6.1 (22 August 2024)
|
||||
- [#1160](https://github.com/WireMock-Net/WireMock.Net/pull/1160) - Use default timeout for Regex [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1159](https://github.com/WireMock-Net/WireMock.Net/issues/1159) - RegexMatchTimeoutException when trying to parse HTTP version [bug]
|
||||
|
||||
# 1.6.0 (16 August 2024)
|
||||
- [#1042](https://github.com/WireMock-Net/WireMock.Net/pull/1042) - Update + add fluent builder methods [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1109](https://github.com/WireMock-Net/WireMock.Net/pull/1109) - Add Aspire Extension [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1148](https://github.com/WireMock-Net/WireMock.Net/pull/1148) - Use Guid.TryParseExact with format "D" contributed by [StefH](https://github.com/StefH)
|
||||
- [#1157](https://github.com/WireMock-Net/WireMock.Net/pull/1157) - Fix FormUrlEncodedMatcher (MatchOperator.And) [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1158](https://github.com/WireMock-Net/WireMock.Net/pull/1158) - Allow setting Content-Length header on the response [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#720](https://github.com/WireMock-Net/WireMock.Net/issues/720) - Response Header Content-Length not available when call HEAD Method [feature]
|
||||
- [#1145](https://github.com/WireMock-Net/WireMock.Net/issues/1145) - Response is auto converting string to guid [bug]
|
||||
- [#1156](https://github.com/WireMock-Net/WireMock.Net/issues/1156) - FormUrlEncodedMatcher is not requiring to match all properties when MatchOperator.And [bug]
|
||||
|
||||
# 1.5.62 (27 July 2024)
|
||||
- [#1147](https://github.com/WireMock-Net/WireMock.Net/pull/1147) - Add FormUrlEncodedMatcher [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1143](https://github.com/WireMock-Net/WireMock.Net/issues/1143) - FormEncoded Request fails (404 Not Found) if key value pairs order in mapping is different from request body order [bug]
|
||||
@@ -17,9 +65,7 @@
|
||||
# 1.5.60 (09 July 2024)
|
||||
- [#1128](https://github.com/WireMock-Net/WireMock.Net/pull/1128) - Add Handlebars.Net.Helpers.Xslt [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1130](https://github.com/WireMock-Net/WireMock.Net/pull/1130) - Add AdminPath to WireMockServerSettings [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1131](https://github.com/WireMock-Net/WireMock.Net/pull/1131) - Add unit tests for AdminApiMappingBuilder [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1132](https://github.com/WireMock-Net/WireMock.Net/pull/1132) - Multipart Matcher Fix [bug] contributed by [rmeshksar](https://github.com/rmeshksar)
|
||||
- [#1133](https://github.com/WireMock-Net/WireMock.Net/pull/1133) - Add unit tests for AdminApiMappingBuilder_ [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1134](https://github.com/WireMock-Net/WireMock.Net/pull/1134) - Remove some files and folders [refactor] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1119](https://github.com/WireMock-Net/WireMock.Net/issues/1119) - Error in RequestMessageMultiPartMatcher [bug]
|
||||
- [#1121](https://github.com/WireMock-Net/WireMock.Net/issues/1121) - XML transformation [feature]
|
||||
@@ -104,7 +150,6 @@
|
||||
|
||||
# 1.5.42 (09 December 2023)
|
||||
- [#1023](https://github.com/WireMock-Net/WireMock.Net/pull/1023) - Fix Mapping[] for WireMock.Org REST API [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1029](https://github.com/WireMock-Net/WireMock.Net/pull/1029) - Add ResponseWithHandlebarsDateTimeTests [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1031](https://github.com/WireMock-Net/WireMock.Net/pull/1031) - Calling Reset also resets the scenarios [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1034](https://github.com/WireMock-Net/WireMock.Net/pull/1034) - Workaround for: Random.Generate Type="Long" [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1021](https://github.com/WireMock-Net/WireMock.Net/issues/1021) - GetAdminMappingsResult in WireMock.Org.Abstractions should contain list of mappings [bug]
|
||||
@@ -113,12 +158,9 @@
|
||||
# 1.5.41 (04 December 2023)
|
||||
- [#1012](https://github.com/WireMock-Net/WireMock.Net/pull/1012) - GraphQL - custom scalar support [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1018](https://github.com/WireMock-Net/WireMock.Net/pull/1018) - Add .NET 8 [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1020](https://github.com/WireMock-Net/WireMock.Net/pull/1020) - Add Github Action [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#984](https://github.com/WireMock-Net/WireMock.Net/issues/984) - GraphQL Schema validation with custom scalars [feature]
|
||||
|
||||
# 1.5.40 (07 November 2023)
|
||||
- [#1009](https://github.com/WireMock-Net/WireMock.Net/pull/1009) - Add more tests for JmesPathMatchers and StringUtils.ParseMatchOperator [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1010](https://github.com/WireMock-Net/WireMock.Net/pull/1010) - Add unit tests for HttpClient with WebProxy [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1011](https://github.com/WireMock-Net/WireMock.Net/pull/1011) - GraphQL - add support for standard scalar types in the schema [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1014](https://github.com/WireMock-Net/WireMock.Net/pull/1014) - FluentAssertions - WithBody and WithBodyAsJson and WithBodyAsBytes contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -130,7 +172,6 @@
|
||||
- [#1005](https://github.com/WireMock-Net/WireMock.Net/pull/1005) - Support for xml namespaces in XPathMatcher [feature] contributed by [cal-schleupen](https://github.com/cal-schleupen)
|
||||
|
||||
# 1.5.37 (27 September 2023)
|
||||
- [#998](https://github.com/WireMock-Net/WireMock.Net/pull/998) - Add JmesPathMatcher UnitTests [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1004](https://github.com/WireMock-Net/WireMock.Net/pull/1004) - Fix MappingModel to map IgnoreCase and RejectOnMatch for Headers, Cookies and Parameters [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#1003](https://github.com/WireMock-Net/WireMock.Net/issues/1003) - Store Mapping per POST request ignores "IgnoreCase" property of HeaderModel [bug]
|
||||
|
||||
@@ -142,7 +183,6 @@
|
||||
- [#1001](https://github.com/WireMock-Net/WireMock.Net/issues/1001) - SaveUnmatchedRequests stopped working [bug]
|
||||
|
||||
# 1.5.35 (19 August 2023)
|
||||
- [#992](https://github.com/WireMock-Net/WireMock.Net/pull/992) - Add extra unit test for WithParam multiple values comma [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#993](https://github.com/WireMock-Net/WireMock.Net/pull/993) - Update JSONPathMatcher.cs to cover the string path selection to a child contributed by [DayLightDancer](https://github.com/DayLightDancer)
|
||||
|
||||
# 1.5.34 (04 August 2023)
|
||||
@@ -168,7 +208,6 @@
|
||||
|
||||
# 1.5.30 (28 June 2023)
|
||||
- [#959](https://github.com/WireMock-Net/WireMock.Net/pull/959) - Fixed logic for FluentAssertions WithHeader [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#961](https://github.com/WireMock-Net/WireMock.Net/pull/961) - Add unit-test for Param MatcherModel LinqMatcher [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#962](https://github.com/WireMock-Net/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-Net/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)
|
||||
- [#958](https://github.com/WireMock-Net/WireMock.Net/issues/958) - [FluentAssertions] Should().HaveReceivedACall().WithHeader() only checks the first header with the matching key. [bug]
|
||||
@@ -189,7 +228,6 @@
|
||||
- [#945](https://github.com/WireMock-Net/WireMock.Net/issues/945) - Webhook logging [feature]
|
||||
|
||||
# 1.5.26 (25 May 2023)
|
||||
- [#938](https://github.com/WireMock-Net/WireMock.Net/pull/938) - Add more unitests for CSharpFormatter utils [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#939](https://github.com/WireMock-Net/WireMock.Net/pull/939) - WireMockMiddleware should use HandleRequestsSynchronously correctly [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#940](https://github.com/WireMock-Net/WireMock.Net/pull/940) - Code generator improvements contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||
- [#942](https://github.com/WireMock-Net/WireMock.Net/pull/942) - Add GetParameter method to IRequestMessage [feature] contributed by [StefH](https://github.com/StefH)
|
||||
@@ -238,7 +276,6 @@
|
||||
|
||||
# 1.5.17 (25 February 2023)
|
||||
- [#881](https://github.com/WireMock-Net/WireMock.Net/pull/881) - Add WithBodyAsJson builder method with accepts a Func [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#882](https://github.com/WireMock-Net/WireMock.Net/pull/882) - Add example code to test HTTP Status 400 and 500 [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#890](https://github.com/WireMock-Net/WireMock.Net/pull/890) - AdminApiMappingBuilder [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.5.16 (01 February 2023)
|
||||
@@ -254,7 +291,6 @@
|
||||
- [#871](https://github.com/WireMock-Net/WireMock.Net/pull/871) - Add UseWebhooksFireAndForget to Server ConvertMapping [bug] contributed by [ggradnig](https://github.com/ggradnig)
|
||||
- [#872](https://github.com/WireMock-Net/WireMock.Net/pull/872) - Fix unsubscribe from LogEntriesChanged event handler [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#875](https://github.com/WireMock-Net/WireMock.Net/pull/875) - Fix Self referencing loop detected for property [bug] contributed by [eseneckiy](https://github.com/eseneckiy)
|
||||
- [#877](https://github.com/WireMock-Net/WireMock.Net/pull/877) - Add unit test example for Transformer Handlebars String.Append String.Join [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#701](https://github.com/WireMock-Net/WireMock.Net/issues/701) - Allow to create MappingModel from c# to be able to configure local and remote mocks similarly [feature]
|
||||
- [#867](https://github.com/WireMock-Net/WireMock.Net/issues/867) - Can I build mappings with code and save them to JSON-file without starting server [feature]
|
||||
- [#870](https://github.com/WireMock-Net/WireMock.Net/issues/870) - Can not unsubscribe from LogEntriesChanged event. [bug]
|
||||
@@ -334,7 +370,6 @@
|
||||
|
||||
# 1.5.2 (24 July 2022)
|
||||
- [#769](https://github.com/WireMock-Net/WireMock.Net/pull/769) - Bump Microsoft.AspNetCore.Server.Kestrel.Core from 2.1.3 to 2.1.7 in /examples/WireMock.Net.StandAlone.Net461 [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||
- [#770](https://github.com/WireMock-Net/WireMock.Net/pull/770) - Added some more tests for JsonMatcher + refactored some code to use nullable [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#771](https://github.com/WireMock-Net/WireMock.Net/pull/771) - JsonPartialMatcher - support Regex [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.5.1 (08 July 2022)
|
||||
@@ -620,9 +655,6 @@
|
||||
- [#492](https://github.com/WireMock-Net/WireMock.Net/pull/492) - Mark FluentMockServer, FluentMockServerSettings, BlacklistedHeaders and BlacklistedCookies as obsolete [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#489](https://github.com/WireMock-Net/WireMock.Net/issues/489) - Change "blacklist" and "whitelist" terms [feature]
|
||||
|
||||
# 1.2.15 (19 July 2020)
|
||||
- [#485](https://github.com/WireMock-Net/WireMock.Net/pull/485) - Add fluent assertions for headers [test] contributed by [akamud](https://github.com/akamud)
|
||||
|
||||
# 1.2.14 (09 July 2020)
|
||||
- [#479](https://github.com/WireMock-Net/WireMock.Net/pull/479) - An OpenApi (swagger) parser to generate MappingModel or mapping.json file [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#482](https://github.com/WireMock-Net/WireMock.Net/pull/482) - Add PartialMatch to logging / logentries [feature] contributed by [StefH](https://github.com/StefH)
|
||||
@@ -923,7 +955,6 @@
|
||||
|
||||
# 1.0.4.21 (30 November 2018)
|
||||
- [#221](https://github.com/WireMock-Net/WireMock.Net/pull/221) - Update dependencies [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#229](https://github.com/WireMock-Net/WireMock.Net/pull/229) - Fix proxy tests [test] contributed by [StefH](https://github.com/StefH)
|
||||
- [#230](https://github.com/WireMock-Net/WireMock.Net/pull/230) - Add HandleBars Random functionality (#219) [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#231](https://github.com/WireMock-Net/WireMock.Net/pull/231) - Use RandomDataGenerator.Net 1.0.3.0 contributed by [StefH](https://github.com/StefH)
|
||||
- [#232](https://github.com/WireMock-Net/WireMock.Net/pull/232) - Add SonarLint checks [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.5.62</VersionPrefix>
|
||||
<VersionPrefix>1.6.6</VersionPrefix>
|
||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||
@@ -44,12 +44,12 @@
|
||||
</Choose>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2023.3.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||
<PackageReference Include="JetBrains.Annotations" Version="2024.2.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition=" '$(TargetFramework)' == 'net8.0' ">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.29.0.95321">
|
||||
<PackageReference Include="SonarAnalyzer.CSharp" Version="9.32.0.97167">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
rem https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
SET version=1.5.62
|
||||
SET version=1.6.6
|
||||
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels test question invalid doc duplicate example environment --version %version% --token %GH_TOKEN%
|
||||
|
||||
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels question invalid doc duplicate example environment --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%
|
||||
GitHubReleaseNotes --output PackageReleaseNotes.txt --skip-empty-releases --exclude-labels test question invalid doc duplicate example environment --template PackageReleaseNotes.template --version %version% --token %GH_TOKEN%
|
||||
@@ -1,5 +1,7 @@
|
||||
# 1.5.62 (27 July 2024)
|
||||
- #1147 Add FormUrlEncodedMatcher [feature]
|
||||
- #1143 FormEncoded Request fails (404 Not Found) if key value pairs order in mapping is different from request body order [bug]
|
||||
# 1.6.6 (01 October 2024)
|
||||
- #1185 Throw exception in case WithTransformer is used after WithBodyFromFile [bug]
|
||||
- #1187 Fix StaticMappingsPath in WireMockContainerBuilder [bug]
|
||||
- #1184 .WithBodyFromFile() + .WithTransformer(transformContentFromBodyAsFile: true) = empty string [bug]
|
||||
- #1186 WithMappings path is null on Build() call [bug]
|
||||
|
||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||
25
README.md
25
README.md
@@ -39,16 +39,21 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
||||
|
||||
| | Official | Preview [:information_source:](https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) |
|
||||
| - | - | - |
|
||||
| **WireMock.Net** | [](https://www.nuget.org/packages/WireMock.Net) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
|
||||
| **WireMock.Net.StandAlone** | [](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
|
||||
| **WireMock.Net.FluentAssertions** | [](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
|
||||
| **WireMock.Net.Matchers.CSharpCode** | [](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
|
||||
| **WireMock.Net.OpenApiParser** | [](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
|
||||
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
||||
| **WireMock.Net.xUnit** | [](https://www.nuget.org/packages/WireMock.Net.xUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
|
||||
| **WireMock.Net.Testcontainers** | [](https://www.nuget.org/packages/WireMock.Net.Testcontainers) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Testcontainers)
|
||||
| **WireMock.Net.Aspire** | [](https://www.nuget.org/packages/WireMock.Net.Aspire) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Aspire)
|
||||
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||
| **WireMock.Net** | [](https://www.nuget.org/packages/WireMock.Net) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net)
|
||||
| **WireMock.Net.StandAlone** | [](https://www.nuget.org/packages/WireMock.Net.StandAlone) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.StandAlone)
|
||||
| **WireMock.Net.Testcontainers** | [](https://www.nuget.org/packages/WireMock.Net.Testcontainers) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Testcontainers)
|
||||
| **WireMock.Net.Aspire** | [](https://www.nuget.org/packages/WireMock.Net.Aspire) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Aspire)
|
||||
| **WireMock.Net.AspNetCore.Middleware** | [](https://www.nuget.org/packages/WireMock.Net.AspNetCore.Middleware) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.AspNetCore.Middleware)
|
||||
| | | |
|
||||
| **WireMock.Net.FluentAssertions** | [](https://www.nuget.org/packages/WireMock.Net.FluentAssertions) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.FluentAssertions)
|
||||
| **WireMock.Net.xUnit** | [](https://www.nuget.org/packages/WireMock.Net.xUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.xUnit)
|
||||
| **WireMock.Net.TUnit** | [](https://www.nuget.org/packages/WireMock.Net.TUnit) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.TUnit)
|
||||
| | | |
|
||||
| **WireMock.Net.Matchers.CSharpCode** | [](https://www.nuget.org/packages/WireMock.Net.Matchers.CSharpCode) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.Matchers.CSharpCode)
|
||||
| **WireMock.Net.OpenApiParser** | [](https://www.nuget.org/packages/WireMock.Net.OpenApiParser) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.OpenApiParser)
|
||||
| | | |
|
||||
| **WireMock.Net.RestClient** | [](https://www.nuget.org/packages/WireMock.Net.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Net.RestClient)
|
||||
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||
|
||||
|
||||
## :memo: Development
|
||||
|
||||
@@ -131,6 +131,18 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Aspire.TestApp
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AspireApp1.AppHostOriginal", "examples-Aspire\AspireApp1.AppHostOriginal\AspireApp1.AppHostOriginal.csproj", "{C9210DA3-F390-4598-8512-349A473FE9C9}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnit", "src\WireMock.Net.TUnit\WireMock.Net.TUnit.csproj", "{91024A93-848F-4A02-AF53-5EBE5834E23C}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.TUnitTests", "test\WireMock.Net.TUnitTests\WireMock.Net.TUnitTests.csproj", "{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.WebApplication", "examples\WireMock.Net.WebApplication\WireMock.Net.WebApplication.csproj", "{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}"
|
||||
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}"
|
||||
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}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -317,6 +329,30 @@ Global
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A13}.Release|Any CPU.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}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6B30AA9F-DA04-4EB5-B03C-45A8EF272ECE}.Release|Any CPU.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.Build.0 = Debug|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{A5FEF4F7-7DA2-4962-89A8-16BA942886E5}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -369,6 +405,12 @@ Global
|
||||
{CE602F57-FEF8-4559-A9E0-6200BE1BF398} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||
{F1B5999D-D22E-48A6-AB86-18A7876BD32E} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||
{C9210DA3-F390-4598-8512-349A473FE9C9} = {AD474543-0715-49F2-A284-936B060BF736}
|
||||
{91024A93-848F-4A02-AF53-5EBE5834E23C} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{4CD237F7-B616-46B8-872F-E49B4BBB3EAE} = {0BB8B634-407A-4610-A91F-11586990767A}
|
||||
{E72ADFAB-4B42-439E-B1EE-C06E504B35D2} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{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}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -33,6 +33,7 @@
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Guids/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heyenrath/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Levenstein/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=openapi/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Pacticipant/@EntryIndexedValue">True</s:Boolean>
|
||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=protobuf/@EntryIndexedValue">True</s:Boolean>
|
||||
|
||||
@@ -38,7 +38,7 @@ jobs:
|
||||
|
||||
# See: https://docs.sonarsource.com/sonarcloud/enriching/test-coverage/dotnet-test-coverage
|
||||
- script: |
|
||||
dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.dotnet.excludeTestProjects=true /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true
|
||||
dotnet sonarscanner begin /k:"WireMock-Net_WireMock.Net" /o:"wiremock-net" /d:sonar.branch.name=$(Build.SourceBranchName) /d:sonar.host.url="https://sonarcloud.io" /d:sonar.token="$(SONAR_TOKEN)" /d:sonar.pullrequest.provider=github /d:sonar.cs.vscoveragexml.reportsPaths=**/wiremock-coverage-*.xml /d:sonar.verbose=true
|
||||
displayName: 'Begin analysis on SonarCloud'
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
|
||||
@@ -52,9 +52,16 @@ jobs:
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
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-1.xml"
|
||||
dotnet-coverage collect "dotnet test ./test/WireMock.Net.Aspire.Tests/WireMock.Net.Aspire.Tests.csproj --configuration Debug --no-build" -f xml -o "wiremock-coverage-2.xml"
|
||||
displayName: 'Execute Unit Tests with Coverage'
|
||||
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 ./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 ./test/WireMock.Net.Middleware.Tests/WireMock.Net.Middleware.Tests.csproj --configuration Debug --no-build --framework net8.0" -f xml -o "wiremock-coverage-middleware.xml"
|
||||
displayName: 'Execute WireMock.Net.Tests with Coverage'
|
||||
|
||||
- task: CmdLine@2
|
||||
inputs:
|
||||
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"
|
||||
displayName: 'Execute WireMock.Net.Aspire.Tests with Coverage'
|
||||
|
||||
- task: CmdLine@2
|
||||
displayName: 'Merge coverage files'
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -14,7 +14,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -137,7 +137,6 @@ message HelloReply {
|
||||
public static void Run()
|
||||
{
|
||||
RunOnLocal();
|
||||
return;
|
||||
|
||||
var mappingBuilder = new MappingBuilder();
|
||||
mappingBuilder
|
||||
@@ -308,17 +307,6 @@ message HelloReply {
|
||||
.RespondWith(Response.Create()
|
||||
.WithBody("GraphQL is ok")
|
||||
);
|
||||
|
||||
//server
|
||||
// .AddGraphQLSchema("my-graphql", TestSchema, customScalars)
|
||||
// .Given(Request.Create()
|
||||
// .WithPath("/graphql2")
|
||||
// .UsingPost()
|
||||
// )
|
||||
// .WithGraphQLSchema("my-graphql")
|
||||
// .RespondWith(Response.Create()
|
||||
// .WithBody("GraphQL is ok")
|
||||
// );
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
@@ -377,6 +365,15 @@ message HelloReply {
|
||||
.WithHeader("Content-Type", "text/plain")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingHead()
|
||||
.WithPath("/cl")
|
||||
)
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Length", "42")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("GET")
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Runtime.InteropServices;
|
||||
using Newtonsoft.Json;
|
||||
using Testcontainers.MsSql;
|
||||
using WireMock.Net.Testcontainers;
|
||||
|
||||
namespace WireMock.Net.TestcontainersExample;
|
||||
@@ -10,17 +10,128 @@ internal class Program
|
||||
{
|
||||
private static async Task Main(string[] args)
|
||||
{
|
||||
var container = new WireMockContainerBuilder()
|
||||
var original = Console.ForegroundColor;
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Yellow;
|
||||
Console.WriteLine("Linux");
|
||||
await TestAsync("sheyenrath/wiremock.net:1.6.5");
|
||||
await Task.Delay(1_000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.White;
|
||||
Console.WriteLine("Linux Alpine");
|
||||
await TestAsync("sheyenrath/wiremock.net-alpine:1.6.5");
|
||||
await Task.Delay(1_000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Gray;
|
||||
Console.WriteLine("WithLinux");
|
||||
await TestAsync("WithLinux");
|
||||
await Task.Delay(1_000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Cyan;
|
||||
Console.WriteLine("Windows");
|
||||
await TestAsync("sheyenrath/wiremock.net-windows:1.6.5");
|
||||
await Task.Delay(1_000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Blue;
|
||||
Console.WriteLine("WithWindows");
|
||||
await TestAsync("WithWindows");
|
||||
await Task.Delay(1_000);
|
||||
}
|
||||
catch (Exception e)
|
||||
{
|
||||
Console.WriteLine(e);
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
Console.ForegroundColor = ConsoleColor.Red;
|
||||
Console.WriteLine("Automatic");
|
||||
await TestAsync();
|
||||
}
|
||||
finally
|
||||
{
|
||||
Console.ForegroundColor = original;
|
||||
}
|
||||
}
|
||||
|
||||
private static async Task TestAsync(string? image = null)
|
||||
{
|
||||
var mappingsPath = Path.Combine(Directory.GetCurrentDirectory(), "..", "..", "..", "..", "WireMock.Net.Console.NET6", "__admin", "mappings");
|
||||
|
||||
var builder = new WireMockContainerBuilder()
|
||||
.WithAdminUserNameAndPassword("x", "y")
|
||||
.WithMappings(@"C:\Dev\GitHub\WireMock.Net\examples\WireMock.Net.Console.NET6\__admin\mappings")
|
||||
.WithMappings(mappingsPath)
|
||||
.WithWatchStaticMappings(true)
|
||||
.WithAutoRemove(true)
|
||||
.WithCleanUp(true)
|
||||
.Build();
|
||||
.WithCleanUp(true);
|
||||
|
||||
await container.StartAsync().ConfigureAwait(false);
|
||||
if (image != null)
|
||||
{
|
||||
builder = image switch
|
||||
{
|
||||
"WithWindows" => builder.WithWindowsImage(),
|
||||
"WithLinux" => builder.WithLinuxImage(),
|
||||
_ => builder.WithImage(image)
|
||||
};
|
||||
}
|
||||
|
||||
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1)).ConfigureAwait(false);
|
||||
var container = builder.Build();
|
||||
|
||||
await container.StartAsync();
|
||||
|
||||
await Task.Delay(1_000);
|
||||
|
||||
var logs = await container.GetLogsAsync(DateTime.Now.AddDays(-1));
|
||||
Console.WriteLine("logs = " + logs.Stdout);
|
||||
|
||||
var restEaseApiClient = container.CreateWireMockAdminClient();
|
||||
@@ -36,10 +147,5 @@ internal class Program
|
||||
Console.WriteLine("result = " + result);
|
||||
|
||||
await container.StopAsync();
|
||||
|
||||
var sql = new MsSqlBuilder()
|
||||
.WithAutoRemove(true)
|
||||
.WithCleanUp(true)
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
@@ -1,24 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Testcontainers.MsSql" Version="3.6.0" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Testcontainers\WireMock.Net.Testcontainers.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Update="873d495f-940e-4b86-a1f4-4f0fc7be8b8b.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
56
examples/WireMock.Net.WebApplication/Program.cs
Normal file
56
examples/WireMock.Net.WebApplication/Program.cs
Normal file
@@ -0,0 +1,56 @@
|
||||
using WireMock.Net.AspNetCore.Middleware;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
if (!builder.Environment.IsProduction())
|
||||
{
|
||||
builder.Services.AddWireMockService(server =>
|
||||
{
|
||||
server.Given(Request.Create()
|
||||
.WithPath("/test1")
|
||||
.UsingAnyMethod()
|
||||
).RespondWith(Response.Create()
|
||||
.WithBody("1 : WireMock.Net !")
|
||||
);
|
||||
|
||||
server.Given(Request.Create()
|
||||
.WithPath("/test2")
|
||||
.UsingAnyMethod()
|
||||
).RespondWith(Response.Create()
|
||||
.WithBody("2 : WireMock.Net !")
|
||||
);
|
||||
}, true);
|
||||
}
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGet("/weatherforecast", async (HttpClient client) =>
|
||||
{
|
||||
var result = await client.GetStringAsync("https://real-api:12345/test1");
|
||||
|
||||
return Enumerable.Range(1, 3).Select(index =>
|
||||
new WeatherForecast
|
||||
(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
result
|
||||
));
|
||||
});
|
||||
|
||||
app.MapGet("/weatherforecast2", async (IHttpClientFactory factory) =>
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
var result = await client.GetStringAsync("https://real-api:12345/test2");
|
||||
|
||||
return Enumerable.Range(1, 3).Select(index =>
|
||||
new WeatherForecast
|
||||
(
|
||||
DateOnly.FromDateTime(DateTime.Now.AddDays(index)),
|
||||
Random.Shared.Next(-20, 55),
|
||||
result
|
||||
));
|
||||
});
|
||||
|
||||
await app.RunAsync();
|
||||
@@ -0,0 +1,41 @@
|
||||
{
|
||||
"$schema": "http://json.schemastore.org/launchsettings.json",
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:57375",
|
||||
"sslPort": 44333
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"http": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "weatherforecast",
|
||||
"applicationUrl": "http://localhost:5112",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"https": {
|
||||
"commandName": "Project",
|
||||
"dotnetRunMessages": true,
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "weatherforecast",
|
||||
"applicationUrl": "https://localhost:7021;http://localhost:5112",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "weatherforecast",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
4
examples/WireMock.Net.WebApplication/WeatherForecast.cs
Normal file
4
examples/WireMock.Net.WebApplication/WeatherForecast.cs
Normal file
@@ -0,0 +1,4 @@
|
||||
record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary)
|
||||
{
|
||||
public int TemperatureF => 32 + (int)(TemperatureC / 0.5556);
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,8 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
}
|
||||
}
|
||||
9
examples/WireMock.Net.WebApplication/appsettings.json
Normal file
9
examples/WireMock.Net.WebApplication/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
25
src/WireMock.Net.Abstractions/Models/IBodyDataExtensions.cs
Normal file
25
src/WireMock.Net.Abstractions/Models/IBodyDataExtensions.cs
Normal file
@@ -0,0 +1,25 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Types;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace WireMock.Util;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public static class IBodyDataExtensions
|
||||
{
|
||||
public static BodyType GetBodyType(this IBodyData bodyData)
|
||||
{
|
||||
if (bodyData.DetectedBodyTypeFromContentType is not null and not BodyType.None)
|
||||
{
|
||||
return bodyData.DetectedBodyTypeFromContentType.Value;
|
||||
}
|
||||
|
||||
if (bodyData.DetectedBodyType is not null and not BodyType.None)
|
||||
{
|
||||
return bodyData.DetectedBodyType.Value;
|
||||
}
|
||||
|
||||
return BodyType.None;
|
||||
}
|
||||
}
|
||||
9
src/WireMock.Net.AspNetCore.Middleware/AppConstants.cs
Normal file
9
src/WireMock.Net.AspNetCore.Middleware/AppConstants.cs
Normal file
@@ -0,0 +1,9 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware;
|
||||
|
||||
internal static class AppConstants
|
||||
{
|
||||
internal const string HEADER_REDIRECT = "X-WireMock-Redirect";
|
||||
internal const string HEADER_RESPONSE_DELAY = "X-WireMock-Response-Delay";
|
||||
}
|
||||
@@ -0,0 +1,72 @@
|
||||
using Microsoft.AspNetCore.Http;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Stef.Validation;
|
||||
using WireMock.Server;
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
|
||||
|
||||
/// <summary>
|
||||
/// DelegatingHandler that takes requests made via the <see cref="HttpClient"/>
|
||||
/// and routes them to the <see cref="WireMockServer"/>.
|
||||
/// </summary>
|
||||
internal class WireMockDelegationHandler : DelegatingHandler
|
||||
{
|
||||
private readonly ILogger<WireMockDelegationHandler> _logger;
|
||||
private readonly WireMockServerInstance _server;
|
||||
private readonly IHttpContextAccessor _httpContextAccessor;
|
||||
private readonly WireMockDelegationHandlerSettings _settings;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance of <see cref="WireMockDelegationHandler"/>
|
||||
/// </summary>
|
||||
public WireMockDelegationHandler(
|
||||
ILogger<WireMockDelegationHandler> logger,
|
||||
WireMockServerInstance server,
|
||||
IHttpContextAccessor httpContextAccessor,
|
||||
WireMockDelegationHandlerSettings settings
|
||||
)
|
||||
{
|
||||
_server = Guard.NotNull(server);
|
||||
_httpContextAccessor = Guard.NotNull(httpContextAccessor);
|
||||
_logger = Guard.NotNull(logger);
|
||||
_settings = Guard.NotNull(settings);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override async Task<HttpResponseMessage> SendAsync(HttpRequestMessage request, CancellationToken cancellationToken)
|
||||
{
|
||||
Guard.NotNull(request);
|
||||
Guard.NotNull(_httpContextAccessor.HttpContext);
|
||||
|
||||
if (_settings.AlwaysRedirect || IsWireMockRedirectHeaderSetToTrue())
|
||||
{
|
||||
_logger.LogDebug("Redirecting request to WireMock server");
|
||||
if (_server.Instance?.Url != null)
|
||||
{
|
||||
request.RequestUri = new Uri(_server.Instance.Url + request.RequestUri!.PathAndQuery);
|
||||
}
|
||||
}
|
||||
|
||||
if (TryGetDelayHeaderValue(out var delayInMs))
|
||||
{
|
||||
await Task.Delay(delayInMs, cancellationToken);
|
||||
}
|
||||
|
||||
return await base.SendAsync(request, cancellationToken);
|
||||
}
|
||||
|
||||
private bool IsWireMockRedirectHeaderSetToTrue()
|
||||
{
|
||||
return
|
||||
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_REDIRECT, out var values) &&
|
||||
bool.TryParse(values.ToString(), out var shouldRedirectToWireMock) && shouldRedirectToWireMock;
|
||||
}
|
||||
|
||||
private bool TryGetDelayHeaderValue(out int delayInMs)
|
||||
{
|
||||
delayInMs = 0;
|
||||
return
|
||||
_httpContextAccessor.HttpContext!.Request.Headers.TryGetValue(AppConstants.HEADER_RESPONSE_DELAY, out var values) &&
|
||||
int.TryParse(values.ToString(), out delayInMs);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
|
||||
|
||||
internal class WireMockDelegationHandlerSettings
|
||||
{
|
||||
public bool AlwaysRedirect { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,52 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Http;
|
||||
using Stef.Validation;
|
||||
using WireMock.Net.AspNetCore.Middleware.HttpDelegatingHandler;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// Extension methods for <see cref="IServiceCollection"/>.
|
||||
/// </summary>
|
||||
public static class ServiceCollectionExtensions
|
||||
{
|
||||
/// <summary>
|
||||
/// Adds all the components necessary to run WireMock.Net as a background service.
|
||||
/// </summary>
|
||||
public static IServiceCollection AddWireMockService(
|
||||
this IServiceCollection services,
|
||||
Action<WireMockServer> configure,
|
||||
bool alwaysRedirectToWireMock = true,
|
||||
WireMockServerSettings? settings = null
|
||||
)
|
||||
{
|
||||
Guard.NotNull(services);
|
||||
Guard.NotNull(configure);
|
||||
|
||||
services.AddTransient<WireMockDelegationHandler>();
|
||||
|
||||
services.AddSingleton(new WireMockServerInstance(configure, settings));
|
||||
|
||||
services.AddSingleton(new WireMockDelegationHandlerSettings
|
||||
{
|
||||
AlwaysRedirect = alwaysRedirectToWireMock
|
||||
});
|
||||
|
||||
services.AddHostedService<WireMockBackgroundService>();
|
||||
services.AddHttpClient();
|
||||
services.AddHttpContextAccessor();
|
||||
services.ConfigureAll<HttpClientFactoryOptions>(options =>
|
||||
{
|
||||
options.HttpMessageHandlerBuilderActions.Add(builder =>
|
||||
{
|
||||
builder.AdditionalHandlers.Add(builder.Services.GetRequiredService<WireMockDelegationHandler>());
|
||||
});
|
||||
});
|
||||
|
||||
return services;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Description>Middleware which can be used to host WireMock.Net as a Middleware background process in a AspNetCore WebApplication</Description>
|
||||
<AssemblyTitle>WireMock.Net.AspNetCore.Middleware</AssemblyTitle>
|
||||
<Authors>Matthew Yost;Stef Heyenrath</Authors>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.AspNetCore.Middleware</AssemblyName>
|
||||
<PackageId>WireMock.Net.AspNetCore.Middleware</PackageId>
|
||||
<PackageTags>dotnet;middleware;wiremock;service;webapplication;aspnetcore</PackageTags>
|
||||
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A13}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
<PackageIcon>WireMock.Net-LogoAspire.png</PackageIcon>
|
||||
<ApplicationIcon>../../resources/WireMock.Net-LogoAspire.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="../../resources/WireMock.Net-Logo.png" />
|
||||
<None Include="../../resources/WireMock.Net-LogoAspire.png" Pack="true" PackagePath="" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection.Abstractions" Version="8.0.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,39 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Stef.Validation;
|
||||
using WireMock.Server;
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// A <see cref="BackgroundService"/> used to start/stop the <see cref="WireMockServer"/>
|
||||
/// </summary>
|
||||
internal class WireMockBackgroundService : BackgroundService
|
||||
{
|
||||
private readonly WireMockServerInstance _serverInstance;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new <see cref="BackgroundService"/> using an instance
|
||||
/// of <see cref="WireMockServerInstance"/>
|
||||
/// </summary>
|
||||
/// <param name="serverInstance"></param>
|
||||
public WireMockBackgroundService(WireMockServerInstance serverInstance)
|
||||
{
|
||||
_serverInstance = Guard.NotNull(serverInstance);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override Task ExecuteAsync(CancellationToken stoppingToken)
|
||||
{
|
||||
_serverInstance.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_serverInstance.Stop();
|
||||
return base.StopAsync(cancellationToken);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,49 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Stef.Validation;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.AspNetCore.Middleware;
|
||||
|
||||
/// <summary>
|
||||
/// WireMockServer Instance object
|
||||
/// </summary>
|
||||
internal class WireMockServerInstance
|
||||
{
|
||||
private readonly Action<WireMockServer> _configureAction;
|
||||
private readonly WireMockServerSettings? _settings;
|
||||
|
||||
/// <summary>
|
||||
/// Creates a new instance and provides ability to add configuration
|
||||
/// for the start method of <see cref="WireMockServer"/>
|
||||
/// </summary>
|
||||
public WireMockServerInstance(Action<WireMockServer> configure, WireMockServerSettings? settings = null)
|
||||
{
|
||||
_configureAction = Guard.NotNull(configure);
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Instance accessor for the <see cref="WireMockServer" />
|
||||
/// </summary>
|
||||
public WireMockServer? Instance { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Configures and starts <see cref="WireMockServer"/> instance for use.
|
||||
/// </summary>
|
||||
public void Start()
|
||||
{
|
||||
Instance = _settings != null ? WireMockServer.Start(_settings) : WireMockServer.Start();
|
||||
|
||||
_configureAction.Invoke(Instance);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Stops the <see cref="WireMockServer"/>
|
||||
/// </summary>
|
||||
public void Stop()
|
||||
{
|
||||
Instance?.Stop();
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Version>0.0.1-preview-05</Version>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Description>Aspire extension to start a WireMock.Net server to stub an api.</Description>
|
||||
<AssemblyTitle>WireMock.Net.Aspire</AssemblyTitle>
|
||||
@@ -36,8 +35,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting" Version="8.0.0" />
|
||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="8.0.0" PrivateAssets="All" />
|
||||
<PackageReference Include="Aspire.Hosting" Version="8.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -10,6 +10,7 @@ using Stef.Validation;
|
||||
using WireMock.Exceptions;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -92,6 +93,17 @@ internal class CSharpCodeMatcher : ICSharpCodeMatcher
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
private bool IsMatch(dynamic input, string pattern)
|
||||
{
|
||||
var isMatchWithString = input is string;
|
||||
|
||||
@@ -43,7 +43,7 @@
|
||||
</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.13" />
|
||||
<PackageReference Include="CS-Script" Version="4.8.17" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
80
src/WireMock.Net.TUnit/TUnitWireMockLogger.cs
Normal file
80
src/WireMock.Net.TUnit/TUnitWireMockLogger.cs
Normal file
@@ -0,0 +1,80 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using TUnit.Core.Logging;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
|
||||
namespace WireMock.Net.TUnit;
|
||||
|
||||
/// <summary>
|
||||
/// When using TUnit, this class enables to log the output from WireMock.Net to the <see cref="TUnitLogger"/>.
|
||||
/// </summary>
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public sealed class TUnitWireMockLogger : IWireMockLogger
|
||||
{
|
||||
private readonly TUnitLogger _tUnitLogger;
|
||||
|
||||
/// <summary>
|
||||
/// Create a new instance on the <see cref="TUnitWireMockLogger"/>.
|
||||
/// </summary>
|
||||
/// <param name="tUnitLogger">Represents a class which can be used to provide test output.</param>
|
||||
public TUnitWireMockLogger(TUnitLogger tUnitLogger)
|
||||
{
|
||||
_tUnitLogger = Guard.NotNull(tUnitLogger);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Debug(string formatString, params object[] args)
|
||||
{
|
||||
_tUnitLogger.LogDebug(Format("Debug", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Info(string formatString, params object[] args)
|
||||
{
|
||||
_tUnitLogger.LogInformation(Format("Info", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Warn(string formatString, params object[] args)
|
||||
{
|
||||
_tUnitLogger.LogWarning(Format("Warning", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Error(string formatString, params object[] args)
|
||||
{
|
||||
_tUnitLogger.LogError(Format("Error", formatString, args));
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void Error(string formatString, Exception exception)
|
||||
{
|
||||
_tUnitLogger.LogError(Format("Error", formatString, exception.Message), exception);
|
||||
|
||||
if (exception is AggregateException ae)
|
||||
{
|
||||
ae.Handle(ex =>
|
||||
{
|
||||
_tUnitLogger.LogError(Format("Error", "Exception {0}", ex.Message), exception);
|
||||
return true;
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||
{
|
||||
var message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
_tUnitLogger.LogDebug(Format("DebugRequestResponse", "Admin[{0}] {1}", isAdminRequest, message));
|
||||
}
|
||||
|
||||
private static string Format(string level, string formatString, params object[] args)
|
||||
{
|
||||
var message = args.Length > 0 ? string.Format(formatString, args) : formatString;
|
||||
return $"{DateTime.UtcNow} [{level}] : {message}";
|
||||
}
|
||||
}
|
||||
38
src/WireMock.Net.TUnit/WireMock.Net.TUnit.csproj
Normal file
38
src/WireMock.Net.TUnit/WireMock.Net.TUnit.csproj
Normal file
@@ -0,0 +1,38 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Description>Some extensions for TUnit (TUnitLogger)</Description>
|
||||
<AssemblyTitle>WireMock.Net.TUnit</AssemblyTitle>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net8.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.TUnit</AssemblyName>
|
||||
<RootNamespace>WireMock.Net.Tunit</RootNamespace>
|
||||
<PackageId>WireMock.Net.TUnit</PackageId>
|
||||
<PackageTags>tdd;wiremock;test;unittest;TUnit</PackageTags>
|
||||
<ProjectGuid>{0DE0954F-8C00-4E8D-B94A-4361FC1CB34A}</ProjectGuid>
|
||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||
<PackageReference Include="TUnit.Core" Version="0.1.817" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -28,7 +28,7 @@
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||
<PackageReference Include="Testcontainers" Version="[3.9.0]" />
|
||||
<PackageReference Include="Testcontainers" Version="3.10.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
using DotNet.Testcontainers.Configurations;
|
||||
@@ -16,6 +17,8 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
||||
|
||||
public string? Password { get; }
|
||||
|
||||
public string? StaticMappingsPath { get; private set; }
|
||||
|
||||
public bool HasBasicAuthentication => !string.IsNullOrEmpty(Username) && !string.IsNullOrEmpty(Password);
|
||||
|
||||
public WireMockConfiguration(string? username = null, string? password = null)
|
||||
@@ -61,5 +64,17 @@ public sealed class WireMockConfiguration : ContainerConfiguration
|
||||
{
|
||||
Username = BuildConfiguration.Combine(oldValue.Username, newValue.Username);
|
||||
Password = BuildConfiguration.Combine(oldValue.Password, newValue.Password);
|
||||
StaticMappingsPath = BuildConfiguration.Combine(oldValue.StaticMappingsPath, newValue.StaticMappingsPath);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Set the StaticMappingsPath.
|
||||
/// </summary>
|
||||
/// <param name="path">The path which contains the StaticMappings.</param>
|
||||
/// <returns><see cref="WireMockConfiguration"/> </returns>
|
||||
public WireMockConfiguration WithStaticMappingsPath(string path)
|
||||
{
|
||||
StaticMappingsPath = path;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Threading.Tasks;
|
||||
using Docker.DotNet.Models;
|
||||
using DotNet.Testcontainers.Builders;
|
||||
@@ -17,15 +18,14 @@ namespace WireMock.Net.Testcontainers;
|
||||
/// </summary>
|
||||
public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContainerBuilder, WireMockContainer, WireMockConfiguration>
|
||||
{
|
||||
private readonly Dictionary<bool, ContainerInfo> _info = new()
|
||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||
private readonly Dictionary<OSPlatform, ContainerInfo> _info = new()
|
||||
{
|
||||
{ false, new ContainerInfo("sheyenrath/wiremock.net:latest", "/app/__admin/mappings") },
|
||||
{ true, new ContainerInfo("sheyenrath/wiremock.net-windows:latest", @"c:\app\__admin\mappings") }
|
||||
{ OSPlatform.Linux, new ContainerInfo("sheyenrath/wiremock.net-alpine", "/app/__admin/mappings") },
|
||||
{ OSPlatform.Windows, new ContainerInfo("sheyenrath/wiremock.net-windows", @"c:\app\__admin\mappings") }
|
||||
};
|
||||
|
||||
private const string DefaultLogger = "WireMockConsoleLogger";
|
||||
|
||||
private readonly Lazy<Task<bool>> _isWindowsAsLazy = new(async () =>
|
||||
private readonly Lazy<Task<OSPlatform>> _getOSAsLazy = new(async () =>
|
||||
{
|
||||
if (TestcontainersSettings.OS.DockerEndpointAuthConfig == null)
|
||||
{
|
||||
@@ -36,9 +36,11 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
using var dockerClient = dockerClientConfig.CreateClient();
|
||||
|
||||
var version = await dockerClient.System.GetVersionAsync();
|
||||
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) > -1;
|
||||
return version.Os.IndexOf("Windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
||||
});
|
||||
|
||||
private OSPlatform? _imageOS;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="ContainerBuilder" /> class.
|
||||
/// </summary>
|
||||
@@ -48,14 +50,36 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically set the correct image (Linux or Windows) for WireMock which to create the container.
|
||||
/// Automatically use the correct image for WireMock.
|
||||
/// For Linux this is "sheyenrath/wiremock.net-alpine:latest"
|
||||
/// For Windows this is "sheyenrath/wiremock.net-windows:latest"
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithImage()
|
||||
{
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
return WithImage(_info[isWindows].Image);
|
||||
_imageOS ??= _getOSAsLazy.Value.GetAwaiter().GetResult();
|
||||
return WithImage(_imageOS.Value);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically use a Linux image for WireMock. This is "sheyenrath/wiremock.net-alpine:latest"
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithLinuxImage()
|
||||
{
|
||||
return WithImage(OSPlatform.Linux);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Automatically use a Windows image for WireMock. This is "sheyenrath/wiremock.net-windows:latest"
|
||||
/// </summary>
|
||||
/// <returns>A configured instance of <see cref="WireMockContainerBuilder"/></returns>
|
||||
[PublicAPI]
|
||||
public WireMockContainerBuilder WithWindowsImage()
|
||||
{
|
||||
return WithImage(OSPlatform.Windows);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -120,11 +144,9 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
{
|
||||
Guard.NotNullOrEmpty(path);
|
||||
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
|
||||
return WithReadStaticMappings()
|
||||
.WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}")
|
||||
.WithBindMount(path, _info[isWindows].MappingsPath);
|
||||
return Merge(DockerResourceConfiguration, DockerResourceConfiguration.WithStaticMappingsPath(path))
|
||||
.WithReadStaticMappings()
|
||||
.WithCommand($"--WatchStaticMappingsInSubdirectories {includeSubDirectories}");
|
||||
}
|
||||
|
||||
private WireMockContainerBuilder(WireMockConfiguration dockerResourceConfiguration) : base(dockerResourceConfiguration)
|
||||
@@ -138,9 +160,33 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
/// <inheritdoc />
|
||||
public override WireMockContainer Build()
|
||||
{
|
||||
Validate();
|
||||
var builder = this;
|
||||
|
||||
return new WireMockContainer(DockerResourceConfiguration);
|
||||
// In case no image has been set, set the image using internal logic.
|
||||
if (DockerResourceConfiguration.Image == null)
|
||||
{
|
||||
builder = WithImage();
|
||||
}
|
||||
|
||||
// In case the _imageOS is not set, determine it from the Image FullName.
|
||||
if (_imageOS == null)
|
||||
{
|
||||
if (builder.DockerResourceConfiguration.Image.FullName.IndexOf("wiremock.net", StringComparison.OrdinalIgnoreCase) < 0)
|
||||
{
|
||||
throw new InvalidOperationException();
|
||||
}
|
||||
|
||||
_imageOS = builder.DockerResourceConfiguration.Image.FullName.IndexOf("windows", StringComparison.OrdinalIgnoreCase) >= 0 ? OSPlatform.Windows : OSPlatform.Linux;
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(builder.DockerResourceConfiguration.StaticMappingsPath))
|
||||
{
|
||||
builder = builder.WithBindMount(builder.DockerResourceConfiguration.StaticMappingsPath, _info[_imageOS.Value].MappingsPath);
|
||||
}
|
||||
|
||||
builder.Validate();
|
||||
|
||||
return new WireMockContainer(builder.DockerResourceConfiguration);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -148,14 +194,7 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
{
|
||||
var builder = base.Init();
|
||||
|
||||
// In case no image has been set, set the image using internal logic.
|
||||
if (builder.DockerResourceConfiguration.Image == null)
|
||||
{
|
||||
builder = builder.WithImage();
|
||||
}
|
||||
|
||||
var isWindows = _isWindowsAsLazy.Value.GetAwaiter().GetResult();
|
||||
var waitForContainerOS = isWindows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
||||
var waitForContainerOS = _imageOS == OSPlatform.Windows ? Wait.ForWindowsContainer() : Wait.ForUnixContainer();
|
||||
return builder
|
||||
.WithPortBinding(WireMockContainer.ContainerPort, true)
|
||||
.WithCommand($"--WireMockLogger {DefaultLogger}")
|
||||
@@ -179,4 +218,10 @@ public sealed class WireMockContainerBuilder : ContainerBuilder<WireMockContaine
|
||||
{
|
||||
return new WireMockContainerBuilder(new WireMockConfiguration(oldValue, newValue));
|
||||
}
|
||||
|
||||
private WireMockContainerBuilder WithImage(OSPlatform os)
|
||||
{
|
||||
_imageOS = os;
|
||||
return WithImage(_info[os].Image);
|
||||
}
|
||||
}
|
||||
@@ -73,8 +73,6 @@ public sealed class TestOutputHelperWireMockLogger : IWireMockLogger
|
||||
|
||||
private static string Format(string level, string formatString, params object[] args)
|
||||
{
|
||||
Guard.NotNull(formatString);
|
||||
|
||||
var message = args.Length > 0 ? string.Format(formatString, args) : formatString;
|
||||
return $"{DateTime.UtcNow} [{level}] : {message}";
|
||||
}
|
||||
|
||||
@@ -10,6 +10,7 @@ using Microsoft.IdentityModel.Protocols;
|
||||
using Microsoft.IdentityModel.Protocols.OpenIdConnect;
|
||||
using Microsoft.IdentityModel.Tokens;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Models;
|
||||
|
||||
@@ -41,7 +42,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
return EmptyArray<AnyOf<string, StringPattern>>.Value;
|
||||
}
|
||||
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
public MatchOperator MatchOperator => MatchOperator.Or;
|
||||
|
||||
public MatchResult IsMatch(string? input)
|
||||
{
|
||||
@@ -50,7 +51,7 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
return MatchScores.Mismatch;
|
||||
}
|
||||
|
||||
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase);
|
||||
var token = Regex.Replace(input, BearerPrefix, string.Empty, RegexOptions.IgnoreCase, WireMockConstants.DefaultRegexTimeout);
|
||||
|
||||
try
|
||||
{
|
||||
@@ -75,5 +76,11 @@ internal class AzureADAuthenticationMatcher : IStringMatcher
|
||||
return new MatchResult(MatchScores.Mismatch, ex);
|
||||
}
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetCSharpCodeArguments()
|
||||
{
|
||||
throw new NotImplementedException();
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -6,12 +6,9 @@ using WireMock.Matchers;
|
||||
|
||||
namespace WireMock.Authentication;
|
||||
|
||||
internal class BasicAuthenticationMatcher : RegexMatcher
|
||||
internal class BasicAuthenticationMatcher(string username, string password)
|
||||
: RegexMatcher(BuildPattern(username, password))
|
||||
{
|
||||
public BasicAuthenticationMatcher(string username, string password) : base(BuildPattern(username, password))
|
||||
{
|
||||
}
|
||||
|
||||
public override string Name => nameof(BasicAuthenticationMatcher);
|
||||
|
||||
private static string BuildPattern(string username, string password)
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
|
||||
#if NET451 || NET452 || NET46 || NET451 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
||||
using System.Text.RegularExpressions;
|
||||
using WireMock.Constants;
|
||||
|
||||
// ReSharper disable once CheckNamespace
|
||||
namespace System;
|
||||
@@ -11,7 +12,7 @@ internal static class StringExtensions
|
||||
public static string Replace(this string text, string oldValue, string newValue, StringComparison stringComparison)
|
||||
{
|
||||
var options = stringComparison == StringComparison.OrdinalIgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
|
||||
return Regex.Replace(text, oldValue, newValue, options);
|
||||
return Regex.Replace(text, oldValue, newValue, options, WireMockConstants.DefaultRegexTimeout);
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,15 +1,19 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
|
||||
namespace WireMock.Constants;
|
||||
|
||||
internal static class WireMockConstants
|
||||
{
|
||||
public const int AdminPriority = int.MinValue;
|
||||
public const int MinPriority = -1_000_000;
|
||||
public const int ProxyPriority = -2_000_000;
|
||||
internal static readonly TimeSpan DefaultRegexTimeout = TimeSpan.FromSeconds(10);
|
||||
|
||||
internal const int AdminPriority = int.MinValue;
|
||||
internal const int MinPriority = -1_000_000;
|
||||
internal const int ProxyPriority = -2_000_000;
|
||||
|
||||
public const string ContentTypeJson = "application/json";
|
||||
public const string ContentTypeTextPlain = "text/plain";
|
||||
internal const string ContentTypeJson = "application/json";
|
||||
internal const string ContentTypeTextPlain = "text/plain";
|
||||
|
||||
public const string NoMatchingFound = "No matching mapping found";
|
||||
}
|
||||
internal const string NoMatchingFound = "No matching mapping found";
|
||||
}
|
||||
@@ -14,12 +14,12 @@ namespace WireMock.Http;
|
||||
/// </summary>
|
||||
internal static class HttpKnownHeaderNames
|
||||
{
|
||||
// https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted
|
||||
// - https://docs.microsoft.com/en-us/dotnet/api/system.net.webheadercollection.isrestricted
|
||||
// - ContentLength is allowed per #720
|
||||
private static readonly string[] RestrictedResponseHeaders =
|
||||
{
|
||||
Accept,
|
||||
Connection,
|
||||
ContentLength,
|
||||
ContentType,
|
||||
Date, // RFC1123Pattern
|
||||
Expect,
|
||||
|
||||
@@ -9,6 +9,7 @@ using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Http;
|
||||
|
||||
@@ -33,12 +34,14 @@ internal static class HttpRequestMessageHelper
|
||||
MediaTypeHeaderValue.TryParse(value, out contentType);
|
||||
}
|
||||
|
||||
httpRequestMessage.Content = requestMessage.BodyData?.DetectedBodyType switch
|
||||
var bodyData = requestMessage.BodyData;
|
||||
httpRequestMessage.Content = bodyData?.GetBodyType() switch
|
||||
{
|
||||
BodyType.Bytes => ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType),
|
||||
BodyType.Json => StringContentHelper.Create(JsonConvert.SerializeObject(requestMessage.BodyData.BodyAsJson), contentType),
|
||||
BodyType.String => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
|
||||
BodyType.FormUrlEncoded => StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType),
|
||||
BodyType.Bytes => ByteArrayContentHelper.Create(bodyData!.BodyAsBytes!, contentType),
|
||||
BodyType.Json => StringContentHelper.Create(JsonConvert.SerializeObject(bodyData!.BodyAsJson), contentType),
|
||||
BodyType.String => StringContentHelper.Create(bodyData!.BodyAsString!, contentType),
|
||||
BodyType.FormUrlEncoded => StringContentHelper.Create(bodyData!.BodyAsString!, contentType),
|
||||
|
||||
_ => httpRequestMessage.Content
|
||||
};
|
||||
|
||||
|
||||
@@ -130,7 +130,10 @@ public class MappingBuilder : IMappingBuilder
|
||||
|
||||
private IMapping[] GetNonAdminMappings()
|
||||
{
|
||||
return _options.Mappings.Values.Where(m => !m.IsAdminInterface).OrderBy(m => m.UpdatedAt).ToArray();
|
||||
return _options.Mappings.Values
|
||||
.Where(m => !m.IsAdminInterface)
|
||||
.OrderBy(m => m.Guid)
|
||||
.ToArray();
|
||||
}
|
||||
|
||||
private void RegisterMapping(IMapping mapping, bool saveToFile)
|
||||
|
||||
@@ -2,7 +2,10 @@
|
||||
|
||||
using System.Net.Http.Headers;
|
||||
using AnyOfTypes;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -19,7 +22,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
|
||||
public ContentTypeMatcher(AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this([pattern], ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -29,7 +32,8 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour,
|
||||
[pattern], ignoreCase)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -50,7 +54,7 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
/// <param name="ignoreCase">IgnoreCase (default false)</param>
|
||||
public ContentTypeMatcher(MatchBehaviour matchBehaviour, AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : base(matchBehaviour, patterns, ignoreCase)
|
||||
{
|
||||
_patterns = patterns;
|
||||
_patterns = Guard.NotNull(patterns);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -72,4 +76,15 @@ public class ContentTypeMatcher : WildcardMatcher
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string Name => nameof(ContentTypeMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -4,7 +4,9 @@ using System;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -86,8 +88,20 @@ public class ExactMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "ExactMatcher";
|
||||
public string Name => nameof(ExactMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public bool IgnoreCase { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_values)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -72,5 +72,11 @@ public class ExactObjectMatcher : IObjectMatcher
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "ExactObjectMatcher";
|
||||
public string Name => nameof(ExactObjectMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return "NotImplemented";
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
@@ -27,7 +29,7 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
/// </summary>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
|
||||
public FormUrlEncodedMatcher(
|
||||
AnyOf<string, StringPattern> pattern,
|
||||
bool ignoreCase = false,
|
||||
@@ -42,7 +44,7 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="pattern">The pattern.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
|
||||
public FormUrlEncodedMatcher(
|
||||
MatchBehaviour matchBehaviour,
|
||||
AnyOf<string, StringPattern> pattern,
|
||||
@@ -57,7 +59,7 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
/// </summary>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
|
||||
public FormUrlEncodedMatcher(
|
||||
AnyOf<string, StringPattern>[] patterns,
|
||||
bool ignoreCase = false,
|
||||
@@ -72,7 +74,7 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="patterns">The patterns.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||
/// <param name="matchOperator">The <see cref="Matchers.MatchOperator"/> to use. (default = "Or")</param>
|
||||
/// <param name="matchOperator">The <see cref="MatchOperator"/> to use. (default = "Or")</param>
|
||||
public FormUrlEncodedMatcher(
|
||||
MatchBehaviour matchBehaviour,
|
||||
AnyOf<string, StringPattern>[] patterns,
|
||||
@@ -112,7 +114,20 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
return new MatchResult(MatchScores.Mismatch);
|
||||
}
|
||||
|
||||
var matches = GetMatches(inputNameValueCollection);
|
||||
|
||||
var score = MatchScores.ToScore(matches, MatchOperator);
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
}
|
||||
|
||||
private bool[] GetMatches(IDictionary<string, string> inputNameValueCollection)
|
||||
{
|
||||
var matches = new List<bool>();
|
||||
if (_pairs.Count > inputNameValueCollection.Count)
|
||||
{
|
||||
matches.AddRange(Enumerable.Repeat(false, _pairs.Count - inputNameValueCollection.Count));
|
||||
}
|
||||
|
||||
foreach (var inputKeyValuePair in inputNameValueCollection)
|
||||
{
|
||||
var match = false;
|
||||
@@ -132,8 +147,7 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
matches.Add(match);
|
||||
}
|
||||
|
||||
var score = MatchScores.ToScore(matches.ToArray(), MatchOperator);
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score));
|
||||
return matches.ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -150,4 +164,16 @@ public class FormUrlEncodedMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -156,6 +156,12 @@ public class GraphQLMatcher : IStringMatcher
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(GraphQLMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return "NotImplemented";
|
||||
}
|
||||
|
||||
private static bool TryGetGraphQLRequest(string input, [NotNullWhen(true)] out GraphQLRequest? graphQLRequest)
|
||||
{
|
||||
try
|
||||
|
||||
@@ -16,4 +16,10 @@ public interface IMatcher
|
||||
/// Gets the match behaviour.
|
||||
/// </summary>
|
||||
MatchBehaviour MatchBehaviour { get; }
|
||||
|
||||
/// <summary>
|
||||
/// Get the C# code arguments.
|
||||
/// </summary>
|
||||
/// <returns></returns>
|
||||
string GetCSharpCodeArguments();
|
||||
}
|
||||
@@ -7,6 +7,7 @@ using Newtonsoft.Json.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -89,7 +90,7 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
|
||||
Exception? exception = null;
|
||||
|
||||
// When input is null or byte[], return Mismatch.
|
||||
if (input != null && !(input is byte[]))
|
||||
if (input != null && input is not byte[])
|
||||
{
|
||||
try
|
||||
{
|
||||
@@ -116,7 +117,18 @@ public class JsonPathMatcher : IStringMatcher, IObjectMatcher
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => "JsonPathMatcher";
|
||||
public string Name => nameof(JsonPathMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
private double IsMatch(JToken jToken)
|
||||
{
|
||||
|
||||
@@ -8,6 +8,7 @@ using Newtonsoft.Json;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -115,4 +116,15 @@ public class JmesPathMatcher : IStringMatcher, IObjectMatcher
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(JmesPathMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Util;
|
||||
using JsonUtils = WireMock.Util.JsonUtils;
|
||||
|
||||
@@ -98,6 +99,18 @@ public class JsonMatcher : IJsonMatcher
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), error);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{CSharpFormatter.ConvertToAnonymousObjectDefinition(Value, 3)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(Regex)}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the input against the matcher value
|
||||
/// </summary>
|
||||
|
||||
@@ -1,5 +1,8 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
@@ -34,4 +37,16 @@ public class JsonPartialMatcher : AbstractJsonPartialMatcher
|
||||
var exactStringMatcher = new ExactMatcher(MatchBehaviour.AcceptOnMatch, IgnoreCase, MatchOperator.Or, value);
|
||||
return exactStringMatcher.IsMatch(input).IsPerfect();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{CSharpFormatter.ConvertToAnonymousObjectDefinition(Value, 3)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(Regex)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,8 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
/// <summary>
|
||||
@@ -34,4 +37,16 @@ public class JsonPartialWildcardMatcher : AbstractJsonPartialMatcher
|
||||
var wildcardStringMatcher = new WildcardMatcher(MatchBehaviour.AcceptOnMatch, value, IgnoreCase);
|
||||
return wildcardStringMatcher.IsMatch(input).IsPerfect();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{CSharpFormatter.ConvertToAnonymousObjectDefinition(Value, 3)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(Regex)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -9,6 +9,7 @@ using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Json;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -136,4 +137,15 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
||||
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(LinqMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
#if MIMEKIT
|
||||
using System;
|
||||
using MimeKit;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Helpers;
|
||||
using WireMock.Models;
|
||||
@@ -60,13 +61,13 @@ public class MimePartMatcher : IMatcher
|
||||
ContentTransferEncodingMatcher = contentTransferEncodingMatcher;
|
||||
ContentMatcher = contentMatcher;
|
||||
|
||||
_funcs = new[]
|
||||
{
|
||||
_funcs =
|
||||
[
|
||||
mp => ContentTypeMatcher?.IsMatch(GetContentTypeAsString(mp.ContentType)) ?? MatchScores.Perfect,
|
||||
mp => ContentDispositionMatcher?.IsMatch(mp.ContentDisposition.ToString().Replace("Content-Disposition: ", string.Empty)) ?? MatchScores.Perfect,
|
||||
mp => ContentTransferEncodingMatcher?.IsMatch(mp.ContentTransferEncoding.ToString().ToLowerInvariant()) ?? MatchScores.Perfect,
|
||||
MatchOnContent
|
||||
};
|
||||
];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
@@ -94,6 +95,12 @@ public class MimePartMatcher : IMatcher
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return "NotImplemented";
|
||||
}
|
||||
|
||||
private MatchResult MatchOnContent(MimePart mimePart)
|
||||
{
|
||||
if (ContentMatcher == null)
|
||||
|
||||
@@ -3,7 +3,9 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -70,5 +72,14 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; } = MatchOperator.Or;
|
||||
public MatchOperator MatchOperator => MatchOperator.Or;
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -89,6 +89,12 @@ public class ProtoBufMatcher : IProtoBufMatcher
|
||||
return DecodeAsync(input, false, cancellationToken);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return "NotImplemented";
|
||||
}
|
||||
|
||||
private async Task<object?> DecodeAsync(byte[]? input, bool throwException, CancellationToken cancellationToken)
|
||||
{
|
||||
if (input == null)
|
||||
|
||||
@@ -5,10 +5,12 @@ using System.Linq;
|
||||
using System.Text.RegularExpressions;
|
||||
using AnyOfTypes;
|
||||
using JetBrains.Annotations;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.RegularExpressions;
|
||||
using Stef.Validation;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -21,6 +23,7 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
{
|
||||
private readonly AnyOf<string, StringPattern>[] _patterns;
|
||||
private readonly Regex[] _expressions;
|
||||
private readonly bool _useRegexExtended;
|
||||
|
||||
/// <inheritdoc />
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
@@ -37,7 +40,7 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
bool ignoreCase = false,
|
||||
bool useRegexExtended = true,
|
||||
MatchOperator matchOperator = MatchOperator.Or) :
|
||||
this(MatchBehaviour.AcceptOnMatch, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator)
|
||||
this(MatchBehaviour.AcceptOnMatch, [pattern], ignoreCase, useRegexExtended, matchOperator)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -55,7 +58,7 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
bool ignoreCase = false,
|
||||
bool useRegexExtended = true,
|
||||
MatchOperator matchOperator = MatchOperator.Or) :
|
||||
this(matchBehaviour, new[] { pattern }, ignoreCase, useRegexExtended, matchOperator)
|
||||
this(matchBehaviour, [pattern], ignoreCase, useRegexExtended, matchOperator)
|
||||
{
|
||||
}
|
||||
|
||||
@@ -76,17 +79,18 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
{
|
||||
_patterns = Guard.NotNull(patterns);
|
||||
IgnoreCase = ignoreCase;
|
||||
_useRegexExtended = useRegexExtended;
|
||||
MatchBehaviour = matchBehaviour;
|
||||
MatchOperator = matchOperator;
|
||||
|
||||
RegexOptions options = RegexOptions.Compiled | RegexOptions.Multiline;
|
||||
var options = RegexOptions.Compiled | RegexOptions.Multiline;
|
||||
|
||||
if (ignoreCase)
|
||||
{
|
||||
options |= RegexOptions.IgnoreCase;
|
||||
}
|
||||
|
||||
_expressions = patterns.Select(p => useRegexExtended ? new RegexExtended(p.GetPattern(), options) : new Regex(p.GetPattern(), options)).ToArray();
|
||||
_expressions = patterns.Select(p => useRegexExtended ? new RegexExtended(p.GetPattern(), options) : new Regex(p.GetPattern(), options, WireMockConstants.DefaultRegexTimeout)).ToArray();
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
@@ -125,4 +129,16 @@ public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||
/// <inheritdoc />
|
||||
public MatchOperator MatchOperator { get; }
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(_useRegexExtended)}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
|
||||
$")";
|
||||
}
|
||||
}
|
||||
@@ -8,6 +8,7 @@ using SimMetrics.Net.Metric;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -88,6 +89,18 @@ public class SimMetricsMatcher : IStringMatcher
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, score);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public virtual string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
|
||||
$"{_simMetricType.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
private IStringMetric GetStringMetricType()
|
||||
{
|
||||
return _simMetricType switch
|
||||
|
||||
@@ -6,6 +6,7 @@ using AnyOfTypes;
|
||||
using Stef.Validation;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Matchers;
|
||||
|
||||
@@ -70,6 +71,18 @@ public class WildcardMatcher : RegexMatcher
|
||||
/// <inheritdoc />
|
||||
public override string Name => nameof(WildcardMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public override string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}, " +
|
||||
$"{CSharpFormatter.ToCSharpBooleanLiteral(IgnoreCase)}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
private static AnyOf<string, StringPattern>[] CreateArray(AnyOf<string, StringPattern>[] patterns)
|
||||
{
|
||||
return patterns
|
||||
|
||||
@@ -10,6 +10,7 @@ using WireMock.Extensions;
|
||||
using WireMock.Models;
|
||||
using Stef.Validation;
|
||||
using WireMock.Admin.Mappings;
|
||||
using WireMock.Util;
|
||||
#if !NETSTANDARD1_3
|
||||
using Wmhelp.XPath2;
|
||||
#endif
|
||||
@@ -89,11 +90,6 @@ public class XPathMatcher : IStringMatcher
|
||||
return CreateMatchResult(score);
|
||||
}
|
||||
|
||||
private MatchResult CreateMatchResult(double score, Exception? exception = null)
|
||||
{
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||
{
|
||||
@@ -106,6 +102,23 @@ public class XPathMatcher : IStringMatcher
|
||||
/// <inheritdoc />
|
||||
public string Name => nameof(XPathMatcher);
|
||||
|
||||
/// <inheritdoc />
|
||||
public string GetCSharpCodeArguments()
|
||||
{
|
||||
return $"new {Name}" +
|
||||
$"(" +
|
||||
$"{MatchBehaviour.GetFullyQualifiedEnumValue()}, " +
|
||||
$"{MatchOperator.GetFullyQualifiedEnumValue()}, " +
|
||||
$"null, " +
|
||||
$"{MappingConverterUtils.ToCSharpCodeArguments(_patterns)}" +
|
||||
$")";
|
||||
}
|
||||
|
||||
private MatchResult CreateMatchResult(double score, Exception? exception = null)
|
||||
{
|
||||
return new MatchResult(MatchBehaviourHelper.Convert(MatchBehaviour, score), exception);
|
||||
}
|
||||
|
||||
private sealed class XPathEvaluator
|
||||
{
|
||||
private XmlDocument? _xmlDocument;
|
||||
@@ -130,6 +143,7 @@ public class XPathMatcher : IStringMatcher
|
||||
{
|
||||
return _xpathNavigator == null ? [] : patterns.Select(pattern => true.Equals(Evaluate(_xpathNavigator, pattern, xmlNamespaceMap))).ToArray();
|
||||
}
|
||||
|
||||
private object Evaluate(XPathNavigator navigator, AnyOf<string, StringPattern> pattern, IEnumerable<XmlNamespace>? xmlNamespaceMap)
|
||||
{
|
||||
var xpath = $"boolean({pattern.GetPattern()})";
|
||||
|
||||
@@ -75,8 +75,15 @@ namespace WireMock.Owin
|
||||
|
||||
private static void Listen(KestrelServerOptions kestrelOptions, HostUrlDetails urlDetail, Action<ListenOptions> configure)
|
||||
{
|
||||
// Listens on any IP with the given port.
|
||||
if (urlDetail is { Port: > 0, Host: "0.0.0.0" })
|
||||
{
|
||||
kestrelOptions.ListenAnyIP(urlDetail.Port, configure);
|
||||
return;
|
||||
}
|
||||
|
||||
// Listens on ::1 and 127.0.0.1 with the given port.
|
||||
if (urlDetail is { Port: > 0, Host: "localhost" or "127.0.0.1" or "0.0.0.0" or "::1" })
|
||||
if (urlDetail is { Port: > 0, Host: "localhost" or "127.0.0.1" or "::1" })
|
||||
{
|
||||
kestrelOptions.ListenLocalhost(urlDetail.Port, configure);
|
||||
return;
|
||||
@@ -113,4 +120,4 @@ namespace WireMock.Owin
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
#endif
|
||||
|
||||
@@ -37,13 +37,20 @@ namespace WireMock.Owin.Mappers
|
||||
private readonly Encoding _utf8NoBom = new UTF8Encoding(false);
|
||||
|
||||
// https://msdn.microsoft.com/en-us/library/78h415ay(v=vs.110).aspx
|
||||
#if !USE_ASPNETCORE
|
||||
private static readonly IDictionary<string, Action<IResponse, WireMockList<string>>> ResponseHeadersToFix = new Dictionary<string, Action<IResponse, WireMockList<string>>>(StringComparer.OrdinalIgnoreCase) {
|
||||
#else
|
||||
private static readonly IDictionary<string, Action<IResponse, WireMockList<string>>> ResponseHeadersToFix = new Dictionary<string, Action<IResponse, WireMockList<string>>>(StringComparer.OrdinalIgnoreCase) {
|
||||
#endif
|
||||
{ HttpKnownHeaderNames.ContentType, (r, v) => r.ContentType = v.FirstOrDefault() }
|
||||
};
|
||||
private static readonly IDictionary<string, Action<IResponse, bool, WireMockList<string>>> ResponseHeadersToFix =
|
||||
new Dictionary<string, Action<IResponse, bool, WireMockList<string>>>(StringComparer.OrdinalIgnoreCase)
|
||||
{
|
||||
{ HttpKnownHeaderNames.ContentType, (r, _, v) => r.ContentType = v.FirstOrDefault() },
|
||||
{ HttpKnownHeaderNames.ContentLength, (r, hasBody, v) =>
|
||||
{
|
||||
// Only set the Content-Length header if the response does not have a body
|
||||
if (!hasBody && long.TryParse(v.FirstOrDefault(), out var contentLength))
|
||||
{
|
||||
r.ContentLength = contentLength;
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/// <summary>
|
||||
/// Constructor
|
||||
@@ -83,23 +90,21 @@ namespace WireMock.Owin.Mappers
|
||||
}
|
||||
|
||||
var statusCodeType = responseMessage.StatusCode?.GetType();
|
||||
switch (statusCodeType)
|
||||
if (statusCodeType != null)
|
||||
{
|
||||
case { } when statusCodeType == typeof(int) || statusCodeType == typeof(int?) || statusCodeType.GetTypeInfo().IsEnum:
|
||||
if (statusCodeType == typeof(int) || statusCodeType == typeof(int?) || statusCodeType.GetTypeInfo().IsEnum)
|
||||
{
|
||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode!);
|
||||
break;
|
||||
|
||||
case { } when statusCodeType == typeof(string):
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(responseMessage.StatusCode as string, out var result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
break;
|
||||
|
||||
default:
|
||||
break;
|
||||
}
|
||||
else if (statusCodeType == typeof(string))
|
||||
{
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(responseMessage.StatusCode as string, out var statusCodeTypeAsInt);
|
||||
response.StatusCode = MapStatusCode(statusCodeTypeAsInt);
|
||||
}
|
||||
}
|
||||
|
||||
SetResponseHeaders(responseMessage, response);
|
||||
SetResponseHeaders(responseMessage, bytes, response);
|
||||
|
||||
if (bytes != null)
|
||||
{
|
||||
@@ -131,45 +136,49 @@ namespace WireMock.Owin.Mappers
|
||||
return responseMessage.FaultPercentage == null || _randomizerDouble.Generate() <= responseMessage.FaultPercentage;
|
||||
}
|
||||
|
||||
private async Task<byte[]?> GetNormalBodyAsync(IResponseMessage responseMessage)
|
||||
{
|
||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||
private async Task<byte[]?> GetNormalBodyAsync(IResponseMessage responseMessage) {
|
||||
var bodyData = responseMessage.BodyData;
|
||||
switch (bodyData?.GetBodyType())
|
||||
{
|
||||
case BodyType.String:
|
||||
case BodyType.FormUrlEncoded:
|
||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
||||
return (bodyData.Encoding ?? _utf8NoBom).GetBytes(bodyData.BodyAsString!);
|
||||
|
||||
case BodyType.Json:
|
||||
var formatting = responseMessage.BodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None;
|
||||
var jsonBody = JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
|
||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
|
||||
var formatting = bodyData.BodyAsJsonIndented == true ? Formatting.Indented : Formatting.None;
|
||||
var jsonBody = JsonConvert.SerializeObject(bodyData.BodyAsJson, new JsonSerializerSettings { Formatting = formatting, NullValueHandling = NullValueHandling.Ignore });
|
||||
return (bodyData.Encoding ?? _utf8NoBom).GetBytes(jsonBody);
|
||||
|
||||
#if PROTOBUF
|
||||
case BodyType.ProtoBuf:
|
||||
var protoDefinition = responseMessage.BodyData.ProtoDefinition?.Invoke().Text;
|
||||
return await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinition, responseMessage.BodyData.ProtoBufMessageType, responseMessage.BodyData.BodyAsJson).ConfigureAwait(false);
|
||||
var protoDefinition = bodyData.ProtoDefinition?.Invoke().Text;
|
||||
return await ProtoBufUtils.GetProtoBufMessageWithHeaderAsync(protoDefinition, bodyData.ProtoBufMessageType, bodyData.BodyAsJson).ConfigureAwait(false);
|
||||
#endif
|
||||
|
||||
case BodyType.Bytes:
|
||||
return responseMessage.BodyData.BodyAsBytes;
|
||||
return bodyData.BodyAsBytes;
|
||||
|
||||
case BodyType.File:
|
||||
return _options.FileSystemHandler?.ReadResponseBodyAsFile(responseMessage.BodyData.BodyAsFile!);
|
||||
return _options.FileSystemHandler?.ReadResponseBodyAsFile(bodyData.BodyAsFile!);
|
||||
|
||||
case BodyType.MultiPart:
|
||||
_options.Logger.Warn("MultiPart body type is not handled!");
|
||||
break;
|
||||
|
||||
case BodyType.None:
|
||||
break;
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
private static void SetResponseHeaders(IResponseMessage responseMessage, IResponse response)
|
||||
private static void SetResponseHeaders(IResponseMessage responseMessage, byte[]? bytes, IResponse response)
|
||||
{
|
||||
// Force setting the Date header (#577)
|
||||
AppendResponseHeader(
|
||||
response,
|
||||
HttpKnownHeaderNames.Date,
|
||||
new[]
|
||||
{
|
||||
DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture)
|
||||
}
|
||||
[ DateTime.UtcNow.ToString(CultureInfo.InvariantCulture.DateTimeFormat.RFC1123Pattern, CultureInfo.InvariantCulture) ]
|
||||
);
|
||||
|
||||
// Set other headers
|
||||
@@ -179,11 +188,11 @@ namespace WireMock.Owin.Mappers
|
||||
var value = item.Value;
|
||||
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
||||
{
|
||||
action?.Invoke(response, value);
|
||||
action?.Invoke(response, bytes != null, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
// Check if this response header can be added (#148 and #227)
|
||||
// Check if this response header can be added (#148, #227 and #720)
|
||||
if (!HttpKnownHeaderNames.IsRestrictedResponseHeader(headerName))
|
||||
{
|
||||
AppendResponseHeader(response, headerName, value.ToArray());
|
||||
@@ -206,7 +215,7 @@ namespace WireMock.Owin.Mappers
|
||||
var value = item.Value;
|
||||
if (ResponseHeadersToFix.TryGetValue(headerName, out var action))
|
||||
{
|
||||
action?.Invoke(response, value);
|
||||
action?.Invoke(response, false, value);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
@@ -126,7 +126,7 @@ namespace WireMock.Owin
|
||||
if (targetMapping == null)
|
||||
{
|
||||
logRequest = true;
|
||||
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found");
|
||||
_options.Logger.Warn("HttpStatusCode set to 404 : No matching mapping found", ctx.Request);
|
||||
response = ResponseMessageBuilder.Create(HttpStatusCode.NotFound, WireMockConstants.NoMatchingFound);
|
||||
return;
|
||||
}
|
||||
@@ -357,4 +357,4 @@ namespace WireMock.Owin
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Stef.Validation;
|
||||
using WireMock.Settings;
|
||||
|
||||
@@ -7,21 +8,31 @@ namespace WireMock.Owin;
|
||||
|
||||
internal static class WireMockMiddlewareOptionsHelper
|
||||
{
|
||||
public static IWireMockMiddlewareOptions InitFromSettings(WireMockServerSettings settings, IWireMockMiddlewareOptions? options = null)
|
||||
public static IWireMockMiddlewareOptions InitFromSettings(
|
||||
WireMockServerSettings settings,
|
||||
IWireMockMiddlewareOptions? options = null,
|
||||
Action<IWireMockMiddlewareOptions>? postConfigure = null
|
||||
)
|
||||
{
|
||||
Guard.NotNull(settings);
|
||||
|
||||
options ??= new WireMockMiddlewareOptions();
|
||||
|
||||
options.FileSystemHandler = settings.FileSystemHandler;
|
||||
options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
|
||||
options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
|
||||
options.Logger = settings.Logger;
|
||||
options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
|
||||
options.AllowOnlyDefinedHttpStatusCodeInResponse = settings.AllowOnlyDefinedHttpStatusCodeInResponse;
|
||||
options.AllowPartialMapping = settings.AllowPartialMapping;
|
||||
options.DisableJsonBodyParsing = settings.DisableJsonBodyParsing;
|
||||
options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
options.DisableRequestBodyDecompressing = settings.DisableRequestBodyDecompressing;
|
||||
options.DoNotSaveDynamicResponseInLogEntry = settings.DoNotSaveDynamicResponseInLogEntry;
|
||||
options.FileSystemHandler = settings.FileSystemHandler;
|
||||
options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
options.Logger = settings.Logger;
|
||||
options.MaxRequestLogCount = settings.MaxRequestLogCount;
|
||||
options.PostWireMockMiddlewareInit = settings.PostWireMockMiddlewareInit;
|
||||
options.PreWireMockMiddlewareInit = settings.PreWireMockMiddlewareInit;
|
||||
options.QueryParameterMultipleValueSupport = settings.QueryParameterMultipleValueSupport;
|
||||
options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||
options.SaveUnmatchedRequests = settings.SaveUnmatchedRequests;
|
||||
|
||||
if (settings.CustomCertificateDefined)
|
||||
{
|
||||
@@ -32,6 +43,8 @@ internal static class WireMockMiddlewareOptionsHelper
|
||||
options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
|
||||
}
|
||||
|
||||
postConfigure?.Invoke(options);
|
||||
|
||||
return options;
|
||||
}
|
||||
}
|
||||
@@ -13,6 +13,8 @@ namespace WireMock.ResponseBuilders;
|
||||
|
||||
public partial class Response
|
||||
{
|
||||
private bool _bodyFromFileSet;
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithBody(Func<IRequestMessage, string> bodyFactory, string? destination = BodyDestinationFormat.SameAsSource, Encoding? encoding = null)
|
||||
{
|
||||
@@ -78,6 +80,8 @@ public partial class Response
|
||||
{
|
||||
Guard.NotNull(filename);
|
||||
|
||||
_bodyFromFileSet = true;
|
||||
|
||||
ResponseMessage.BodyData = new BodyData
|
||||
{
|
||||
BodyAsFileIsCached = cache,
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using WireMock.Types;
|
||||
|
||||
namespace WireMock.ResponseBuilders;
|
||||
|
||||
public partial class Response
|
||||
{
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
||||
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(ReplaceNodeOptions)"/>
|
||||
public IResponseBuilder WithTransformer(ReplaceNodeOptions options)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, false, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.EvaluateAndTryToConvert)
|
||||
{
|
||||
if (_bodyFromFileSet)
|
||||
{
|
||||
throw new InvalidOperationException("WithTransformer should be used before WithBodyFromFile.");
|
||||
}
|
||||
|
||||
UseTransformer = true;
|
||||
TransformerType = transformerType;
|
||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
||||
TransformerReplaceNodeOptions = options;
|
||||
return this;
|
||||
}
|
||||
}
|
||||
@@ -164,28 +164,6 @@ public partial class Response : IResponseBuilder
|
||||
return WithStatusCode((int)HttpStatusCode.NotFound);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(bool)"/>
|
||||
public IResponseBuilder WithTransformer(bool transformContentFromBodyAsFile)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, transformContentFromBodyAsFile);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ITransformResponseBuilder.WithTransformer(ReplaceNodeOptions)"/>
|
||||
public IResponseBuilder WithTransformer(ReplaceNodeOptions options)
|
||||
{
|
||||
return WithTransformer(TransformerType.Handlebars, false, options);
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithTransformer(TransformerType transformerType, bool transformContentFromBodyAsFile = false, ReplaceNodeOptions options = ReplaceNodeOptions.EvaluateAndTryToConvert)
|
||||
{
|
||||
UseTransformer = true;
|
||||
TransformerType = transformerType;
|
||||
UseTransformerForBodyAsFile = transformContentFromBodyAsFile;
|
||||
TransformerReplaceNodeOptions = options;
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
public IResponseBuilder WithDelay(TimeSpan delay)
|
||||
{
|
||||
@@ -286,7 +264,7 @@ public partial class Response : IResponseBuilder
|
||||
|
||||
if (UseTransformer)
|
||||
{
|
||||
// Check if the body matcher is a RequestMessageProtoBufMatcher and try to to decode the byte-array to a BodyAsJson.
|
||||
// Check if the body matcher is a RequestMessageProtoBufMatcher and try to decode the byte-array to a BodyAsJson.
|
||||
if (mapping.RequestMatcher is Request requestMatcher && requestMessage is RequestMessage request)
|
||||
{
|
||||
var protoBufMatcher = requestMatcher.GetRequestMessageMatcher<RequestMessageProtoBufMatcher>()?.Matcher;
|
||||
|
||||
@@ -23,16 +23,11 @@ using static WireMock.Util.CSharpFormatter;
|
||||
|
||||
namespace WireMock.Serialization;
|
||||
|
||||
internal class MappingConverter
|
||||
internal class MappingConverter(MatcherMapper mapper)
|
||||
{
|
||||
private static readonly string AcceptOnMatch = MatchBehaviour.AcceptOnMatch.GetFullyQualifiedEnumValue();
|
||||
|
||||
private readonly MatcherMapper _mapper;
|
||||
|
||||
public MappingConverter(MatcherMapper mapper)
|
||||
{
|
||||
_mapper = Guard.NotNull(mapper);
|
||||
}
|
||||
private readonly MatcherMapper _mapper = Guard.NotNull(mapper);
|
||||
|
||||
public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings = null)
|
||||
{
|
||||
@@ -77,26 +72,26 @@ internal class MappingConverter
|
||||
sb.AppendLine(" .Given(Request.Create()");
|
||||
sb.AppendLine($" .UsingMethod({To1Or2Or3Arguments(methodMatcher?.MatchBehaviour, methodMatcher?.MatchOperator, methodMatcher?.Methods, HttpRequestMethod.GET)})");
|
||||
|
||||
if (pathMatcher is { Matchers: { } })
|
||||
if (pathMatcher?.Matchers != null)
|
||||
{
|
||||
sb.AppendLine($" .WithPath({To1Or2Arguments(pathMatcher.MatchOperator, pathMatcher.Matchers)})");
|
||||
}
|
||||
else if (urlMatcher is { Matchers: { } })
|
||||
else if (urlMatcher?.Matchers != null)
|
||||
{
|
||||
sb.AppendLine($" .WithUrl({To1Or2Arguments(urlMatcher.MatchOperator, urlMatcher.Matchers)})");
|
||||
}
|
||||
|
||||
foreach (var paramsMatcher in paramsMatchers)
|
||||
foreach (var paramsMatcher in paramsMatchers.Where(pm => pm.Matchers != null))
|
||||
{
|
||||
sb.AppendLine($" .WithParam({To1Or2Or3Arguments(paramsMatcher.Key, paramsMatcher.MatchBehaviour, paramsMatcher.Matchers!)})");
|
||||
sb.AppendLine($" .WithParam({To2Or3Arguments(paramsMatcher.Key, paramsMatcher.MatchBehaviour, paramsMatcher.Matchers!)})");
|
||||
}
|
||||
|
||||
if (clientIPMatcher is { Matchers: { } })
|
||||
if (clientIPMatcher?.Matchers != null)
|
||||
{
|
||||
sb.AppendLine($" .WithClientIP({ToValueArguments(GetStringArray(clientIPMatcher.Matchers))})");
|
||||
}
|
||||
|
||||
foreach (var headerMatcher in headerMatchers.Where(h => h.Matchers is { }))
|
||||
foreach (var headerMatcher in headerMatchers.Where(h => h.Matchers != null))
|
||||
{
|
||||
var headerBuilder = new StringBuilder($"\"{headerMatcher.Name}\", {ToValueArguments(GetStringArray(headerMatcher.Matchers!))}, true");
|
||||
if (headerMatcher.MatchOperator != MatchOperator.Or)
|
||||
@@ -106,7 +101,7 @@ internal class MappingConverter
|
||||
sb.AppendLine($" .WithHeader({headerBuilder})");
|
||||
}
|
||||
|
||||
foreach (var cookieMatcher in cookieMatchers.Where(h => h.Matchers is { }))
|
||||
foreach (var cookieMatcher in cookieMatchers.Where(c => c.Matchers != null))
|
||||
{
|
||||
sb.AppendLine($" .WithCookie(\"{cookieMatcher.Name}\", {ToValueArguments(GetStringArray(cookieMatcher.Matchers!))}, true)");
|
||||
}
|
||||
@@ -117,7 +112,7 @@ internal class MappingConverter
|
||||
}
|
||||
|
||||
#if GRAPHQL
|
||||
if (requestMessageGraphQLMatcher is { Matchers: { } })
|
||||
if (requestMessageGraphQLMatcher?.Matchers != null)
|
||||
{
|
||||
if (requestMessageGraphQLMatcher.Matchers.OfType<GraphQLMatcher>().FirstOrDefault() is { } graphQLMatcher && graphQLMatcher.GetPatterns().Any())
|
||||
{
|
||||
@@ -127,7 +122,7 @@ internal class MappingConverter
|
||||
#endif
|
||||
|
||||
#if MIMEKIT
|
||||
if (requestMessageMultiPartMatcher is { Matchers: { } })
|
||||
if (requestMessageMultiPartMatcher?.Matchers != null)
|
||||
{
|
||||
if (requestMessageMultiPartMatcher.Matchers.OfType<MimePartMatcher>().Any())
|
||||
{
|
||||
@@ -137,13 +132,13 @@ internal class MappingConverter
|
||||
#endif
|
||||
|
||||
#if PROTOBUF
|
||||
if (requestMessageProtoBufMatcher is { Matcher: { } })
|
||||
if (requestMessageProtoBufMatcher?.Matcher != null)
|
||||
{
|
||||
sb.AppendLine(" // .WithBodyAsProtoBuf() is not yet supported");
|
||||
}
|
||||
#endif
|
||||
|
||||
if (requestMessageBodyMatcher is { Matchers: { } })
|
||||
if (requestMessageBodyMatcher?.Matchers != null)
|
||||
{
|
||||
var firstMatcher = requestMessageBodyMatcher.Matchers.FirstOrDefault();
|
||||
|
||||
@@ -154,15 +149,15 @@ internal class MappingConverter
|
||||
break;
|
||||
|
||||
case JsonMatcher jsonMatcher:
|
||||
{
|
||||
var matcherType = jsonMatcher.GetType().Name;
|
||||
sb.AppendLine($" .WithBody(new {matcherType}(");
|
||||
sb.AppendLine($" value: {ConvertToAnonymousObjectDefinition(jsonMatcher.Value, 3)},");
|
||||
sb.AppendLine($" ignoreCase: {ToCSharpBooleanLiteral(jsonMatcher.IgnoreCase)},");
|
||||
sb.AppendLine($" regex: {ToCSharpBooleanLiteral(jsonMatcher.Regex)}");
|
||||
sb.AppendLine(@" ))");
|
||||
break;
|
||||
}
|
||||
{
|
||||
var matcherType = jsonMatcher.GetType().Name;
|
||||
sb.AppendLine($" .WithBody(new {matcherType}(");
|
||||
sb.AppendLine($" value: {ConvertToAnonymousObjectDefinition(jsonMatcher.Value, 3)},");
|
||||
sb.AppendLine($" ignoreCase: {ToCSharpBooleanLiteral(jsonMatcher.IgnoreCase)},");
|
||||
sb.AppendLine($" regex: {ToCSharpBooleanLiteral(jsonMatcher.Regex)}");
|
||||
sb.AppendLine(@" ))");
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -309,7 +304,7 @@ internal class MappingConverter
|
||||
Response = new ResponseModel()
|
||||
};
|
||||
|
||||
if (methodMatcher is { Methods: { } })
|
||||
if (methodMatcher != null)
|
||||
{
|
||||
mappingModel.Request.Methods = methodMatcher.Methods;
|
||||
mappingModel.Request.MethodsRejectOnMatch = methodMatcher.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : null;
|
||||
@@ -321,7 +316,7 @@ internal class MappingConverter
|
||||
mappingModel.Request.HttpVersion = httpVersionMatcher.HttpVersion;
|
||||
}
|
||||
|
||||
if (clientIPMatcher is { Matchers: { } })
|
||||
if (clientIPMatcher?.Matchers != null)
|
||||
{
|
||||
var clientIPMatchers = _mapper.Map(clientIPMatcher.Matchers);
|
||||
mappingModel.Request.Path = new ClientIPModel
|
||||
@@ -331,7 +326,7 @@ internal class MappingConverter
|
||||
};
|
||||
}
|
||||
|
||||
if (pathMatcher is { Matchers: { } })
|
||||
if (pathMatcher?.Matchers != null)
|
||||
{
|
||||
var pathMatchers = _mapper.Map(pathMatcher.Matchers);
|
||||
mappingModel.Request.Path = new PathModel
|
||||
@@ -340,7 +335,7 @@ internal class MappingConverter
|
||||
MatchOperator = pathMatchers?.Length > 1 ? pathMatcher.MatchOperator.ToString() : null
|
||||
};
|
||||
}
|
||||
else if (urlMatcher is { Matchers: { } })
|
||||
else if (urlMatcher?.Matchers != null)
|
||||
{
|
||||
var urlMatchers = _mapper.Map(urlMatcher.Matchers);
|
||||
mappingModel.Request.Url = new UrlModel
|
||||
@@ -538,7 +533,7 @@ internal class MappingConverter
|
||||
return stringMatchers.SelectMany(m => m.GetPatterns()).Select(p => p.GetPattern()).ToArray();
|
||||
}
|
||||
|
||||
private static string To1Or2Or3Arguments(string key, MatchBehaviour? matchBehaviour, IReadOnlyList<IStringMatcher> matchers)
|
||||
private static string To2Or3Arguments(string key, MatchBehaviour? matchBehaviour, IReadOnlyList<IStringMatcher> matchers)
|
||||
{
|
||||
var sb = new StringBuilder($"\"{key}\", ");
|
||||
|
||||
@@ -547,7 +542,7 @@ internal class MappingConverter
|
||||
sb.AppendFormat("{0}, ", matchBehaviour.Value.GetFullyQualifiedEnumValue());
|
||||
}
|
||||
|
||||
sb.AppendFormat("{0}", ToValueArguments(GetStringArray(matchers), string.Empty));
|
||||
sb.AppendFormat("{0}", MappingConverterUtils.ToCSharpCodeArguments(matchers));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
@@ -566,7 +561,16 @@ internal class MappingConverter
|
||||
|
||||
private static string To1Or2Arguments(MatchOperator? matchOperator, IReadOnlyList<IStringMatcher> matchers)
|
||||
{
|
||||
return To1Or2Arguments(matchOperator, GetStringArray(matchers), string.Empty);
|
||||
var sb = new StringBuilder();
|
||||
|
||||
if (matchOperator.HasValue && matchOperator != MatchOperator.Or)
|
||||
{
|
||||
sb.AppendFormat("{0}, ", matchOperator.Value.GetFullyQualifiedEnumValue());
|
||||
}
|
||||
|
||||
sb.AppendFormat("{0}", MappingConverterUtils.ToCSharpCodeArguments(matchers));
|
||||
|
||||
return sb.ToString();
|
||||
}
|
||||
|
||||
private static string To1Or2Arguments(MatchOperator? matchOperator, string[]? values, string defaultValue)
|
||||
|
||||
@@ -18,6 +18,7 @@ using WireMock.Http;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Owin;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Serialization;
|
||||
@@ -321,29 +322,27 @@ public partial class WireMockServer
|
||||
|
||||
InitSettings(_settings);
|
||||
|
||||
// _options
|
||||
if (settings.GlobalProcessingDelay != null)
|
||||
{
|
||||
_options.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
|
||||
}
|
||||
_options.AllowBodyForAllHttpMethods = settings.AllowBodyForAllHttpMethods;
|
||||
_options.AllowPartialMapping = settings.AllowPartialMapping;
|
||||
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
_options.MaxRequestLogCount = settings.MaxRequestLogCount;
|
||||
_options.RequestLogExpirationDuration = settings.RequestLogExpirationDuration;
|
||||
|
||||
// _settings & _options
|
||||
#if USE_ASPNETCORE
|
||||
if (Enum.TryParse<CorsPolicyOptions>(settings.CorsPolicyOptions, true, out var corsPolicyOptions))
|
||||
{
|
||||
_settings.CorsPolicyOptions = corsPolicyOptions;
|
||||
_options.CorsPolicyOptions = corsPolicyOptions;
|
||||
}
|
||||
|
||||
_options.ClientCertificateMode = _settings.ClientCertificateMode;
|
||||
_options.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate;
|
||||
#endif
|
||||
|
||||
WireMockMiddlewareOptionsHelper.InitFromSettings(_settings, _options, o =>
|
||||
{
|
||||
if (settings.GlobalProcessingDelay != null)
|
||||
{
|
||||
o.RequestProcessingDelay = TimeSpan.FromMilliseconds(settings.GlobalProcessingDelay.Value);
|
||||
}
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
o.CorsPolicyOptions = corsPolicyOptions;
|
||||
o.ClientCertificateMode = _settings.ClientCertificateMode;
|
||||
o.AcceptAnyClientCertificate = _settings.AcceptAnyClientCertificate;
|
||||
#endif
|
||||
});
|
||||
|
||||
return ResponseMessageBuilder.Create(200, "Settings updated");
|
||||
}
|
||||
#endregion Settings
|
||||
@@ -624,7 +623,7 @@ public partial class WireMockServer
|
||||
{
|
||||
var requestModel = DeserializeObject<RequestModel>(requestMessage);
|
||||
|
||||
var request = (Request)InitRequestBuilder(requestModel, false)!;
|
||||
var request = (Request)InitRequestBuilder(requestModel);
|
||||
|
||||
var dict = new Dictionary<ILogEntry, RequestMatchResult>();
|
||||
foreach (var logEntry in LogEntries.Where(le => !le.RequestMessage.Path.StartsWith("/__admin/")))
|
||||
|
||||
@@ -36,17 +36,13 @@ public partial class WireMockServer
|
||||
}
|
||||
}
|
||||
|
||||
private Guid? ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string? path = null)
|
||||
private Guid ConvertMappingAndRegisterAsRespondProvider(MappingModel mappingModel, Guid? guid = null, string? path = null)
|
||||
{
|
||||
Guard.NotNull(mappingModel);
|
||||
Guard.NotNull(mappingModel.Request);
|
||||
Guard.NotNull(mappingModel.Response);
|
||||
|
||||
var requestBuilder = InitRequestBuilder(mappingModel.Request, true);
|
||||
if (requestBuilder == null)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
var requestBuilder = InitRequestBuilder(mappingModel.Request);
|
||||
|
||||
var respondProvider = Given(requestBuilder, mappingModel.SaveToFile == true);
|
||||
|
||||
@@ -126,9 +122,9 @@ public partial class WireMockServer
|
||||
return respondProvider.Guid;
|
||||
}
|
||||
|
||||
private IRequestBuilder? InitRequestBuilder(RequestModel requestModel, bool pathOrUrlRequired)
|
||||
private IRequestBuilder InitRequestBuilder(RequestModel requestModel)
|
||||
{
|
||||
IRequestBuilder requestBuilder = Request.Create();
|
||||
var requestBuilder = Request.Create();
|
||||
|
||||
if (requestModel.ClientIP != null)
|
||||
{
|
||||
@@ -146,13 +142,11 @@ public partial class WireMockServer
|
||||
}
|
||||
}
|
||||
|
||||
bool pathOrUrlMatchersValid = false;
|
||||
if (requestModel.Path != null)
|
||||
{
|
||||
if (requestModel.Path is string path)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithPath(path);
|
||||
pathOrUrlMatchersValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -161,7 +155,6 @@ public partial class WireMockServer
|
||||
{
|
||||
var matchOperator = StringUtils.ParseMatchOperator(pathModel.MatchOperator);
|
||||
requestBuilder = requestBuilder.WithPath(matchOperator, pathModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
|
||||
pathOrUrlMatchersValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -170,7 +163,6 @@ public partial class WireMockServer
|
||||
if (requestModel.Url is string url)
|
||||
{
|
||||
requestBuilder = requestBuilder.WithUrl(url);
|
||||
pathOrUrlMatchersValid = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -179,17 +171,10 @@ public partial class WireMockServer
|
||||
{
|
||||
var matchOperator = StringUtils.ParseMatchOperator(urlModel.MatchOperator);
|
||||
requestBuilder = requestBuilder.WithUrl(matchOperator, urlModel.Matchers.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
|
||||
pathOrUrlMatchersValid = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (pathOrUrlRequired && !pathOrUrlMatchersValid)
|
||||
{
|
||||
_settings.Logger.Error("Path or Url matcher is missing for this mapping, this mapping will not be added.");
|
||||
return null;
|
||||
}
|
||||
|
||||
if (requestModel.Methods != null)
|
||||
{
|
||||
var matchBehaviour = requestModel.MethodsRejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||
@@ -233,7 +218,7 @@ public partial class WireMockServer
|
||||
{
|
||||
foreach (var paramModel in requestModel.Params.Where(p => p is { Matchers: { } }))
|
||||
{
|
||||
bool ignoreCase = paramModel.IgnoreCase == true;
|
||||
var ignoreCase = paramModel.IgnoreCase == true;
|
||||
requestBuilder = requestBuilder.WithParam(paramModel.Name, ignoreCase, paramModel.Matchers!.Select(_matcherMapper.Map).OfType<IStringMatcher>().ToArray());
|
||||
}
|
||||
}
|
||||
@@ -253,7 +238,7 @@ public partial class WireMockServer
|
||||
|
||||
private static IResponseBuilder InitResponseBuilder(ResponseModel responseModel)
|
||||
{
|
||||
IResponseBuilder responseBuilder = Response.Create();
|
||||
var responseBuilder = Response.Create();
|
||||
|
||||
if (responseModel.Delay > 0)
|
||||
{
|
||||
|
||||
@@ -20,7 +20,6 @@ using WireMock.Exceptions;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Http;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Models;
|
||||
using WireMock.Owin;
|
||||
using WireMock.RequestBuilders;
|
||||
@@ -369,9 +368,10 @@ public partial class WireMockServer : IWireMockServer
|
||||
}
|
||||
}
|
||||
|
||||
WireMockMiddlewareOptionsHelper.InitFromSettings(settings, _options);
|
||||
|
||||
_options.LogEntries.CollectionChanged += LogEntries_CollectionChanged;
|
||||
WireMockMiddlewareOptionsHelper.InitFromSettings(settings, _options, o =>
|
||||
{
|
||||
o.LogEntries.CollectionChanged += LogEntries_CollectionChanged;
|
||||
});
|
||||
|
||||
_matcherMapper = new MatcherMapper(_settings);
|
||||
_mappingConverter = new MappingConverter(_matcherMapper);
|
||||
@@ -649,13 +649,11 @@ public partial class WireMockServer : IWireMockServer
|
||||
{
|
||||
if (settings.AllowBodyForAllHttpMethods == true)
|
||||
{
|
||||
_options.AllowBodyForAllHttpMethods = _settings.AllowBodyForAllHttpMethods;
|
||||
_settings.Logger.Info("AllowBodyForAllHttpMethods is set to True");
|
||||
}
|
||||
|
||||
if (settings.AllowOnlyDefinedHttpStatusCodeInResponse == true)
|
||||
{
|
||||
_options.AllowOnlyDefinedHttpStatusCodeInResponse = _settings.AllowOnlyDefinedHttpStatusCodeInResponse;
|
||||
_settings.Logger.Info("AllowOnlyDefinedHttpStatusCodeInResponse is set to True");
|
||||
}
|
||||
|
||||
|
||||
@@ -198,7 +198,7 @@ internal class Transformer : ITransformer
|
||||
|
||||
private JToken ReplaceSingleNode(ITransformerContext transformerContext, ReplaceNodeOptions options, string stringValue, object model)
|
||||
{
|
||||
string transformedString = transformerContext.ParseAndRender(stringValue, model);
|
||||
var transformedString = transformerContext.ParseAndRender(stringValue, model);
|
||||
|
||||
if (!string.Equals(stringValue, transformedString))
|
||||
{
|
||||
@@ -346,7 +346,7 @@ internal class Transformer : ITransformer
|
||||
|
||||
private static IBodyData TransformBodyAsFile(ITransformerContext transformerContext, object model, IBodyData original, bool useTransformerForBodyAsFile)
|
||||
{
|
||||
string transformedBodyAsFilename = transformerContext.ParseAndRender(original.BodyAsFile!, model);
|
||||
var transformedBodyAsFilename = transformerContext.ParseAndRender(original.BodyAsFile!, model);
|
||||
|
||||
if (!useTransformerForBodyAsFile)
|
||||
{
|
||||
@@ -358,7 +358,7 @@ internal class Transformer : ITransformer
|
||||
};
|
||||
}
|
||||
|
||||
string text = transformerContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
||||
var text = transformerContext.FileSystemHandler.ReadResponseBodyAsString(transformedBodyAsFilename);
|
||||
return new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Text.RegularExpressions;
|
||||
using Stef.Validation;
|
||||
using WireMock.Constants;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
@@ -11,7 +11,7 @@ namespace WireMock.Util;
|
||||
/// </summary>
|
||||
internal static class HttpVersionParser
|
||||
{
|
||||
private static readonly Regex HttpVersionRegex = new(@"HTTP/(\d+(\.\d+)?(?!\.))", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled, TimeSpan.FromMilliseconds(100));
|
||||
private static readonly Regex HttpVersionRegex = new(@"HTTP/(\d+(\.\d+)?(?!\.))", RegexOptions.IgnoreCase | RegexOptions.CultureInvariant | RegexOptions.Compiled, WireMockConstants.DefaultRegexTimeout);
|
||||
|
||||
/// <summary>
|
||||
/// Try to extract the version (as a string) from the protocol.
|
||||
|
||||
23
src/WireMock.Net/Util/MappingConverterUtils.cs
Normal file
23
src/WireMock.Net/Util/MappingConverterUtils.cs
Normal file
@@ -0,0 +1,23 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using AnyOfTypes;
|
||||
using WireMock.Extensions;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Models;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
internal static class MappingConverterUtils
|
||||
{
|
||||
internal static string ToCSharpCodeArguments(IReadOnlyList<IMatcher> matchers)
|
||||
{
|
||||
return string.Join(", ", matchers.Select(m => m.GetCSharpCodeArguments()));
|
||||
}
|
||||
|
||||
internal static string ToCSharpCodeArguments(AnyOf<string, StringPattern>[] patterns)
|
||||
{
|
||||
return string.Join(", ", patterns.Select(p => CSharpFormatter.ToCSharpStringLiteral(p.GetPattern())));
|
||||
}
|
||||
}
|
||||
@@ -5,6 +5,7 @@ using System.Diagnostics.CodeAnalysis;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.RegularExpressions;
|
||||
using WireMock.Constants;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
@@ -13,7 +14,7 @@ namespace WireMock.Util;
|
||||
/// </summary>
|
||||
internal static class PortUtils
|
||||
{
|
||||
private static readonly Regex UrlDetailsRegex = new(@"^((?<proto>\w+)://)(?<host>[^/]+?):(?<port>\d+)\/?$", RegexOptions.Compiled);
|
||||
private static readonly Regex UrlDetailsRegex = new(@"^((?<proto>\w+)://)(?<host>[^/]+?):(?<port>\d+)\/?$", RegexOptions.Compiled, WireMockConstants.DefaultRegexTimeout);
|
||||
|
||||
/// <summary>
|
||||
/// Finds a free TCP port.
|
||||
|
||||
@@ -1,16 +1,14 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Text.RegularExpressions;
|
||||
using WireMock.Constants;
|
||||
using WireMock.RegularExpressions;
|
||||
|
||||
namespace WireMock.Util;
|
||||
|
||||
internal static class RegexUtils
|
||||
{
|
||||
private static readonly TimeSpan RegexTimeOut = new(0, 0, 10);
|
||||
|
||||
public static Dictionary<string, string> GetNamedGroups(Regex regex, string input)
|
||||
{
|
||||
var namedGroupsDictionary = new Dictionary<string, string>();
|
||||
@@ -38,11 +36,11 @@ internal static class RegexUtils
|
||||
{
|
||||
if (useRegexExtended)
|
||||
{
|
||||
var regexExtended = new RegexExtended(pattern!, RegexOptions.None, RegexTimeOut);
|
||||
var regexExtended = new RegexExtended(pattern!, RegexOptions.None, WireMockConstants.DefaultRegexTimeout);
|
||||
return (true, regexExtended.IsMatch(input));
|
||||
}
|
||||
|
||||
var regex = new Regex(pattern, RegexOptions.None, RegexTimeOut);
|
||||
var regex = new Regex(pattern, RegexOptions.None, WireMockConstants.DefaultRegexTimeout);
|
||||
return (true, regex.IsMatch(input));
|
||||
}
|
||||
catch
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.0.0" />
|
||||
<PackageReference Include="Aspire.Hosting.AppHost" Version="8.2.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -8,10 +8,7 @@ namespace WireMock.Net.Aspire.Tests;
|
||||
[ExcludeFromCodeCoverage]
|
||||
internal static class DockerUtils
|
||||
{
|
||||
public static bool IsDockerRunningLinuxContainerMode()
|
||||
{
|
||||
return IsDockerRunning() && IsLinuxContainerMode();
|
||||
}
|
||||
public static Lazy<bool> IsDockerRunningLinuxContainerMode => new(() => IsDockerRunning() && IsLinuxContainerMode());
|
||||
|
||||
private static bool IsDockerRunning()
|
||||
{
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
namespace WireMock.Net.Aspire.Tests.Facts;
|
||||
|
||||
public sealed class DockerIsRunningInLinuxContainerModeFact : FactAttribute
|
||||
{
|
||||
private const string SkipReason = "Docker is not running in Linux container mode. Skipping test.";
|
||||
|
||||
public DockerIsRunningInLinuxContainerModeFact()
|
||||
{
|
||||
if (!DockerUtils.IsDockerRunningLinuxContainerMode.Value)
|
||||
{
|
||||
Skip = SkipReason;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,6 +3,7 @@
|
||||
using System.Net.Http.Json;
|
||||
using FluentAssertions;
|
||||
using Projects;
|
||||
using WireMock.Net.Aspire.Tests.Facts;
|
||||
using Xunit.Abstractions;
|
||||
|
||||
namespace WireMock.Net.Aspire.Tests;
|
||||
@@ -11,15 +12,9 @@ public class IntegrationTests(ITestOutputHelper output)
|
||||
{
|
||||
private record WeatherForecast(DateOnly Date, int TemperatureC, string? Summary);
|
||||
|
||||
[Fact]
|
||||
[DockerIsRunningInLinuxContainerModeFact]
|
||||
public async Task StartAppHostWithWireMockAndCreateHttpClientToCallTheMockedWeatherForecastEndpoint()
|
||||
{
|
||||
if (!DockerUtils.IsDockerRunningLinuxContainerMode())
|
||||
{
|
||||
output.WriteLine("Docker is not running in Linux container mode. Skipping test.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrange
|
||||
var appHostBuilder = await DistributedApplicationTestingBuilder.CreateAsync<WireMock_Net_Aspire_TestAppHost>();
|
||||
await using var app = await appHostBuilder.BuildAsync();
|
||||
@@ -44,15 +39,9 @@ public class IntegrationTests(ITestOutputHelper output)
|
||||
weatherForecasts2.Should().HaveCount(5);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
[DockerIsRunningInLinuxContainerModeFact]
|
||||
public async Task StartAppHostWithWireMockAndCreateWireMockAdminClientToCallTheAdminEndpoint()
|
||||
{
|
||||
if (!DockerUtils.IsDockerRunningLinuxContainerMode())
|
||||
{
|
||||
output.WriteLine("Docker is not running in Linux container mode. Skipping test.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Arrange
|
||||
var appHostBuilder = await DistributedApplicationTestingBuilder.CreateAsync<WireMock_Net_Aspire_TestAppHost>();
|
||||
await using var app = await appHostBuilder.BuildAsync();
|
||||
|
||||
@@ -6,13 +6,14 @@
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<SonarQubeExclude>true</SonarQubeExclude>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="8.0.0" />
|
||||
<PackageReference Include="Aspire.Hosting.Testing" Version="8.2.0" />
|
||||
<PackageReference Include="Codecov" Version="1.13.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
|
||||
@@ -0,0 +1,25 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Mvc.Testing;
|
||||
|
||||
namespace WireMock.Net.Middleware.Tests;
|
||||
|
||||
internal class CustomWebApplicationFactory<TEntryPoint> : WebApplicationFactory<TEntryPoint>
|
||||
where TEntryPoint : class
|
||||
{
|
||||
private readonly List<(string Key, string Value)> _settings = new();
|
||||
|
||||
public CustomWebApplicationFactory(bool alwaysRedirectToWireMock = true)
|
||||
{
|
||||
_settings.Add(("AlwaysRedirectToWireMock", alwaysRedirectToWireMock.ToString().ToLowerInvariant()));
|
||||
}
|
||||
|
||||
protected override void ConfigureWebHost(IWebHostBuilder builder)
|
||||
{
|
||||
foreach (var arg in _settings)
|
||||
{
|
||||
builder.UseSetting(arg.Key, arg.Value);
|
||||
}
|
||||
}
|
||||
}
|
||||
49
test/WireMock.Net.Middleware.Tests/IntegrationTests.cs
Normal file
49
test/WireMock.Net.Middleware.Tests/IntegrationTests.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using FluentAssertions;
|
||||
using WireMock.Net.TestWebApplication;
|
||||
|
||||
namespace WireMock.Net.Middleware.Tests;
|
||||
|
||||
public class IntegrationTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData("/real1", "Hello 1 from WireMock.Net !")]
|
||||
[InlineData("/real2", "Hello 2 from WireMock.Net !")]
|
||||
public async Task CallingRealApi_WithAlwaysRedirectToWireMockIsTrue(string requestUri, string expectedResponse)
|
||||
{
|
||||
// Arrange
|
||||
await using var factory = new CustomWebApplicationFactory<Program>();
|
||||
using var client = factory.CreateClient();
|
||||
|
||||
// Act
|
||||
var response = await client.GetAsync(requestUri);
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||
stringResponse.Should().Be(expectedResponse);
|
||||
}
|
||||
|
||||
[Theory]
|
||||
[InlineData("/real1", "Hello 1 from WireMock.Net !")]
|
||||
[InlineData("/real2", "Hello 2 from WireMock.Net !")]
|
||||
public async Task CallingRealApi_WithAlwaysRedirectToWireMockIsFalse(string requestUri, string expectedResponse)
|
||||
{
|
||||
// Arrange
|
||||
await using var factory = new CustomWebApplicationFactory<Program>(false);
|
||||
using var client = factory.CreateClient();
|
||||
|
||||
var request = new HttpRequestMessage(HttpMethod.Get, requestUri);
|
||||
request.Headers.Add("X-WireMock-Redirect", "true");
|
||||
request.Headers.Add("X-WireMock-Response-Delay", "10");
|
||||
|
||||
// Act
|
||||
var response = await client.SendAsync(request);
|
||||
|
||||
// Assert
|
||||
response.EnsureSuccessStatusCode();
|
||||
var stringResponse = await response.Content.ReadAsStringAsync();
|
||||
stringResponse.Should().Be(expectedResponse);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,43 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsPackable>false</IsPackable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Codecov" Version="1.13.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="coverlet.collector" Version="6.0.2">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="6.12.0" />
|
||||
<PackageReference Include="Microsoft.AspNetCore.Mvc.Testing" Version="8.0.8" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="17.10.0" />
|
||||
<PackageReference Include="Moq" Version="4.20.70" />
|
||||
<PackageReference Include="xunit" Version="2.8.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.8.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||
</PackageReference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\WireMock.Net.TestWebApplication\WireMock.Net.TestWebApplication.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Using Include="Xunit" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
37
test/WireMock.Net.TUnitTests/TUnitTests.cs
Normal file
37
test/WireMock.Net.TUnitTests/TUnitTests.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using WireMock.Net.TUnit;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.TUnitTests;
|
||||
|
||||
// ReSharper disable once InconsistentNaming
|
||||
public class TUnitTests
|
||||
{
|
||||
[Test]
|
||||
public async Task Test_TUnitWireMockLogger()
|
||||
{
|
||||
// Assign
|
||||
var path = $"/foo_{Guid.NewGuid()}";
|
||||
|
||||
using var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Logger = new TUnitWireMockLogger(TestContext.Current!.GetDefaultLogger())
|
||||
});
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.WithPath(path)
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create().WithBody("TUnit"));
|
||||
|
||||
// Act
|
||||
var response = await server.CreateClient().GetStringAsync($"{server.Url}{path}");
|
||||
|
||||
// Assert
|
||||
await Assert.That(response).IsEqualTo("TUnit");
|
||||
}
|
||||
}
|
||||
20
test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj
Normal file
20
test/WireMock.Net.TUnitTests/WireMock.Net.TUnitTests.csproj
Normal file
@@ -0,0 +1,20 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<IsTestProject>true</IsTestProject>
|
||||
<SonarQubeExclude>true</SonarQubeExclude>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="TUnit" Version="0.1.817" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.TUnit\WireMock.Net.TUnit.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
49
test/WireMock.Net.TestWebApplication/Program.cs
Normal file
49
test/WireMock.Net.TestWebApplication/Program.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using WireMock.Net.AspNetCore.Middleware;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
|
||||
namespace WireMock.Net.TestWebApplication;
|
||||
|
||||
// Make the implicit Program class public so test projects can access it.
|
||||
public class Program
|
||||
{
|
||||
public static async Task Main(string[] args)
|
||||
{
|
||||
var alwaysRedirectToWireMock = args.Contains("--AlwaysRedirectToWireMock=true");
|
||||
|
||||
var builder = WebApplication.CreateBuilder(args);
|
||||
|
||||
builder.Services.AddWireMockService(server =>
|
||||
{
|
||||
server.Given(Request.Create()
|
||||
.WithPath("/test1")
|
||||
.UsingAnyMethod()
|
||||
).RespondWith(Response.Create()
|
||||
.WithBody("Hello 1 from WireMock.Net !")
|
||||
);
|
||||
|
||||
server.Given(Request.Create()
|
||||
.WithPath("/test2")
|
||||
.UsingAnyMethod()
|
||||
).RespondWith(Response.Create()
|
||||
.WithBody("Hello 2 from WireMock.Net !")
|
||||
);
|
||||
}, alwaysRedirectToWireMock);
|
||||
|
||||
var app = builder.Build();
|
||||
|
||||
app.MapGet("/real1", async (HttpClient client) =>
|
||||
{
|
||||
var result = await client.GetStringAsync("https://real-api:12345/test1");
|
||||
return result;
|
||||
});
|
||||
|
||||
app.MapGet("/real2", async (IHttpClientFactory factory) =>
|
||||
{
|
||||
using var client = factory.CreateClient();
|
||||
return await client.GetStringAsync("https://real-api:12345/test2");
|
||||
});
|
||||
|
||||
await app.RunAsync();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"profiles": {
|
||||
"WireMock.Net.TestWebApplication": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "https://localhost:57712;http://localhost:57713"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<Nullable>enable</Nullable>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.AspNetCore.Middleware\WireMock.Net.AspNetCore.Middleware.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
9
test/WireMock.Net.TestWebApplication/appsettings.json
Normal file
9
test/WireMock.Net.TestWebApplication/appsettings.json
Normal file
@@ -0,0 +1,9 @@
|
||||
{
|
||||
"Logging": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug",
|
||||
"Microsoft.AspNetCore": "Warning"
|
||||
}
|
||||
},
|
||||
"AllowedHosts": "*"
|
||||
}
|
||||
@@ -47,6 +47,7 @@ message HelloReply {
|
||||
.WithPath("/grpc/greet.Greeter/SayHello")
|
||||
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloRequest", protoBufJsonMatcher)
|
||||
)
|
||||
.WithGuid(_guidUtilsMock.Object.NewGuid())
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "application/grpc")
|
||||
.WithBodyAsProtoBuf(ProtoDefinition, "greet.HelloReply",
|
||||
@@ -66,6 +67,7 @@ message HelloReply {
|
||||
.WithBodyAsProtoBuf("greet.HelloRequest", protoBufJsonMatcher)
|
||||
)
|
||||
.WithProtoDefinition(ProtoDefinition)
|
||||
.WithGuid(_guidUtilsMock.Object.NewGuid())
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "application/grpc")
|
||||
.WithBodyAsProtoBuf("greet.HelloReply",
|
||||
@@ -86,6 +88,7 @@ message HelloReply {
|
||||
.WithBodyAsProtoBuf("greet.HelloRequest", protoBufJsonMatcher)
|
||||
)
|
||||
.WithProtoDefinition("my-greeter")
|
||||
.WithGuid(_guidUtilsMock.Object.NewGuid())
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "application/grpc")
|
||||
.WithBodyAsProtoBuf("greet.HelloReply",
|
||||
@@ -106,6 +109,7 @@ message HelloReply {
|
||||
.WithBodyAsProtoBuf("greet.HelloRequest")
|
||||
)
|
||||
.WithProtoDefinition("my-greeter")
|
||||
.WithGuid(_guidUtilsMock.Object.NewGuid())
|
||||
.RespondWith(Response.Create()
|
||||
.WithHeader("Content-Type", "application/grpc")
|
||||
.WithBodyAsProtoBuf("greet.HelloReply",
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("GET")
|
||||
.WithPath("/foo1")
|
||||
.WithParam("p1", "xyz")
|
||||
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/foo1", false, WireMock.Matchers.MatchOperator.Or))
|
||||
.WithParam("p1", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "xyz"))
|
||||
)
|
||||
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
|
||||
.RespondWith(Response.Create()
|
||||
|
||||
@@ -2,25 +2,7 @@
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("POST")
|
||||
.WithPath("/users/post1")
|
||||
.WithBody(new JsonMatcher(
|
||||
value: new
|
||||
{
|
||||
city = "Amsterdam",
|
||||
country = "The Netherlands"
|
||||
},
|
||||
ignoreCase: false,
|
||||
regex: false
|
||||
))
|
||||
)
|
||||
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
|
||||
.RespondWith(Response.Create()
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("POST")
|
||||
.WithPath("/users/post2")
|
||||
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/users/post2", false, WireMock.Matchers.MatchOperator.Or))
|
||||
.WithBody(new JsonPartialMatcher(
|
||||
value: new
|
||||
{
|
||||
@@ -37,23 +19,11 @@ server
|
||||
Some ""value"" in Line2")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("GET")
|
||||
.WithPath("/foo1")
|
||||
.WithParam("p1", "xyz")
|
||||
)
|
||||
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("1")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("POST")
|
||||
.WithPath("/foo2")
|
||||
.WithParam("p2", "abc")
|
||||
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/foo2", false, WireMock.Matchers.MatchOperator.Or))
|
||||
.WithParam("p2", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "abc"))
|
||||
.WithHeader("h1", "W/\"234f2q3r\"", true)
|
||||
)
|
||||
.WithGuid("4126dec8-470b-4eff-93bb-c24f83b8b1fd")
|
||||
@@ -64,10 +34,28 @@ server
|
||||
.WithBody("2")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("POST")
|
||||
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/users/post1", false, WireMock.Matchers.MatchOperator.Or))
|
||||
.WithBody(new JsonMatcher(
|
||||
value: new
|
||||
{
|
||||
city = "Amsterdam",
|
||||
country = "The Netherlands"
|
||||
},
|
||||
ignoreCase: false,
|
||||
regex: false
|
||||
))
|
||||
)
|
||||
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
|
||||
.RespondWith(Response.Create()
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("DELETE")
|
||||
.WithUrl("https://localhost/test")
|
||||
.WithUrl(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "https://localhost/test", false, WireMock.Matchers.MatchOperator.Or))
|
||||
)
|
||||
.WithGuid("c9929240-7ae8-4a5d-8ed8-0913479f6eeb")
|
||||
.RespondWith(Response.Create()
|
||||
@@ -108,3 +96,15 @@ text
|
||||
})
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create()
|
||||
.UsingMethod("GET")
|
||||
.WithPath(new WildcardMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, "/foo1", false, WireMock.Matchers.MatchOperator.Or))
|
||||
.WithParam("p1", new ExactMatcher(WireMock.Matchers.MatchBehaviour.AcceptOnMatch, false, WireMock.Matchers.MatchOperator.And, "xyz"))
|
||||
)
|
||||
.WithGuid("f74fd144-df53-404f-8e35-da22a640bd5f")
|
||||
.RespondWith(Response.Create()
|
||||
.WithStatusCode(200)
|
||||
.WithBody("1")
|
||||
);
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.AdminApi;
|
||||
@@ -39,6 +40,14 @@ public partial class WireMockAdminApiTests
|
||||
{
|
||||
private static readonly VerifySettings VerifySettings = new();
|
||||
|
||||
private readonly Mock<IGuidUtils> _guidUtilsMock = new();
|
||||
|
||||
public WireMockAdminApiTests()
|
||||
{
|
||||
var startGuid = 1000;
|
||||
_guidUtilsMock.Setup(g => g.NewGuid()).Returns(() => new Guid($"98fae52e-76df-47d9-876f-2ee32e93{startGuid++}"));
|
||||
}
|
||||
|
||||
static WireMockAdminApiTests()
|
||||
{
|
||||
VerifyNewtonsoftJson.Enable(VerifySettings);
|
||||
|
||||
@@ -0,0 +1,22 @@
|
||||
// Copyright © WireMock.Net
|
||||
|
||||
using System;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.Facts;
|
||||
|
||||
public sealed class IgnoreOnContinuousIntegrationFact : FactAttribute
|
||||
{
|
||||
private const string SkipReason = "Ignore when run via CI/CD";
|
||||
private static readonly bool IsContinuousIntegrationAzure = bool.TryParse(Environment.GetEnvironmentVariable("TF_BUILD"), out var isTF) && isTF;
|
||||
private static readonly bool IsContinuousIntegrationGithub = bool.TryParse(Environment.GetEnvironmentVariable("GITHUB_ACTIONS"), out var isGH) && isGH;
|
||||
private static readonly bool IsContinuousIntegration = IsContinuousIntegrationAzure || IsContinuousIntegrationGithub;
|
||||
|
||||
public IgnoreOnContinuousIntegrationFact()
|
||||
{
|
||||
if (IsContinuousIntegration)
|
||||
{
|
||||
Skip = SkipReason;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -49,6 +49,26 @@ public class HttpRequestMessageHelperTests
|
||||
Check.That(await message.Content.ReadAsByteArrayAsync().ConfigureAwait(false)).ContainsExactly(Encoding.UTF8.GetBytes("hi"));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpRequestMessageHelper_Create_TextPlain()
|
||||
{
|
||||
// Assign
|
||||
var body = new BodyData
|
||||
{
|
||||
BodyAsString = "0123", // or 83 in decimal
|
||||
BodyAsJson = 83,
|
||||
DetectedBodyType = BodyType.Json,
|
||||
DetectedBodyTypeFromContentType = BodyType.String
|
||||
};
|
||||
var request = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", ClientIp, body);
|
||||
|
||||
// Act
|
||||
var message = HttpRequestMessageHelper.Create(request, "http://url");
|
||||
|
||||
// Assert
|
||||
Check.That(await message.Content!.ReadAsStringAsync().ConfigureAwait(false)).Equals("0123");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task HttpRequestMessageHelper_Create_Json()
|
||||
{
|
||||
@@ -64,7 +84,7 @@ public class HttpRequestMessageHelperTests
|
||||
var message = HttpRequestMessageHelper.Create(request, "http://url");
|
||||
|
||||
// Assert
|
||||
Check.That(await message.Content.ReadAsStringAsync().ConfigureAwait(false)).Equals("{\"x\":42}");
|
||||
Check.That(await message.Content!.ReadAsStringAsync().ConfigureAwait(false)).Equals("{\"x\":42}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
|
||||
@@ -32,6 +32,35 @@
|
||||
Body: { msg: "Hello world!"}
|
||||
}
|
||||
},
|
||||
{
|
||||
Guid: 98fae52e-76df-47d9-876f-2ee32e931001,
|
||||
UpdatedAt: 2023-01-14 15:16:17,
|
||||
Request: {
|
||||
Path: {
|
||||
Matchers: [
|
||||
{
|
||||
Name: WildcardMatcher,
|
||||
Pattern: /users/post1,
|
||||
IgnoreCase: false
|
||||
}
|
||||
]
|
||||
},
|
||||
Methods: [
|
||||
POST
|
||||
],
|
||||
Body: {
|
||||
Matcher: {
|
||||
Name: JsonMatcher,
|
||||
Pattern: {
|
||||
Request: Hello?
|
||||
},
|
||||
IgnoreCase: false,
|
||||
Regex: false
|
||||
}
|
||||
}
|
||||
},
|
||||
Response: {}
|
||||
},
|
||||
{
|
||||
Guid: 98fae52e-76df-47d9-876f-2ee32e931002,
|
||||
UpdatedAt: 2023-01-14 15:16:17,
|
||||
@@ -106,31 +135,33 @@
|
||||
Response: {}
|
||||
},
|
||||
{
|
||||
Guid: 98fae52e-76df-47d9-876f-2ee32e931001,
|
||||
Guid: 98fae52e-76df-47d9-876f-2ee32e931004,
|
||||
UpdatedAt: 2023-01-14 15:16:17,
|
||||
Request: {
|
||||
Path: {
|
||||
Matchers: [
|
||||
{
|
||||
Name: WildcardMatcher,
|
||||
Pattern: /users/post1,
|
||||
Pattern: /regex,
|
||||
IgnoreCase: false
|
||||
}
|
||||
]
|
||||
},
|
||||
Methods: [
|
||||
POST
|
||||
GET
|
||||
],
|
||||
Body: {
|
||||
Matcher: {
|
||||
Name: JsonMatcher,
|
||||
Pattern: {
|
||||
Request: Hello?
|
||||
},
|
||||
IgnoreCase: false,
|
||||
Regex: false
|
||||
Params: [
|
||||
{
|
||||
Name: foo,
|
||||
Matchers: [
|
||||
{
|
||||
Name: RegexMatcher,
|
||||
Pattern: .*,
|
||||
IgnoreCase: false
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
]
|
||||
},
|
||||
Response: {}
|
||||
}
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user