mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-05-05 07:24:28 +02:00
Compare commits
75 Commits
1.5.12
...
stef-Ignor
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
dabe3a2a10 | ||
|
|
1f1bc05f00 | ||
|
|
c107e38e3b | ||
|
|
b609191095 | ||
|
|
b1ae9aaf46 | ||
|
|
a77c4fe1ac | ||
|
|
ad3ef83c5e | ||
|
|
35ffbbc7d9 | ||
|
|
c1e71707c5 | ||
|
|
69499afe43 | ||
|
|
aadac78577 | ||
|
|
71393204cc | ||
|
|
e5cc6f570c | ||
|
|
7c3a0c815d | ||
|
|
e61f08fe48 | ||
|
|
11f4c47851 | ||
|
|
3956cd703b | ||
|
|
27682d0ce4 | ||
|
|
8444c8c506 | ||
|
|
6ef116a295 | ||
|
|
59195eaed8 | ||
|
|
7d9e450814 | ||
|
|
7019a5a78c | ||
|
|
d29f3e81f3 | ||
|
|
ccd8026884 | ||
|
|
1214ba5108 | ||
|
|
427715a38a | ||
|
|
d949dfb64c | ||
|
|
0a2763c06e | ||
|
|
9ef8bd0b7b | ||
|
|
090e0eb437 | ||
|
|
f3d52adbb2 | ||
|
|
a8775c3b77 | ||
|
|
3e24e3452b | ||
|
|
95bf8e31aa | ||
|
|
090989ea7f | ||
|
|
651486f718 | ||
|
|
9dea577da1 | ||
|
|
7ca4294de6 | ||
|
|
66245409f9 | ||
|
|
da6cb9fe0a | ||
|
|
b30e4faab6 | ||
|
|
1221d52c69 | ||
|
|
52d2109c7e | ||
|
|
30064b922b | ||
|
|
78b94d2ebc | ||
|
|
19701f5260 | ||
|
|
1269fb178f | ||
|
|
7426bf76ee | ||
|
|
36c9d95abb | ||
|
|
674fa89c3e | ||
|
|
61cdc13fae | ||
|
|
c344b73f45 | ||
|
|
2ac9ca207a | ||
|
|
f099f3a288 | ||
|
|
02b607cc95 | ||
|
|
7ac89e85b7 | ||
|
|
cc4cf27101 | ||
|
|
6839b11d35 | ||
|
|
1000f4409f | ||
|
|
7fe2c8af78 | ||
|
|
0fc664b404 | ||
|
|
770a670e53 | ||
|
|
b4c8779d68 | ||
|
|
c85eaf1072 | ||
|
|
b2a8178161 | ||
|
|
20eb37b0c8 | ||
|
|
742f1d1f0a | ||
|
|
d8927b88c8 | ||
|
|
7ab136557a | ||
|
|
3d17913f35 | ||
|
|
9ed6a75384 | ||
|
|
9606fee8cb | ||
|
|
6b03dfaa8c | ||
|
|
e2f3ffd33a |
2
.gitignore
vendored
2
.gitignore
vendored
@@ -255,3 +255,5 @@ paket-files/
|
|||||||
/test/WireMock.Net.Tests/coverage.opencover.xml
|
/test/WireMock.Net.Tests/coverage.opencover.xml
|
||||||
/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
||||||
/test/WireMock.Net.Tests/coverage.net5.0.opencover.xml
|
/test/WireMock.Net.Tests/coverage.net5.0.opencover.xml
|
||||||
|
|
||||||
|
*.received.*
|
||||||
90
CHANGELOG.md
90
CHANGELOG.md
@@ -1,3 +1,88 @@
|
|||||||
|
# 1.5.27 (03 June 2023)
|
||||||
|
- [#946](https://github.com/WireMock-Net/WireMock.Net/pull/946) - Add warning logging when sending a request to a Webhook does not return status 200 [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#949](https://github.com/WireMock-Net/WireMock.Net/pull/949) - Add ".NET Framework 4.7" to WireMock.Net.FluentAssertions [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#928](https://github.com/WireMock-Net/WireMock.Net/issues/928) - TypeLoadException when using WithHeader method. [bug]
|
||||||
|
- [#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)
|
||||||
|
- [#941](https://github.com/WireMock-Net/WireMock.Net/issues/941) - RequestMessage.GetParameter method missing from IRequestMessage interface [feature]
|
||||||
|
|
||||||
|
# 1.5.25 (13 May 2023)
|
||||||
|
- [#934](https://github.com/WireMock-Net/WireMock.Net/pull/934) - Code generator improvements [feature] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||||
|
|
||||||
|
# 1.5.24 (07 May 2023)
|
||||||
|
- [#926](https://github.com/WireMock-Net/WireMock.Net/pull/926) - Fix C# mapping code generator for header names [bug] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||||
|
- [#927](https://github.com/WireMock-Net/WireMock.Net/pull/927) - Enrich generated code with status code [feature] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||||
|
- [#930](https://github.com/WireMock-Net/WireMock.Net/pull/930) - Update C# mapping code generator for WithStatusCode [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#931](https://github.com/WireMock-Net/WireMock.Net/pull/931) - Add property 'IsStartedWithAdminInterface' to 'IWireMockServer' [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#933](https://github.com/WireMock-Net/WireMock.Net/pull/933) - C# code generator improvements [feature] contributed by [cezarypiatek](https://github.com/cezarypiatek)
|
||||||
|
|
||||||
|
# 1.5.23 (23 April 2023)
|
||||||
|
- [#922](https://github.com/WireMock-Net/WireMock.Net/pull/922) - Add WithProbability [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#924](https://github.com/WireMock-Net/WireMock.Net/pull/924) - Allow removal of prefix when proxying to another server (#630) [feature] contributed by [nudejustin](https://github.com/nudejustin)
|
||||||
|
- [#925](https://github.com/WireMock-Net/WireMock.Net/pull/925) - Add IgnoreCase option to ProxyUrlReplaceSettings [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
|
# 1.5.22 (08 April 2023)
|
||||||
|
- [#914](https://github.com/WireMock-Net/WireMock.Net/pull/914) - #912 add excluded params to proxy mapping [feature] contributed by [walidhaidarii](https://github.com/walidhaidarii)
|
||||||
|
- [#916](https://github.com/WireMock-Net/WireMock.Net/pull/916) - Include WireMockOpenApiParser project [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#912](https://github.com/WireMock-Net/WireMock.Net/issues/912) - Feature: adding excluded params to proxy and records settings [feature]
|
||||||
|
|
||||||
|
# 1.5.21 (22 March 2023)
|
||||||
|
- [#908](https://github.com/WireMock-Net/WireMock.Net/pull/908) - RequestBuilder : add WithBodyAsJson and WithBody (with IJsonConverter) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#911](https://github.com/WireMock-Net/WireMock.Net/pull/911) - Fixed QueryStringParser for UrlEncoded values [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#901](https://github.com/WireMock-Net/WireMock.Net/issues/901) - Matching one form-urlencoded value [feature]
|
||||||
|
|
||||||
|
# 1.5.20 (19 March 2023)
|
||||||
|
- [#905](https://github.com/WireMock-Net/WireMock.Net/pull/905) - Add DeserializeFormUrl Encoded to the settings [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#907](https://github.com/WireMock-Net/WireMock.Net/pull/907) - Fix issue with application/x-www-form-urlencoded and ExactMatcher [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#906](https://github.com/WireMock-Net/WireMock.Net/issues/906) - Upgrade to 1.5.19 breaks a form data test [bug]
|
||||||
|
|
||||||
|
# 1.5.19 (17 March 2023)
|
||||||
|
- [#903](https://github.com/WireMock-Net/WireMock.Net/pull/903) - Add WithBody with IDictionary (form-urlencoded values) [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#904](https://github.com/WireMock-Net/WireMock.Net/pull/904) - Update Handlebars.Net.Helpers to 2.3.15 [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
|
# 1.5.18 (09 March 2023)
|
||||||
|
- [#893](https://github.com/WireMock-Net/WireMock.Net/pull/893) - Add 'Data' to response which can be used during transforming the response [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#896](https://github.com/WireMock-Net/WireMock.Net/pull/896) - Bump Microsoft.Owin from 2.0.2 to 4.2.2 in /examples/WireMock.Net.Service [dependencies] contributed by [dependabot[bot]](https://github.com/apps/dependabot)
|
||||||
|
- [#900](https://github.com/WireMock-Net/WireMock.Net/pull/900) - ProxySettings : Add logic to not save some requests depending on HttpMethods [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#897](https://github.com/WireMock-Net/WireMock.Net/issues/897) - WebHostBuilder.ConfigureServices method not found when using nunit3testadapter 4.4.0 [bug]
|
||||||
|
- [#899](https://github.com/WireMock-Net/WireMock.Net/issues/899) - Ignore OPTIONS request when using proxyandrecord [feature]
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
- [#880](https://github.com/WireMock-Net/WireMock.Net/pull/880) - Add `WithProxy(string proxyUrl, X509Certificate2 certificate)` [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#879](https://github.com/WireMock-Net/WireMock.Net/issues/879) - Possibility to pass a X509Certificate2 to WithProxy() or specifiy certificate loading options [feature]
|
||||||
|
|
||||||
|
# 1.5.15 (29 January 2023)
|
||||||
|
- [#878](https://github.com/WireMock-Net/WireMock.Net/pull/878) - Update REST Admin interface to support "Get Mapping(s) as C# Code" [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
|
||||||
|
# 1.5.14 (24 January 2023)
|
||||||
|
- [#842](https://github.com/WireMock-Net/WireMock.Net/pull/842) - Generate C# code from Mapping [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#869](https://github.com/WireMock-Net/WireMock.Net/pull/869) - Add MappingBuilder to build mappings in code and export to Models or JSON [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#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]
|
||||||
|
|
||||||
|
# 1.5.13 (11 December 2022)
|
||||||
|
- [#858](https://github.com/WireMock-Net/WireMock.Net/pull/858) - Update Transformer functionality to return value instead of string [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#859](https://github.com/WireMock-Net/WireMock.Net/pull/859) - Add UpdatedAt property to Mapping [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#861](https://github.com/WireMock-Net/WireMock.Net/pull/861) - Add extra functionality for issue 55 contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#862](https://github.com/WireMock-Net/WireMock.Net/pull/862) - Add client certificate support [feature] contributed by [billybraga](https://github.com/billybraga)
|
||||||
|
- [#863](https://github.com/WireMock-Net/WireMock.Net/pull/863) - Update WireMockServer.CreateClient/CreateClients to include handlers [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
|
- [#856](https://github.com/WireMock-Net/WireMock.Net/issues/856) - Inconsistent result with overlapping (duplicate) request [bug]
|
||||||
|
|
||||||
# 1.5.12 (03 December 2022)
|
# 1.5.12 (03 December 2022)
|
||||||
- [#851](https://github.com/WireMock-Net/WireMock.Net/pull/851) - Fix Linux CI build + Fix opencover [feature] contributed by [StefH](https://github.com/StefH)
|
- [#851](https://github.com/WireMock-Net/WireMock.Net/pull/851) - Fix Linux CI build + Fix opencover [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
- [#853](https://github.com/WireMock-Net/WireMock.Net/pull/853) - Add .Net 7 [feature] contributed by [StefH](https://github.com/StefH)
|
- [#853](https://github.com/WireMock-Net/WireMock.Net/pull/853) - Add .Net 7 [feature] contributed by [StefH](https://github.com/StefH)
|
||||||
@@ -625,8 +710,8 @@
|
|||||||
- [#263](https://github.com/WireMock-Net/WireMock.Net/issues/263) - Content-Type multipart/form-data is not serialized in proxy and recording mode [bug]
|
- [#263](https://github.com/WireMock-Net/WireMock.Net/issues/263) - Content-Type multipart/form-data is not serialized in proxy and recording mode [bug]
|
||||||
|
|
||||||
# 1.0.11.0 (30 March 2019)
|
# 1.0.11.0 (30 March 2019)
|
||||||
- [#261](https://github.com/WireMock-Net/WireMock.Net/pull/261) - Fix BodyAsJson transform bug in ResponseMessageTransformer contributed by [psypilat](https://github.com/psypilat)
|
- [#261](https://github.com/WireMock-Net/WireMock.Net/pull/261) - Fix BodyAsJson transform bug in ResponseMessageTransformer contributed by [ghost](https://github.com/ghost)
|
||||||
- [#262](https://github.com/WireMock-Net/WireMock.Net/pull/262) - Add ProvideResponse_WithJsonBodyAndTransform test contributed by [psypilat](https://github.com/psypilat)
|
- [#262](https://github.com/WireMock-Net/WireMock.Net/pull/262) - Add ProvideResponse_WithJsonBodyAndTransform test contributed by [ghost](https://github.com/ghost)
|
||||||
|
|
||||||
# 1.0.10.0 (27 March 2019)
|
# 1.0.10.0 (27 March 2019)
|
||||||
- [#260](https://github.com/WireMock-Net/WireMock.Net/pull/260) - Fix Response.Delay property serialization [bug] contributed by [StefH](https://github.com/StefH)
|
- [#260](https://github.com/WireMock-Net/WireMock.Net/pull/260) - Fix Response.Delay property serialization [bug] contributed by [StefH](https://github.com/StefH)
|
||||||
@@ -915,6 +1000,7 @@
|
|||||||
- [#45](https://github.com/WireMock-Net/WireMock.Net/pull/45) - Add RequestLogExpirationDuration and MaxRequestLogCount (#43) contributed by [StefH](https://github.com/StefH)
|
- [#45](https://github.com/WireMock-Net/WireMock.Net/pull/45) - Add RequestLogExpirationDuration and MaxRequestLogCount (#43) contributed by [StefH](https://github.com/StefH)
|
||||||
- [#51](https://github.com/WireMock-Net/WireMock.Net/pull/51) - Observable logs contributed by [dmtrrk](https://github.com/dmtrrk)
|
- [#51](https://github.com/WireMock-Net/WireMock.Net/pull/51) - Observable logs contributed by [dmtrrk](https://github.com/dmtrrk)
|
||||||
- [#15](https://github.com/WireMock-Net/WireMock.Net/issues/15) - New feature: Proxying [feature]
|
- [#15](https://github.com/WireMock-Net/WireMock.Net/issues/15) - New feature: Proxying [feature]
|
||||||
|
- [#20](https://github.com/WireMock-Net/WireMock.Net/issues/20) - Add client certificate authentication [feature]
|
||||||
- [#31](https://github.com/WireMock-Net/WireMock.Net/issues/31) - Feature request: Nuget package for standalone version [feature]
|
- [#31](https://github.com/WireMock-Net/WireMock.Net/issues/31) - Feature request: Nuget package for standalone version [feature]
|
||||||
- [#33](https://github.com/WireMock-Net/WireMock.Net/issues/33) - Issue with launching sample code (StandAlone server) [bug]
|
- [#33](https://github.com/WireMock-Net/WireMock.Net/issues/33) - Issue with launching sample code (StandAlone server) [bug]
|
||||||
- [#38](https://github.com/WireMock-Net/WireMock.Net/issues/38) - Bug: support also listening on *:{port}
|
- [#38](https://github.com/WireMock-Net/WireMock.Net/issues/38) - Bug: support also listening on *:{port}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<VersionPrefix>1.5.12</VersionPrefix>
|
<VersionPrefix>1.5.27</VersionPrefix>
|
||||||
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
<PackageIcon>WireMock.Net-Logo.png</PackageIcon>
|
||||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||||
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
|
||||||
@@ -12,6 +12,7 @@
|
|||||||
<RepositoryType>git</RepositoryType>
|
<RepositoryType>git</RepositoryType>
|
||||||
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
|
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
|
||||||
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
||||||
|
<PackageReadmeFile>PackageReadme.md</PackageReadmeFile>
|
||||||
<LangVersion>Latest</LangVersion>
|
<LangVersion>Latest</LangVersion>
|
||||||
<Nullable>enable</Nullable>
|
<Nullable>enable</Nullable>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
@@ -29,7 +30,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<None Include="../../resources/WireMock.Net-Logo.png" Pack="true" PackagePath="" />
|
<None Include="../../resources/WireMock.Net-Logo.png" Pack="true" PackagePath="" />
|
||||||
<!--<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>-->
|
<None Include="../../PackageReadme.md" Pack="true" PackagePath=""/>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<Choose>
|
<Choose>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
rem https://github.com/StefH/GitHubReleaseNotes
|
rem https://github.com/StefH/GitHubReleaseNotes
|
||||||
|
|
||||||
SET version=1.5.12
|
SET version=1.5.27
|
||||||
|
|
||||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc duplicate --version %version% --token %GH_TOKEN%
|
||||||
|
|
||||||
|
|||||||
55
PackageReadme.md
Normal file
55
PackageReadme.md
Normal file
@@ -0,0 +1,55 @@
|
|||||||
|
## WireMock.Net
|
||||||
|
Lightweight Http Mocking Server for .NET, inspired by [WireMock(http://WireMock.org) from the Java landscape.
|
||||||
|
|
||||||
|
### :star: Key Features
|
||||||
|
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
||||||
|
* Library can be used in unit tests and integration tests
|
||||||
|
* Runs as a standalone process, as windows service, as Azure/IIS or as docker
|
||||||
|
* Configurable via a fluent C# .NET API, JSON files and JSON over HTTP
|
||||||
|
* Record/playback of stubs (proxying)
|
||||||
|
* Per-request conditional proxying
|
||||||
|
* Stateful behaviour simulation
|
||||||
|
* Response templating / transformation using Handlebars and extensions
|
||||||
|
* Can be used locally or in CI/CD scenarios
|
||||||
|
|
||||||
|
### :star: Stubbing
|
||||||
|
A core feature of WireMock.Net is the ability to return predefined HTTP responses for requests matching criteria.
|
||||||
|
See [Wiki : Stubbing](https://github.com/WireMock-Net/WireMock.Net/wiki/Stubbing).
|
||||||
|
|
||||||
|
### :star: Request Matching
|
||||||
|
WireMock.Net support advanced request-matching logic, see [Wiki : Request Matching](https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching).
|
||||||
|
|
||||||
|
### :star: Response Templating
|
||||||
|
The response which is returned WireMock.Net can be changed using templating. This is described here [Wiki : Response Templating](https://github.com/WireMock-Net/WireMock.Net/wiki/Response-Templating).
|
||||||
|
|
||||||
|
### :star: Admin API Reference
|
||||||
|
The WireMock admin API provides functionality to define the mappings via a http interface see [Wiki : Admin API Reference](https://github.com/StefH/WireMock.Net/wiki/Admin-API-Reference).
|
||||||
|
|
||||||
|
### :star: Using
|
||||||
|
WireMock.Net can be used in several ways:
|
||||||
|
|
||||||
|
#### UnitTesting
|
||||||
|
You can use your favorite test framework and use WireMock within your tests, see
|
||||||
|
[Wiki : UnitTesting](https://github.com/StefH/WireMock.Net/wiki/Using-WireMock-in-UnitTests).
|
||||||
|
|
||||||
|
#### As a dotnet tool
|
||||||
|
It's simple to install WireMock.Net as (global) dotnet tool, see [Wiki : dotnet tool](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-dotnet-tool).
|
||||||
|
|
||||||
|
#### As standalone process / console application
|
||||||
|
This is quite straight forward to launch a mock server within a console application, see [Wiki : Standalone Process](https://github.com/StefH/WireMock.Net/wiki/WireMock-as-a-standalone-process).
|
||||||
|
|
||||||
|
#### As a Windows Service
|
||||||
|
You can also run WireMock.Net as a Windows Service, follow this [WireMock-as-a-Windows-Service](https://github.com/WireMock-Net/WireMock.Net/wiki/WireMock-as-a-Windows-Service).
|
||||||
|
|
||||||
|
#### As a Web Job in Azure or application in IIS
|
||||||
|
See this link [WireMock-as-a-(Azure)-Web-App](https://github.com/WireMock-Net/WireMock.Net/wiki/WireMock-as-a-(Azure)-Web-App)
|
||||||
|
|
||||||
|
#### In a docker container
|
||||||
|
There is also a Linux and Windows-Nano container available at [hub.docker.com](https://hub.docker.com/r/sheyenrath).
|
||||||
|
For more details see also [Docker](https://github.com/WireMock-Net/WireMock.Net-docker).
|
||||||
|
|
||||||
|
#### HTTPS / SSL
|
||||||
|
More details on using HTTPS (SSL) can be found here [Wiki : HTTPS](https://github.com/WireMock-Net/WireMock.Net/wiki/Using-HTTPS-(SSL))
|
||||||
|
|
||||||
|
## :books: Documentation
|
||||||
|
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/WireMock-Net/WireMock.Net/wiki/What-Is-WireMock.Net).
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
# 1.5.12 (03 December 2022)
|
# 1.5.27 (03 June 2023)
|
||||||
- #851 Fix Linux CI build + Fix opencover [feature]
|
- #946 Add warning logging when sending a request to a Webhook does not return status 200 [feature]
|
||||||
- #853 Add .Net 7 [feature]
|
- #949 Add ".NET Framework 4.7" to WireMock.Net.FluentAssertions [feature]
|
||||||
- #854 Fix logic for QueryParameterMultipleValueSupport [bug]
|
- #928 TypeLoadException when using WithHeader method. [bug]
|
||||||
- #857 Update some dependencies [feature]
|
- #945 Webhook logging [feature]
|
||||||
|
|
||||||
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
The full release notes can be found here: https://github.com/WireMock-Net/WireMock.Net/blob/master/CHANGELOG.md
|
||||||
28
README.md
28
README.md
@@ -1,24 +1,28 @@
|
|||||||
# WireMock.Net
|
# WireMock.Net
|
||||||
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics the functionality from the JAVA based [WireMock.org](http://WireMock.org).
|
A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) which mimics the functionality from the JAVA based [WireMock](http://WireMock.org).
|
||||||
|
|
||||||
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/WireMock-Net/WireMock.Net/wiki/What-Is-WireMock.Net).
|
For more info, see also this WIKI page: [What is WireMock.Net](https://github.com/WireMock-Net/WireMock.Net/wiki/What-Is-WireMock.Net).
|
||||||
|
|
||||||
## Key Features
|
## :star: Key Features
|
||||||
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
||||||
* Library can be used in unit tests and integration tests
|
* Library can be used in unit tests and integration tests
|
||||||
* Runs as a standalone process, as windows service, as Azure/IIS or as docker
|
* Runs as a standalone process, as windows service, as Azure/IIS or as docker
|
||||||
* Configurable via a fluent DotNet API, JSON files and JSON over HTTP
|
* Configurable via a fluent C# .NET API, JSON files and JSON over HTTP
|
||||||
* Record/playback of stubs (proxying)
|
* Record/playback of stubs (proxying)
|
||||||
* Per-request conditional proxying
|
* Per-request conditional proxying
|
||||||
* Stateful behaviour simulation
|
* Stateful behaviour simulation
|
||||||
* Response templating / transformation using Handlebars and extensions
|
* Response templating / transformation using Handlebars and extensions
|
||||||
* Can be used locally or in CI/CD scenarios
|
* Can be used locally or in CI/CD scenarios
|
||||||
|
|
||||||
## Info
|
## :memo: Blogs
|
||||||
|
- [mStack.nl : Generate C# Code from Mapping(s)](https://mstack.nl/blog/20230201-wiremock.net-tocode/)
|
||||||
|
|
||||||
|
|
||||||
|
## :computer: Project Info
|
||||||
| | |
|
| | |
|
||||||
| --- | --- |
|
| --- | --- |
|
||||||
| ***Project*** | |
|
| ***Project*** | |
|
||||||
| **Chat** | [](https://gitter.im/wiremock_dotnet/Lobby) |
|
| **Chat** | [](https://slack.wiremock.org/) [](https://gitter.im/wiremock_dotnet/Lobby) |
|
||||||
| **Issues** | [](https://github.com/WireMock-Net/WireMock.Net/issues) |
|
| **Issues** | [](https://github.com/WireMock-Net/WireMock.Net/issues) |
|
||||||
| | |
|
| | |
|
||||||
| ***Quality*** | |
|
| ***Quality*** | |
|
||||||
@@ -27,7 +31,7 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
|||||||
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
|
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net&resolved=false&types=CODE_SMELL) |
|
||||||
| **Coverage** | [](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [](https://codecov.io/gh/WireMock-Net/WireMock.Net)|
|
| **Coverage** | [](https://sonarcloud.io/component_measures?id=WireMock-Net_WireMock.Net&metric=coverage) [](https://codecov.io/gh/WireMock-Net/WireMock.Net)|
|
||||||
|
|
||||||
### NuGet packages
|
### :package: NuGet packages
|
||||||
|
|
||||||
| | Official | Preview [:information_source:](https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) |
|
| | Official | Preview [:information_source:](https://github.com/WireMock-Net/WireMock.Net/wiki/MyGet-preview-versions) |
|
||||||
| - | - | - |
|
| - | - | - |
|
||||||
@@ -41,23 +45,23 @@ For more info, see also this WIKI page: [What is WireMock.Net](https://github.co
|
|||||||
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
| **WireMock.Org.RestClient** | [](https://www.nuget.org/packages/WireMock.Org.RestClient) | [](https://www.myget.org/feed/wiremock-net/package/nuget/WireMock.Org.RestClient)
|
||||||
|
|
||||||
|
|
||||||
## Development
|
## :memo: Development
|
||||||
For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page.
|
For the supported frameworks and build information, see [this](https://github.com/WireMock-Net/WireMock.Net/wiki/Development-Information) page.
|
||||||
|
|
||||||
## Stubbing
|
## :star: Stubbing
|
||||||
A core feature of WireMock.Net is the ability to return predefined HTTP responses for requests matching criteria.
|
A core feature of WireMock.Net is the ability to return predefined HTTP responses for requests matching criteria.
|
||||||
See [Wiki : Stubbing](https://github.com/WireMock-Net/WireMock.Net/wiki/Stubbing).
|
See [Wiki : Stubbing](https://github.com/WireMock-Net/WireMock.Net/wiki/Stubbing).
|
||||||
|
|
||||||
## Request Matching
|
## :star: Request Matching
|
||||||
WireMock.Net support advanced request-matching logic, see [Wiki : Request Matching](https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching).
|
WireMock.Net support advanced request-matching logic, see [Wiki : Request Matching](https://github.com/WireMock-Net/WireMock.Net/wiki/Request-Matching).
|
||||||
|
|
||||||
## Response Templating
|
## :star: Response Templating
|
||||||
The response which is returned WireMock.Net can be changed using templating. This is described here [Wiki : Response Templating](https://github.com/WireMock-Net/WireMock.Net/wiki/Response-Templating).
|
The response which is returned WireMock.Net can be changed using templating. This is described here [Wiki : Response Templating](https://github.com/WireMock-Net/WireMock.Net/wiki/Response-Templating).
|
||||||
|
|
||||||
## Admin API Reference
|
## :star: Admin API Reference
|
||||||
The WireMock admin API provides functionality to define the mappings via a http interface see [Wiki : Admin API Reference](https://github.com/StefH/WireMock.Net/wiki/Admin-API-Reference).
|
The WireMock admin API provides functionality to define the mappings via a http interface see [Wiki : Admin API Reference](https://github.com/StefH/WireMock.Net/wiki/Admin-API-Reference).
|
||||||
|
|
||||||
## Using
|
## :star: Using
|
||||||
WireMock.Net can be used in several ways:
|
WireMock.Net can be used in several ways:
|
||||||
|
|
||||||
### UnitTesting
|
### UnitTesting
|
||||||
|
|||||||
@@ -28,6 +28,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
|||||||
.github\FUNDING.yml = .github\FUNDING.yml
|
.github\FUNDING.yml = .github\FUNDING.yml
|
||||||
Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
|
Generate-ReleaseNotes.cmd = Generate-ReleaseNotes.cmd
|
||||||
nuget.config = nuget.config
|
nuget.config = nuget.config
|
||||||
|
PackageReadme.md = PackageReadme.md
|
||||||
PackageReleaseNotes.template = PackageReleaseNotes.template
|
PackageReleaseNotes.template = PackageReleaseNotes.template
|
||||||
PackageReleaseNotes.txt = PackageReleaseNotes.txt
|
PackageReleaseNotes.txt = PackageReleaseNotes.txt
|
||||||
README.md = README.md
|
README.md = README.md
|
||||||
|
|||||||
@@ -27,12 +27,14 @@
|
|||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Guids/@EntryIndexedValue">True</s:Boolean>
|
<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/=Heyenrath/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@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/=Pacticipant/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Raml/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Raml/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=randomizer/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=randomizer/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriban/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Scriban/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sigil/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Sigil/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Stef/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=templated/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Victoor/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhook/@EntryIndexedValue">True</s:Boolean>
|
||||||
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
|
<s:Boolean x:Key="/Default/UserDictionary/Words/=Webhooks/@EntryIndexedValue">True</s:Boolean>
|
||||||
|
|||||||
@@ -1,78 +1,125 @@
|
|||||||
using Newtonsoft.Json;
|
|
||||||
using RestEase;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using RestEase;
|
||||||
using WireMock.Admin.Settings;
|
using WireMock.Admin.Settings;
|
||||||
using WireMock.Client;
|
using WireMock.Client;
|
||||||
|
using WireMock.Client.Extensions;
|
||||||
|
|
||||||
namespace WireMock.Net.Client
|
namespace WireMock.Net.Client;
|
||||||
|
|
||||||
|
class Program
|
||||||
{
|
{
|
||||||
class Program
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
static async Task Main(string[] args)
|
// Create an implementation of the IWireMockAdminApi and pass in the base URL for the API.
|
||||||
|
var api = RestClient.For<IWireMockAdminApi>("http://localhost:9091");
|
||||||
|
|
||||||
|
// await api.ResetMappingsAsync().ConfigureAwait(false);
|
||||||
|
|
||||||
|
var mappingBuilder = api.GetMappingBuilder();
|
||||||
|
mappingBuilder.Given(m => m
|
||||||
|
.WithTitle("This is my title 1")
|
||||||
|
.WithRequest(req => req
|
||||||
|
.UsingGet()
|
||||||
|
.WithPath("/bla1")
|
||||||
|
)
|
||||||
|
.WithResponse(rsp => rsp
|
||||||
|
.WithBody("x1")
|
||||||
|
.WithHeaders(h => h.Add("h1", "v1"))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
mappingBuilder.Given(m => m
|
||||||
|
.WithTitle("This is my title 2")
|
||||||
|
.WithRequest(req => req
|
||||||
|
.UsingGet()
|
||||||
|
.WithPath("/bla2")
|
||||||
|
)
|
||||||
|
.WithResponse(rsp => rsp
|
||||||
|
.WithBody("x2")
|
||||||
|
.WithHeaders(h => h.Add("h2", "v2"))
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
mappingBuilder.Given(m => m
|
||||||
|
.WithTitle("This is my title 3")
|
||||||
|
.WithRequest(req => req
|
||||||
|
.UsingGet()
|
||||||
|
.WithPath("/bla3")
|
||||||
|
)
|
||||||
|
.WithResponse(rsp => rsp
|
||||||
|
.WithBodyAsJson(new
|
||||||
|
{
|
||||||
|
x = "test"
|
||||||
|
}, true)
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
var result = await mappingBuilder.BuildAndPostAsync().ConfigureAwait(false);
|
||||||
|
Console.WriteLine($"result = {JsonConvert.SerializeObject(result)}");
|
||||||
|
|
||||||
|
var mappings = await api.GetMappingsAsync();
|
||||||
|
Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}");
|
||||||
|
|
||||||
|
// Set BASIC Auth
|
||||||
|
var value = Convert.ToBase64String(Encoding.ASCII.GetBytes("a:b"));
|
||||||
|
api.Authorization = new AuthenticationHeaderValue("Basic", value);
|
||||||
|
|
||||||
|
var settings1 = await api.GetSettingsAsync();
|
||||||
|
Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}");
|
||||||
|
|
||||||
|
var settingsViaBuilder = new SettingsModelBuilder()
|
||||||
|
.WithGlobalProcessingDelay(1077)
|
||||||
|
.WithoutGlobalProcessingDelay()
|
||||||
|
.Build();
|
||||||
|
|
||||||
|
settings1.GlobalProcessingDelay = 1077;
|
||||||
|
api.PostSettingsAsync(settings1).Wait();
|
||||||
|
|
||||||
|
var settings2 = await api.GetSettingsAsync();
|
||||||
|
Console.WriteLine($"settings2 = {JsonConvert.SerializeObject(settings2)}");
|
||||||
|
|
||||||
|
mappings = await api.GetMappingsAsync();
|
||||||
|
Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}");
|
||||||
|
|
||||||
|
try
|
||||||
{
|
{
|
||||||
// Create an implementation of the IWireMockAdminApi and pass in the base URL for the API.
|
var guid = Guid.Parse("11111110-a633-40e8-a244-5cb80bc0ab66");
|
||||||
var api = RestClient.For<IWireMockAdminApi>("http://localhost:9091");
|
var mapping = await api.GetMappingAsync(guid);
|
||||||
|
Console.WriteLine($"mapping = {JsonConvert.SerializeObject(mapping)}");
|
||||||
// Set BASIC Auth
|
|
||||||
var value = Convert.ToBase64String(Encoding.ASCII.GetBytes("a:b"));
|
|
||||||
api.Authorization = new AuthenticationHeaderValue("Basic", value);
|
|
||||||
|
|
||||||
var settings1 = await api.GetSettingsAsync();
|
|
||||||
Console.WriteLine($"settings1 = {JsonConvert.SerializeObject(settings1)}");
|
|
||||||
|
|
||||||
var settingsViaBuilder = new SettingsModelBuilder()
|
|
||||||
.WithGlobalProcessingDelay(1077)
|
|
||||||
.WithoutGlobalProcessingDelay()
|
|
||||||
.Build();
|
|
||||||
|
|
||||||
settings1.GlobalProcessingDelay = 1077;
|
|
||||||
api.PostSettingsAsync(settings1).Wait();
|
|
||||||
|
|
||||||
var settings2 = await api.GetSettingsAsync();
|
|
||||||
Console.WriteLine($"settings2 = {JsonConvert.SerializeObject(settings2)}");
|
|
||||||
|
|
||||||
var mappings = await api.GetMappingsAsync();
|
|
||||||
Console.WriteLine($"mappings = {JsonConvert.SerializeObject(mappings)}");
|
|
||||||
|
|
||||||
try
|
|
||||||
{
|
|
||||||
var guid = Guid.Parse("11111110-a633-40e8-a244-5cb80bc0ab66");
|
|
||||||
var mapping = await api.GetMappingAsync(guid);
|
|
||||||
Console.WriteLine($"mapping = {JsonConvert.SerializeObject(mapping)}");
|
|
||||||
}
|
|
||||||
catch (Exception e)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
var request = await api.GetRequestsAsync();
|
|
||||||
Console.WriteLine($"request = {JsonConvert.SerializeObject(request)}");
|
|
||||||
|
|
||||||
//var deleteRequestsAsync = api.DeleteRequestsAsync().Result;
|
|
||||||
//Console.WriteLine($"DeleteRequestsAsync = {deleteRequestsAsync.Status}");
|
|
||||||
|
|
||||||
//var resetRequestsAsync = api.ResetRequestsAsync().Result;
|
|
||||||
//Console.WriteLine($"ResetRequestsAsync = {resetRequestsAsync.Status}");
|
|
||||||
|
|
||||||
var scenarioStates = await api.GetScenariosAsync();
|
|
||||||
Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}");
|
|
||||||
|
|
||||||
var postFileResult = await api.PostFileAsync("1.cs", "C# Hello");
|
|
||||||
Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}");
|
|
||||||
|
|
||||||
var getFileResult = await api.GetFileAsync("1.cs");
|
|
||||||
Console.WriteLine($"getFileResult = {getFileResult}");
|
|
||||||
|
|
||||||
var resetMappingsAsync = await api.ResetMappingsAsync();
|
|
||||||
Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}");
|
|
||||||
|
|
||||||
var resetMappingsAndReloadStaticMappingsAsync = await api.ResetMappingsAsync(true);
|
|
||||||
Console.WriteLine($"resetMappingsAndReloadStaticMappingsAsync = {resetMappingsAndReloadStaticMappingsAsync.Status}");
|
|
||||||
|
|
||||||
Console.WriteLine("Press any key to quit");
|
|
||||||
Console.ReadKey();
|
|
||||||
}
|
}
|
||||||
|
catch (Exception e)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
var request = await api.GetRequestsAsync();
|
||||||
|
Console.WriteLine($"request = {JsonConvert.SerializeObject(request)}");
|
||||||
|
|
||||||
|
//var deleteRequestsAsync = api.DeleteRequestsAsync().Result;
|
||||||
|
//Console.WriteLine($"DeleteRequestsAsync = {deleteRequestsAsync.Status}");
|
||||||
|
|
||||||
|
//var resetRequestsAsync = api.ResetRequestsAsync().Result;
|
||||||
|
//Console.WriteLine($"ResetRequestsAsync = {resetRequestsAsync.Status}");
|
||||||
|
|
||||||
|
var scenarioStates = await api.GetScenariosAsync();
|
||||||
|
Console.WriteLine($"GetScenariosAsync = {JsonConvert.SerializeObject(scenarioStates)}");
|
||||||
|
|
||||||
|
var postFileResult = await api.PostFileAsync("1.cs", "C# Hello");
|
||||||
|
Console.WriteLine($"postFileResult = {JsonConvert.SerializeObject(postFileResult)}");
|
||||||
|
|
||||||
|
var getFileResult = await api.GetFileAsync("1.cs");
|
||||||
|
Console.WriteLine($"getFileResult = {getFileResult}");
|
||||||
|
|
||||||
|
var resetMappingsAsync = await api.ResetMappingsAsync();
|
||||||
|
Console.WriteLine($"resetMappingsAsync = {resetMappingsAsync.Status}");
|
||||||
|
|
||||||
|
var resetMappingsAndReloadStaticMappingsAsync = await api.ResetMappingsAsync(true);
|
||||||
|
Console.WriteLine($"resetMappingsAndReloadStaticMappingsAsync = {resetMappingsAndReloadStaticMappingsAsync.Status}");
|
||||||
|
|
||||||
|
Console.WriteLine("Press any key to quit");
|
||||||
|
Console.ReadKey();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,19 +1,13 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
<TargetFramework>net6.0</TargetFramework>
|
<TargetFramework>net7.0</TargetFramework>
|
||||||
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
<ApplicationIcon>../../resources/WireMock.Net-Logo.ico</ApplicationIcon>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
|
||||||
<PackageReference Include="RestEase" Version="1.5.7" />
|
</ItemGroup>
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
<ItemGroup>
|
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
|
|
||||||
</ItemGroup>
|
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -27,7 +27,7 @@
|
|||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
<!--<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />-->
|
||||||
<PackageReference Include="log4net" Version="2.0.15" />
|
<PackageReference Include="log4net" Version="2.0.15" />
|
||||||
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
<PackageReference Include="Microsoft.Extensions.Configuration" Version="6.0.0" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -21,10 +21,10 @@
|
|||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||||
<PackageReference Include="log4net" Version="2.0.15" />
|
<PackageReference Include="log4net" Version="2.0.15" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -33,10 +33,10 @@
|
|||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||||
<PackageReference Include="log4net" Version="2.0.15" />
|
<PackageReference Include="log4net" Version="2.0.15" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<OutputType>Exe</OutputType>
|
<OutputType>Exe</OutputType>
|
||||||
@@ -30,10 +30,10 @@
|
|||||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.DynamicLinq" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Json" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
<PackageReference Include="Handlebars.Net.Helpers.XPath" Version="2.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Xeger" Version="2.3.*" />
|
||||||
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.10" />
|
<PackageReference Include="Handlebars.Net.Helpers.Random" Version="2.3.*" />
|
||||||
<PackageReference Include="log4net" Version="2.0.15" />
|
<PackageReference Include="log4net" Version="2.0.15" />
|
||||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|||||||
@@ -1,6 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Globalization;
|
using System.Globalization;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Linq;
|
||||||
using System.Net;
|
using System.Net;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
@@ -33,12 +35,54 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public class Todo
|
||||||
|
{
|
||||||
|
public int Id { get; set; }
|
||||||
|
}
|
||||||
|
|
||||||
public static class MainApp
|
public static class MainApp
|
||||||
{
|
{
|
||||||
public static void Run()
|
public static void Run()
|
||||||
{
|
{
|
||||||
var s = WireMockServer.Start();
|
var mappingBuilder = new MappingBuilder();
|
||||||
s.Stop();
|
mappingBuilder
|
||||||
|
.Given(Request
|
||||||
|
.Create()
|
||||||
|
.WithPath(new WildcardMatcher("/param2", true))
|
||||||
|
.WithParam("key", "test")
|
||||||
|
.UsingGet())
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithHeader("Content-Type", "application/json")
|
||||||
|
.WithBodyAsJson(new { result = "param2" }));
|
||||||
|
|
||||||
|
var json = mappingBuilder.ToJson();
|
||||||
|
System.Console.WriteLine("mappingBuilder : Json = {0}", json);
|
||||||
|
|
||||||
|
var todos = new Dictionary<int, Todo>();
|
||||||
|
|
||||||
|
var server = WireMockServer.Start();
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("todos")
|
||||||
|
.UsingGet()
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithBodyAsJson(todos.Values)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingGet()
|
||||||
|
.WithPath("todos")
|
||||||
|
.WithParam("id")
|
||||||
|
)
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithBodyAsJson(rm => todos[int.Parse(rm.Query!["id"].ToString())])
|
||||||
|
);
|
||||||
|
|
||||||
|
var httpClient = server.CreateClient();
|
||||||
|
//server.Stop();
|
||||||
|
|
||||||
var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
|
var httpAndHttpsWithPort = WireMockServer.Start(new WireMockServerSettings
|
||||||
{
|
{
|
||||||
@@ -57,7 +101,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
string url2 = "http://localhost:9092/";
|
string url2 = "http://localhost:9092/";
|
||||||
string url3 = "https://localhost:9443/";
|
string url3 = "https://localhost:9443/";
|
||||||
|
|
||||||
var server = WireMockServer.Start(new WireMockServerSettings
|
server = WireMockServer.Start(new WireMockServerSettings
|
||||||
{
|
{
|
||||||
AllowCSharpCodeMatcher = true,
|
AllowCSharpCodeMatcher = true,
|
||||||
Urls = new[] { url1, url2, url3 },
|
Urls = new[] { url1, url2, url3 },
|
||||||
@@ -93,7 +137,43 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
|
|
||||||
// server.AllowPartialMapping();
|
// server.AllowPartialMapping();
|
||||||
|
|
||||||
|
// 400 ms
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/slow/400")
|
||||||
|
.UsingPost())
|
||||||
|
.RespondWith(
|
||||||
|
Response.Create()
|
||||||
|
.WithStatusCode(400)
|
||||||
|
.WithBody("return 400")
|
||||||
|
.WithHeader("Content-Type", "text/plain")
|
||||||
|
);
|
||||||
|
// 4 sec
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.WithPath("/slow/500")
|
||||||
|
.UsingPost())
|
||||||
|
.RespondWith(
|
||||||
|
Response.Create()
|
||||||
|
.WithStatusCode(500)
|
||||||
|
.WithBody("return 500")
|
||||||
|
.WithHeader("Content-Type", "text/plain")
|
||||||
|
);
|
||||||
|
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(Request.Create()
|
||||||
|
.UsingMethod("GET")
|
||||||
|
.WithPath("/foo1")
|
||||||
|
.WithParam("p1", "xyz")
|
||||||
|
)
|
||||||
|
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
|
||||||
|
.RespondWith(Response.Create()
|
||||||
|
.WithBody("Hello World")
|
||||||
|
);
|
||||||
|
|
||||||
server.Given(Request.Create().WithPath(MatchOperator.Or, "/mypath", "/mypath1", "/mypath2").UsingPost())
|
server.Given(Request.Create().WithPath(MatchOperator.Or, "/mypath", "/mypath1", "/mypath2").UsingPost())
|
||||||
|
.WithGuid("86984b0e-2516-4935-a2ef-b45bf4820d7d")
|
||||||
.RespondWith(Response.Create()
|
.RespondWith(Response.Create()
|
||||||
.WithHeader("Content-Type", "application/json")
|
.WithHeader("Content-Type", "application/json")
|
||||||
.WithBodyAsJson("{{JsonPath.SelectToken request.body \"..name\"}}")
|
.WithBodyAsJson("{{JsonPath.SelectToken request.body \"..name\"}}")
|
||||||
@@ -366,14 +446,14 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
// http://localhost:9091/trans?start=1000&stop=1&stop=2
|
// http://localhost:9091/trans?start=1000&stop=1&stop=2
|
||||||
server
|
server
|
||||||
.Given(Request.Create().WithPath("/trans").UsingGet())
|
.Given(Request.Create().WithPath("/trans").UsingGet())
|
||||||
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f05")
|
.WithGuid("90356dba-b36c-469a-a17e-669cd84f1f06")
|
||||||
.RespondWith(Response.Create()
|
.RespondWith(Response.Create()
|
||||||
.WithStatusCode(200)
|
.WithStatusCode(200)
|
||||||
.WithHeader("Content-Type", "application/json")
|
.WithHeader("Content-Type", "application/json")
|
||||||
.WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}")
|
.WithHeader("Transformed-Postman-Token", "token is {{request.headers.Postman-Token}}")
|
||||||
.WithHeader("xyz_{{request.headers.Postman-Token}}", "token is {{request.headers.Postman-Token}}")
|
.WithHeader("xyz_{{request.headers.Postman-Token}}", "token is {{request.headers.Postman-Token}}")
|
||||||
.WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, add={{Math.Add request.query.start.[0] 42}} bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }")
|
.WithBody(@"{""msg"": ""Hello world CATCH-ALL on /*, {{request.path}}, add={{Math.Add request.query.start.[0] 42}} bykey={{request.query.start}}, bykey={{request.query.stop}}, byidx0={{request.query.stop.[0]}}, byidx1={{request.query.stop.[1]}}"" }")
|
||||||
.WithTransformer(TransformerType.Handlebars, true, ReplaceNodeOptions.None)
|
.WithTransformer(TransformerType.Handlebars, true, ReplaceNodeOptions.EvaluateAndTryToConvert)
|
||||||
.WithDelay(TimeSpan.FromMilliseconds(100))
|
.WithDelay(TimeSpan.FromMilliseconds(100))
|
||||||
);
|
);
|
||||||
|
|
||||||
@@ -563,6 +643,7 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
.WithStatusCode(200)
|
.WithStatusCode(200)
|
||||||
.WithHeader("Content-Type", "application/json")
|
.WithHeader("Content-Type", "application/json")
|
||||||
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
|
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
|
||||||
|
|
||||||
server
|
server
|
||||||
.Given(Request.Create().WithPath("/random200or505").UsingGet())
|
.Given(Request.Create().WithPath("/random200or505").UsingGet())
|
||||||
.RespondWith(Response.Create().WithCallback(request =>
|
.RespondWith(Response.Create().WithCallback(request =>
|
||||||
@@ -570,7 +651,11 @@ namespace WireMock.Net.ConsoleApplication
|
|||||||
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
||||||
return new ResponseMessage
|
return new ResponseMessage
|
||||||
{
|
{
|
||||||
BodyData = new BodyData { BodyAsString = "random200or505:" + code, DetectedBodyType = Types.BodyType.String },
|
BodyData = new BodyData
|
||||||
|
{
|
||||||
|
BodyAsString = "random200or505:" + code + ", HeadersFromRequest = " + string.Join(",", request.Headers),
|
||||||
|
DetectedBodyType = Types.BodyType.String,
|
||||||
|
},
|
||||||
StatusCode = code
|
StatusCode = code
|
||||||
};
|
};
|
||||||
}));
|
}));
|
||||||
|
|||||||
@@ -42,11 +42,11 @@
|
|||||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net452\Handlebars.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net452\Handlebars.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.10\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="AnyOf" version="0.3.0" targetFramework="net452" />
|
<package id="AnyOf" version="0.3.0" targetFramework="net452" />
|
||||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net452" />
|
<package id="Handlebars.Net" version="2.1.2" targetFramework="net452" />
|
||||||
<package id="Handlebars.Net.Helpers" version="2.3.10" targetFramework="net452" />
|
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net452" />
|
||||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.10" targetFramework="net452" />
|
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net452" />
|
||||||
<package id="log4net" version="2.0.15" targetFramework="net452" />
|
<package id="log4net" version="2.0.15" targetFramework="net452" />
|
||||||
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
|
<package id="Microsoft.Owin.Host.HttpListener" version="3.1.0" targetFramework="net452" />
|
||||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||||
|
|||||||
@@ -41,11 +41,11 @@
|
|||||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.10\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
<Reference Include="log4net, Version=2.0.15.0, Culture=neutral, PublicKeyToken=669e0ddf0bb1aa2a, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
<HintPath>..\..\packages\log4net.2.0.15\lib\net45\log4net.dll</HintPath>
|
||||||
|
|||||||
@@ -2,8 +2,8 @@
|
|||||||
<packages>
|
<packages>
|
||||||
<package id="AnyOf" version="0.3.0" targetFramework="net461" />
|
<package id="AnyOf" version="0.3.0" targetFramework="net461" />
|
||||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net461" />
|
<package id="Handlebars.Net" version="2.1.2" targetFramework="net461" />
|
||||||
<package id="Handlebars.Net.Helpers" version="2.3.10" targetFramework="net461" />
|
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net461" />
|
||||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.10" targetFramework="net461" />
|
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net461" />
|
||||||
<package id="log4net" version="2.0.15" targetFramework="net461" />
|
<package id="log4net" version="2.0.15" targetFramework="net461" />
|
||||||
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
|
<package id="Microsoft.Extensions.DependencyInjection.Abstractions" version="2.2.0" targetFramework="net461" />
|
||||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net461" />
|
||||||
|
|||||||
@@ -49,29 +49,29 @@
|
|||||||
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
<Reference Include="Handlebars, Version=2.1.2.0, Culture=neutral, PublicKeyToken=22225d0bf33cd661, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.2.1.2\lib\net46\Handlebars.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Handlebars.Net.Helpers, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="Handlebars.Net.Helpers, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.10\lib\net452\Handlebars.Net.Helpers.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.2.3.12\lib\net46\Handlebars.Net.Helpers.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Core, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Core.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Core.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.DynamicLinq, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.3.10\lib\net452\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.DynamicLinq.2.3.12\lib\net46\HandlebarsDotNet.Helpers.DynamicLinq.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Humanizer, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Humanizer.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Humanizer.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Json, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Json.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Json.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Random, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Random.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Random.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.Xeger, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.3.10\lib\net452\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.Xeger.2.3.12\lib\net46\HandlebarsDotNet.Helpers.Xeger.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.3.10.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
<Reference Include="HandlebarsDotNet.Helpers.XPath, Version=2.3.12.0, Culture=neutral, PublicKeyToken=00d131fae0c250bc, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.3.10\lib\net452\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
<HintPath>..\..\packages\Handlebars.Net.Helpers.XPath.2.3.12\lib\net46\HandlebarsDotNet.Helpers.XPath.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
<Reference Include="Humanizer, Version=2.14.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
<Reference Include="Humanizer, Version=2.14.0.0, Culture=neutral, PublicKeyToken=979442b78dfc278e, processorArchitecture=MSIL">
|
||||||
<HintPath>..\..\packages\Humanizer.Core.2.14.1\lib\netstandard2.0\Humanizer.dll</HintPath>
|
<HintPath>..\..\packages\Humanizer.Core.2.14.1\lib\netstandard2.0\Humanizer.dll</HintPath>
|
||||||
|
|||||||
@@ -3,14 +3,14 @@
|
|||||||
<package id="AnyOf" version="0.3.0" targetFramework="net472" />
|
<package id="AnyOf" version="0.3.0" targetFramework="net472" />
|
||||||
<package id="Fare" version="2.2.1" targetFramework="net472" />
|
<package id="Fare" version="2.2.1" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net" version="2.1.2" targetFramework="net472" />
|
<package id="Handlebars.Net" version="2.1.2" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.Core" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.Core" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.DynamicLinq" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.Humanizer" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.Humanizer" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.Json" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.Json" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.Random" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.Random" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.Xeger" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.Xeger" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Handlebars.Net.Helpers.XPath" version="2.3.10" targetFramework="net472" />
|
<package id="Handlebars.Net.Helpers.XPath" version="2.3.12" targetFramework="net472" />
|
||||||
<package id="Humanizer" version="2.14.1" targetFramework="net472" />
|
<package id="Humanizer" version="2.14.1" targetFramework="net472" />
|
||||||
<package id="Humanizer.Core" version="2.14.1" targetFramework="net472" />
|
<package id="Humanizer.Core" version="2.14.1" targetFramework="net472" />
|
||||||
<package id="Humanizer.Core.af" version="2.14.1" targetFramework="net472" />
|
<package id="Humanizer.Core.af" version="2.14.1" targetFramework="net472" />
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Specialized;
|
||||||
using System.Net.Http;
|
using System.Net.Http;
|
||||||
using Newtonsoft.Json;
|
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
|
||||||
@@ -26,10 +26,8 @@ namespace WireMock.Net.Console.Proxy.Net452
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
server.LogEntriesChanged += (sender, eventRecordArgs) =>
|
System.Console.WriteLine("Subscribing to LogEntriesChanged");
|
||||||
{
|
server.LogEntriesChanged += Server_LogEntriesChanged;
|
||||||
System.Console.WriteLine(JsonConvert.SerializeObject(eventRecordArgs.NewItems, Formatting.Indented));
|
|
||||||
};
|
|
||||||
|
|
||||||
var uri = new Uri(urls[0]);
|
var uri = new Uri(urls[0]);
|
||||||
var form = new MultipartFormDataContent
|
var form = new MultipartFormDataContent
|
||||||
@@ -38,9 +36,23 @@ namespace WireMock.Net.Console.Proxy.Net452
|
|||||||
};
|
};
|
||||||
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
|
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
|
||||||
|
|
||||||
|
System.Console.WriteLine("Unsubscribing to LogEntriesChanged");
|
||||||
|
server.LogEntriesChanged -= Server_LogEntriesChanged;
|
||||||
|
|
||||||
|
form = new MultipartFormDataContent
|
||||||
|
{
|
||||||
|
{ new StringContent("data2"), "test2", "test2.txt" }
|
||||||
|
};
|
||||||
|
new HttpClient().PostAsync(uri, form).GetAwaiter().GetResult();
|
||||||
|
|
||||||
System.Console.WriteLine("Press any key to stop the server");
|
System.Console.WriteLine("Press any key to stop the server");
|
||||||
System.Console.ReadKey();
|
System.Console.ReadKey();
|
||||||
server.Stop();
|
server.Stop();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static void Server_LogEntriesChanged(object sender, NotifyCollectionChangedEventArgs eventRecordArgs)
|
||||||
|
{
|
||||||
|
System.Console.WriteLine("Server_LogEntriesChanged : {0}", eventRecordArgs.NewItems.Count);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -11,7 +11,7 @@ public class DynamicDataGeneration : WireMockOpenApiParserDynamicExampleValues
|
|||||||
get
|
get
|
||||||
{
|
{
|
||||||
// Since you have your Schema, you can get if max-length is set. You can generate accurate examples with this settings
|
// Since you have your Schema, you can get if max-length is set. You can generate accurate examples with this settings
|
||||||
var maxLength = Schema.MaxLength ?? 9;
|
var maxLength = Schema?.MaxLength ?? 9;
|
||||||
|
|
||||||
return RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex
|
return RandomizerFactory.GetRandomizer(new FieldOptionsTextRegex
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,5 +1,6 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
using WireMock.RequestBuilders;
|
using WireMock.RequestBuilders;
|
||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
|
|
||||||
@@ -17,8 +18,8 @@ class Program
|
|||||||
|
|
||||||
private static void RunMockServerWithDynamicExampleGeneration()
|
private static void RunMockServerWithDynamicExampleGeneration()
|
||||||
{
|
{
|
||||||
//Run your mocking framework specifieing youur Example Values generator class.
|
// Run your mocking framework specifying your Example Values generator class.
|
||||||
var serverCustomer_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Customer_V2.0.json"), "http://localhost:8090/", true, new DynamicDataGeneration(), Types.ExampleValueType.Value, Types.ExampleValueType.Value);
|
var serverCustomer_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Customer_V2.0.json"), "http://localhost:8090/", true, new DynamicDataGeneration(), ExampleValueType.Value, ExampleValueType.Value);
|
||||||
Console.WriteLine("Press any key to stop the servers");
|
Console.WriteLine("Press any key to stop the servers");
|
||||||
|
|
||||||
Console.ReadKey();
|
Console.ReadKey();
|
||||||
@@ -27,15 +28,15 @@ class Program
|
|||||||
|
|
||||||
private static void RunOthersOpenApiParserExample()
|
private static void RunOthersOpenApiParserExample()
|
||||||
{
|
{
|
||||||
var serverOpenAPIExamples = Run.RunServer(Path.Combine(Folder, "openAPIExamples.yaml"), "https://localhost:9091/");
|
var serverOpenAPIExamples = Run.RunServer(Path.Combine(Folder, "openAPIExamples.yaml"), "http://localhost:9091/");
|
||||||
var serverPetstore_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.json"), "https://localhost:9092/");
|
var serverPetstore_V2_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.json"), "http://localhost:9092/");
|
||||||
var serverPetstore_V2_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.yaml"), "https://localhost:9093/");
|
var serverPetstore_V2_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V2.0.yaml"), "http://localhost:9093/");
|
||||||
var serverPetstore_V300_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.0.yaml"), "https://localhost:9094/");
|
var serverPetstore_V300_yaml = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.0.yaml"), "http://localhost:9094/");
|
||||||
var serverPetstore_V302_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.2.json"), "https://localhost:9095/");
|
var serverPetstore_V302_json = Run.RunServer(Path.Combine(Folder, "Swagger_Petstore_V3.0.2.json"), "http://localhost:9095/");
|
||||||
var testopenapifile_json = Run.RunServer(Path.Combine(Folder, "testopenapifile.json"), "https://localhost:9096/");
|
var testopenapifile_json = Run.RunServer(Path.Combine(Folder, "testopenapifile.json"), "http://localhost:9096/");
|
||||||
var file_errorYaml = Run.RunServer(Path.Combine(Folder, "file_error.yaml"), "https://localhost:9097/");
|
var file_errorYaml = Run.RunServer(Path.Combine(Folder, "file_error.yaml"), "http://localhost:9097/");
|
||||||
var file_petJson = Run.RunServer(Path.Combine(Folder, "pet.json"), "https://localhost:9098/");
|
var file_petJson = Run.RunServer(Path.Combine(Folder, "pet.json"), "http://localhost:9098/");
|
||||||
var refsYaml = Run.RunServer(Path.Combine(Folder, "refs.yaml"), "https://localhost:9099/");
|
var refsYaml = Run.RunServer(Path.Combine(Folder, "refs.yaml"), "http://localhost:9099/");
|
||||||
|
|
||||||
testopenapifile_json
|
testopenapifile_json
|
||||||
.Given(Request.Create().WithPath("/x").UsingGet())
|
.Given(Request.Create().WithPath("/x").UsingGet())
|
||||||
|
|||||||
@@ -9,64 +9,70 @@ using WireMock.Net.OpenApiParser.Types;
|
|||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.ConsoleApp
|
namespace WireMock.Net.OpenApiParser.ConsoleApp;
|
||||||
|
|
||||||
|
public static class Run
|
||||||
{
|
{
|
||||||
public static class Run
|
public static WireMockServer RunServer(
|
||||||
|
string path,
|
||||||
|
string url,
|
||||||
|
bool dynamicExamples = true,
|
||||||
|
IWireMockOpenApiParserExampleValues? examplesValuesGenerator = null,
|
||||||
|
ExampleValueType pathPatternToUse = ExampleValueType.Wildcard,
|
||||||
|
ExampleValueType headerPatternToUse = ExampleValueType.Wildcard
|
||||||
|
)
|
||||||
{
|
{
|
||||||
public static WireMockServer RunServer(string path, string url, bool dynamicExamples = true, IWireMockOpenApiParserExampleValues examplesValuesGenerator = null, ExampleValueType pathPatternToUse = ExampleValueType.Wildcard, ExampleValueType headerPatternToUse = ExampleValueType.Wildcard)
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
{
|
{
|
||||||
var server = WireMockServer.Start(new WireMockServerSettings
|
AllowCSharpCodeMatcher = true,
|
||||||
{
|
Urls = new[] { url },
|
||||||
AllowCSharpCodeMatcher = true,
|
StartAdminInterface = true,
|
||||||
Urls = new[] { url },
|
ReadStaticMappings = true,
|
||||||
StartAdminInterface = true,
|
WatchStaticMappings = false,
|
||||||
ReadStaticMappings = true,
|
WatchStaticMappingsInSubdirectories = false,
|
||||||
WatchStaticMappings = false,
|
Logger = new WireMockConsoleLogger(),
|
||||||
WatchStaticMappingsInSubdirectories = false,
|
SaveUnmatchedRequests = true
|
||||||
Logger = new WireMockConsoleLogger(),
|
});
|
||||||
SaveUnmatchedRequests = true
|
|
||||||
});
|
|
||||||
|
|
||||||
Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
||||||
|
|
||||||
//server.SetBasicAuthentication("a", "b");
|
//server.SetBasicAuthentication("a", "b");
|
||||||
|
|
||||||
var settings = new WireMockOpenApiParserSettings
|
var settings = new WireMockOpenApiParserSettings
|
||||||
{
|
|
||||||
DynamicExamples = dynamicExamples,
|
|
||||||
ExampleValues = examplesValuesGenerator,
|
|
||||||
PathPatternToUse = pathPatternToUse,
|
|
||||||
HeaderPatternToUse = headerPatternToUse,
|
|
||||||
};
|
|
||||||
|
|
||||||
server.WithMappingFromOpenApiFile(path, settings, out var diag);
|
|
||||||
|
|
||||||
return server;
|
|
||||||
}
|
|
||||||
|
|
||||||
public static void RunServer(IEnumerable<MappingModel> mappings)
|
|
||||||
{
|
{
|
||||||
string url1 = "http://localhost:9091/";
|
DynamicExamples = dynamicExamples,
|
||||||
|
ExampleValues = examplesValuesGenerator,
|
||||||
|
PathPatternToUse = pathPatternToUse,
|
||||||
|
HeaderPatternToUse = headerPatternToUse,
|
||||||
|
};
|
||||||
|
|
||||||
var server = WireMockServer.Start(new WireMockServerSettings
|
server.WithMappingFromOpenApiFile(path, settings, out var diag);
|
||||||
{
|
|
||||||
AllowCSharpCodeMatcher = true,
|
|
||||||
Urls = new[] { url1 },
|
|
||||||
StartAdminInterface = true,
|
|
||||||
ReadStaticMappings = false,
|
|
||||||
WatchStaticMappings = false,
|
|
||||||
WatchStaticMappingsInSubdirectories = false,
|
|
||||||
Logger = new WireMockConsoleLogger(),
|
|
||||||
});
|
|
||||||
Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
|
||||||
|
|
||||||
server.SetBasicAuthentication("a", "b");
|
return server;
|
||||||
|
}
|
||||||
|
|
||||||
server.WithMapping(mappings.ToArray());
|
public static void RunServer(IEnumerable<MappingModel> mappings)
|
||||||
|
{
|
||||||
|
string url1 = "http://localhost:9091/";
|
||||||
|
|
||||||
Console.WriteLine("Press any key to stop the server");
|
var server = WireMockServer.Start(new WireMockServerSettings
|
||||||
System.Console.ReadKey();
|
{
|
||||||
server.Stop();
|
AllowCSharpCodeMatcher = true,
|
||||||
}
|
Urls = new[] { url1 },
|
||||||
|
StartAdminInterface = true,
|
||||||
|
ReadStaticMappings = false,
|
||||||
|
WatchStaticMappings = false,
|
||||||
|
WatchStaticMappingsInSubdirectories = false,
|
||||||
|
Logger = new WireMockConsoleLogger(),
|
||||||
|
});
|
||||||
|
Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
||||||
|
|
||||||
|
server.SetBasicAuthentication("a", "b");
|
||||||
|
|
||||||
|
server.WithMapping(mappings.ToArray());
|
||||||
|
|
||||||
|
Console.WriteLine("Press any key to stop the server");
|
||||||
|
System.Console.ReadKey();
|
||||||
|
server.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -5,7 +5,7 @@
|
|||||||
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
|
<package id="Microsoft.AspNet.WebApi.Core" version="5.2.3" targetFramework="net452" />
|
||||||
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net452" />
|
<package id="Microsoft.AspNet.WebApi.Owin" version="5.2.3" targetFramework="net452" />
|
||||||
<package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.3" targetFramework="net452" />
|
<package id="Microsoft.AspNet.WebApi.OwinSelfHost" version="5.2.3" targetFramework="net452" />
|
||||||
<package id="Microsoft.Owin" version="2.0.2" targetFramework="net452" />
|
<package id="Microsoft.Owin" version="4.2.2" targetFramework="net452" />
|
||||||
<package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net452" />
|
<package id="Microsoft.Owin.Host.HttpListener" version="2.0.2" targetFramework="net452" />
|
||||||
<package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net452" />
|
<package id="Microsoft.Owin.Hosting" version="2.0.2" targetFramework="net452" />
|
||||||
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
<package id="Newtonsoft.Json" version="13.0.1" targetFramework="net452" />
|
||||||
|
|||||||
@@ -3,6 +3,7 @@ using System.IO;
|
|||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Reflection;
|
using System.Reflection;
|
||||||
using System.Threading;
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
using log4net;
|
using log4net;
|
||||||
using log4net.Config;
|
using log4net.Config;
|
||||||
using log4net.Repository;
|
using log4net.Repository;
|
||||||
@@ -10,71 +11,112 @@ using WireMock.RequestBuilders;
|
|||||||
using WireMock.ResponseBuilders;
|
using WireMock.ResponseBuilders;
|
||||||
using WireMock.Server;
|
using WireMock.Server;
|
||||||
using WireMock.Settings;
|
using WireMock.Settings;
|
||||||
using WireMock.Util;
|
|
||||||
|
|
||||||
namespace WireMock.Net.StandAlone.NETCoreApp
|
namespace WireMock.Net.StandAlone.NETCoreApp;
|
||||||
|
|
||||||
|
static class Program
|
||||||
{
|
{
|
||||||
static class Program
|
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
||||||
|
// private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||||
|
|
||||||
|
private static int sleepTime = 30000;
|
||||||
|
private static WireMockServer _server;
|
||||||
|
|
||||||
|
static async Task Main(string[] args)
|
||||||
{
|
{
|
||||||
private static readonly ILoggerRepository LogRepository = LogManager.GetRepository(Assembly.GetEntryAssembly());
|
//await TestAsync().ConfigureAwait(false);
|
||||||
// private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
//return;
|
||||||
|
|
||||||
private static int sleepTime = 30000;
|
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||||
private static WireMockServer _server;
|
|
||||||
|
|
||||||
static void Main(string[] args)
|
if (!WireMockServerSettingsParser.TryParseArguments(args, out var settings, new WireMockLog4NetLogger()))
|
||||||
{
|
{
|
||||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
return;
|
||||||
|
|
||||||
if (!WireMockServerSettingsParser.TryParseArguments(args, out var settings, new WireMockLog4NetLogger()))
|
|
||||||
{
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
|
||||||
|
|
||||||
_server = WireMockServer.Start(settings);
|
|
||||||
|
|
||||||
//_server.Given(Request.Create().WithPath("/api/sap")
|
|
||||||
// .UsingPost()
|
|
||||||
// .WithBody((IBodyData xmlData) =>
|
|
||||||
// {
|
|
||||||
// //xmlData is always null
|
|
||||||
// return true;
|
|
||||||
// }))
|
|
||||||
// .RespondWith(Response.Create().WithStatusCode(System.Net.HttpStatusCode.OK));
|
|
||||||
|
|
||||||
//_server
|
|
||||||
// .Given(Request.Create()
|
|
||||||
// .UsingAnyMethod())
|
|
||||||
// .RespondWith(Response.Create()
|
|
||||||
// .WithTransformer()
|
|
||||||
// .WithBody("{{Random Type=\"Integer\" Min=100 Max=999999}} {{DateTime.Now}} {{DateTime.Now \"yyyy-MMM\"}} {{String.Format (DateTime.Now) \"MMM-dd\"}}"));
|
|
||||||
|
|
||||||
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
|
|
||||||
|
|
||||||
Console.CancelKeyPress += (s, e) =>
|
|
||||||
{
|
|
||||||
Stop("CancelKeyPress");
|
|
||||||
};
|
|
||||||
|
|
||||||
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
|
|
||||||
{
|
|
||||||
Stop("AssemblyLoadContext.Default.Unloading");
|
|
||||||
};
|
|
||||||
|
|
||||||
while (true)
|
|
||||||
{
|
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running : {_server.IsStarted}");
|
|
||||||
Thread.Sleep(sleepTime);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void Stop(string why)
|
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||||
|
|
||||||
|
_server = WireMockServer.Start(settings);
|
||||||
|
|
||||||
|
//_server.Given(Request.Create().WithPath("/api/sap")
|
||||||
|
// .UsingPost()
|
||||||
|
// .WithBody((IBodyData xmlData) =>
|
||||||
|
// {
|
||||||
|
// //xmlData is always null
|
||||||
|
// return true;
|
||||||
|
// }))
|
||||||
|
// .RespondWith(Response.Create().WithStatusCode(System.Net.HttpStatusCode.OK));
|
||||||
|
|
||||||
|
//_server
|
||||||
|
// .Given(Request.Create()
|
||||||
|
// .UsingAnyMethod())
|
||||||
|
// .RespondWith(Response.Create()
|
||||||
|
// .WithTransformer()
|
||||||
|
// .WithBody("{{Random Type=\"Integer\" Min=100 Max=999999}} {{DateTime.Now}} {{DateTime.Now \"yyyy-MMM\"}} {{String.Format (DateTime.Now) \"MMM-dd\"}}"));
|
||||||
|
|
||||||
|
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
|
||||||
|
|
||||||
|
Console.CancelKeyPress += (s, e) =>
|
||||||
{
|
{
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopping because '{why}'");
|
Stop("CancelKeyPress");
|
||||||
_server.Stop();
|
};
|
||||||
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopped");
|
|
||||||
|
System.Runtime.Loader.AssemblyLoadContext.Default.Unloading += ctx =>
|
||||||
|
{
|
||||||
|
Stop("AssemblyLoadContext.Default.Unloading");
|
||||||
|
};
|
||||||
|
|
||||||
|
while (true)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server running : {_server.IsStarted}");
|
||||||
|
Thread.Sleep(sleepTime);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void Stop(string why)
|
||||||
|
{
|
||||||
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopping because '{why}'");
|
||||||
|
_server.Stop();
|
||||||
|
Console.WriteLine($"{DateTime.UtcNow} WireMock.Net server stopped");
|
||||||
|
}
|
||||||
|
|
||||||
|
private static async Task TestAsync()
|
||||||
|
{
|
||||||
|
for (var i = 0; i < 20; i++)
|
||||||
|
{
|
||||||
|
var server = WireMockServer.Start();
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(
|
||||||
|
Request.Create().WithPath("/some/thing").UsingGet()
|
||||||
|
)
|
||||||
|
.RespondWith(
|
||||||
|
Response.Create()
|
||||||
|
.WithStatusCode(200)
|
||||||
|
.WithHeader("Content-Type", "text/plain")
|
||||||
|
.WithBody("Hello world! : " + i)
|
||||||
|
);
|
||||||
|
|
||||||
|
server
|
||||||
|
.Given(
|
||||||
|
Request.Create().WithPath("/some/thing").UsingGet()
|
||||||
|
)
|
||||||
|
.RespondWith(
|
||||||
|
Response.Create()
|
||||||
|
.WithStatusCode(200)
|
||||||
|
.WithHeader("Content-Type", "text/plain")
|
||||||
|
.WithBody("Hello world duplicate! : " + i)
|
||||||
|
);
|
||||||
|
|
||||||
|
var client = server.CreateClient();
|
||||||
|
|
||||||
|
var response = await client.GetAsync($"{server.Url}/some/thing").ConfigureAwait(false);
|
||||||
|
var content = await response.Content.ReadAsStringAsync().ConfigureAwait(false);
|
||||||
|
Console.WriteLine($"counter {i} value:{content}");
|
||||||
|
|
||||||
|
server.Reset();
|
||||||
|
server.Dispose();
|
||||||
|
server.Stop();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,44 +1,43 @@
|
|||||||
using System;
|
using System;
|
||||||
using log4net;
|
using log4net;
|
||||||
using Newtonsoft.Json;
|
using Newtonsoft.Json;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
|
|
||||||
namespace WireMock.Net.StandAlone.NETCoreApp
|
namespace WireMock.Net.StandAlone.NETCoreApp;
|
||||||
|
|
||||||
|
internal class WireMockLog4NetLogger : IWireMockLogger
|
||||||
{
|
{
|
||||||
internal class WireMockLog4NetLogger : IWireMockLogger
|
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
||||||
|
|
||||||
|
public void Debug(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
private static readonly ILog Log = LogManager.GetLogger(typeof(Program));
|
Log.DebugFormat(formatString, args);
|
||||||
|
}
|
||||||
|
|
||||||
public void Debug(string formatString, params object[] args)
|
public void Info(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
Log.DebugFormat(formatString, args);
|
Log.InfoFormat(formatString, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Info(string formatString, params object[] args)
|
public void Warn(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
Log.InfoFormat(formatString, args);
|
Log.WarnFormat(formatString, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Warn(string formatString, params object[] args)
|
public void Error(string formatString, params object[] args)
|
||||||
{
|
{
|
||||||
Log.WarnFormat(formatString, args);
|
Log.ErrorFormat(formatString, args);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Error(string formatString, params object[] args)
|
public void Error(string message, Exception exception)
|
||||||
{
|
{
|
||||||
Log.ErrorFormat(formatString, args);
|
Log.Error(message, exception);
|
||||||
}
|
}
|
||||||
|
|
||||||
public void Error(string message, Exception exception)
|
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
||||||
{
|
{
|
||||||
Log.Error(message, exception);
|
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||||
}
|
Log.DebugFormat("Admin[{0}] {1}", isAdminRequest, message);
|
||||||
|
|
||||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminRequest)
|
|
||||||
{
|
|
||||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
|
||||||
Log.DebugFormat("Admin[{0}] {1}", isAdminRequest, message);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -19,12 +19,12 @@ public class CookieModel
|
|||||||
public IList<MatcherModel>? Matchers { get; set; }
|
public IList<MatcherModel>? Matchers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ignore case.
|
/// Gets or sets the ignore case for the Cookie Name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? IgnoreCase { get; set; }
|
public bool? IgnoreCase { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reject on match.
|
/// Gets or sets the Reject on match for the Cookie Name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? RejectOnMatch { get; set; }
|
public bool? RejectOnMatch { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
namespace WireMock.Admin.Mappings
|
namespace WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Fault Model
|
||||||
|
/// </summary>
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class FaultModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Fault Model
|
/// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE or MALFORMED_RESPONSE_CHUNK.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FluentBuilder.AutoGenerateBuilder]
|
public string? Type { get; set; }
|
||||||
public class FaultModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the fault. Can be null, "", NONE, EMPTY_RESPONSE, MALFORMED_RESPONSE_CHUNK or RANDOM_DATA_THEN_CLOSE.
|
|
||||||
/// </summary>
|
|
||||||
public string Type { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the fault percentage.
|
/// Gets or sets the fault percentage.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public double? Percentage { get; set; }
|
public double? Percentage { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -9,7 +9,7 @@ namespace WireMock.Admin.Mappings;
|
|||||||
public class HeaderModel
|
public class HeaderModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the name.
|
/// Gets or sets the name (key).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string Name { get; set; } = null!;
|
public string Name { get; set; } = null!;
|
||||||
|
|
||||||
@@ -19,12 +19,12 @@ public class HeaderModel
|
|||||||
public IList<MatcherModel>? Matchers { get; set; }
|
public IList<MatcherModel>? Matchers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the ignore case.
|
/// Gets or sets the ignore case for the Header Key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? IgnoreCase { get; set; }
|
public bool? IgnoreCase { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reject on match.
|
/// Gets or sets the Reject on match for the Header Key.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? RejectOnMatch { get; set; }
|
public bool? RejectOnMatch { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -14,6 +14,11 @@ public class MappingModel
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid? Guid { get; set; }
|
public Guid? Guid { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The datetime when this mapping was created or updated.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the TimeSettings when which this mapping should be used.
|
/// Gets or sets the TimeSettings when which this mapping should be used.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -79,4 +84,18 @@ public class MappingModel
|
|||||||
/// Fire and forget for webhooks.
|
/// Fire and forget for webhooks.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseWebhooksFireAndForget { get; set; }
|
public bool? UseWebhooksFireAndForget { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data Object which can be used when WithTransformer is used.
|
||||||
|
/// e.g. lookup an path in this object using
|
||||||
|
/// <example>
|
||||||
|
/// lookup data "1"
|
||||||
|
/// </example>
|
||||||
|
/// </summary>
|
||||||
|
public object? Data { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The probability when this request should be matched. Value is between 0 and 1. [Optional]
|
||||||
|
/// </summary>
|
||||||
|
public double? Probability { get; set; }
|
||||||
}
|
}
|
||||||
@@ -1,121 +1,120 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
|
||||||
namespace WireMock.Admin.Mappings
|
namespace WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ResponseModel
|
||||||
|
/// </summary>
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class ResponseModel
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ResponseModel
|
/// Gets or sets the HTTP status.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[FluentBuilder.AutoGenerateBuilder]
|
public object? StatusCode { get; set; }
|
||||||
public class ResponseModel
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets or sets the HTTP status.
|
|
||||||
/// </summary>
|
|
||||||
public object? StatusCode { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body destination (SameAsSource, String or Bytes).
|
/// Gets or sets the body destination (SameAsSource, String or Bytes).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? BodyDestination { get; set; }
|
public string? BodyDestination { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body.
|
/// Gets or sets the body.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? Body { get; set; }
|
public string? Body { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body (as JSON object).
|
/// Gets or sets the body (as JSON object).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public object? BodyAsJson { get; set; }
|
public object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
/// Gets or sets a value indicating whether child objects to be indented according to the Newtonsoft.Json.JsonTextWriter.Indentation and Newtonsoft.Json.JsonTextWriter.IndentChar settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? BodyAsJsonIndented { get; set; }
|
public bool? BodyAsJsonIndented { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body (as bytearray).
|
/// Gets or sets the body (as bytearray).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public byte[]? BodyAsBytes { get; set; }
|
public byte[]? BodyAsBytes { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body as a file.
|
/// Gets or sets the body as a file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? BodyAsFile { get; set; }
|
public string? BodyAsFile { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Is the body as file cached?
|
/// Is the body as file cached?
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? BodyAsFileIsCached { get; set; }
|
public bool? BodyAsFileIsCached { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the body encoding.
|
/// Gets or sets the body encoding.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public EncodingModel? BodyEncoding { get; set; }
|
public EncodingModel? BodyEncoding { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use ResponseMessage Transformer.
|
/// Use ResponseMessage Transformer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseTransformer { get; set; }
|
public bool? UseTransformer { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the type of the transformer.
|
/// Gets the type of the transformer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? TransformerType { get; set; }
|
public string? TransformerType { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use the Handlebars transformer for the content from the referenced BodyAsFile.
|
/// Use the Handlebars transformer for the content from the referenced BodyAsFile.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseTransformerForBodyAsFile { get; set; }
|
public bool? UseTransformerForBodyAsFile { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
/// The ReplaceNodeOptions to use when transforming a JSON node.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? TransformerReplaceNodeOptions { get; set; }
|
public string? TransformerReplaceNodeOptions { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the headers.
|
/// Gets or sets the headers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public IDictionary<string, object>? Headers { get; set; }
|
public IDictionary<string, object>? Headers { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Headers (Raw).
|
/// Gets or sets the Headers (Raw).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? HeadersRaw { get; set; }
|
public string? HeadersRaw { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the delay in milliseconds.
|
/// Gets or sets the delay in milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? Delay { get; set; }
|
public int? Delay { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the minimum random delay in milliseconds.
|
/// Gets or sets the minimum random delay in milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MinimumRandomDelay { get; set; }
|
public int? MinimumRandomDelay { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the maximum random delay in milliseconds.
|
/// Gets or sets the maximum random delay in milliseconds.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public int? MaximumRandomDelay { get; set; }
|
public int? MaximumRandomDelay { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the Proxy URL.
|
/// Gets or sets the Proxy URL.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? ProxyUrl { get; set; }
|
public string? ProxyUrl { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The client X509Certificate2 Thumbprint or SubjectName to use.
|
/// The client X509Certificate2 Thumbprint or SubjectName to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public string? X509Certificate2ThumbprintOrSubjectName { get; set; }
|
public string? X509Certificate2ThumbprintOrSubjectName { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the fault.
|
/// Gets or sets the fault.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public FaultModel? Fault { get; set; }
|
public FaultModel? Fault { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets or sets the WebProxy settings.
|
/// Gets or sets the WebProxy settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public WebProxyModel? WebProxy { get; set; }
|
public WebProxyModel? WebProxy { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -68,4 +68,9 @@ public class ProxyAndRecordSettingsModel
|
|||||||
/// Append an unique GUID to the filename from the saved mapping file.
|
/// Append an unique GUID to the filename from the saved mapping file.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool AppendGuidToSavedMappingFile { get; set; }
|
public bool AppendGuidToSavedMappingFile { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines the Replace Settings
|
||||||
|
/// </summary>
|
||||||
|
public ProxyUrlReplaceSettingsModel? ReplaceSettings { get; set; }
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,23 @@
|
|||||||
|
namespace WireMock.Admin.Settings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines an old path param and a new path param to be replaced when proxying.
|
||||||
|
/// </summary>
|
||||||
|
[FluentBuilder.AutoGenerateBuilder]
|
||||||
|
public class ProxyUrlReplaceSettingsModel
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The old path value to be replaced by the new path value
|
||||||
|
/// </summary>
|
||||||
|
public string OldValue { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The new path value to replace the old value with
|
||||||
|
/// </summary>
|
||||||
|
public string NewValue { get; set; } = null!;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Defines if the case should be ignore when replacing.
|
||||||
|
/// </summary>
|
||||||
|
public bool IgnoreCase { get; set; }
|
||||||
|
}
|
||||||
@@ -31,27 +31,49 @@ public class SettingsModel
|
|||||||
public int? MaxRequestLogCount { get; set; }
|
public int? MaxRequestLogCount { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allow a Body for all HTTP Methods. (default set to false).
|
/// Allow a Body for all HTTP Methods. (default set to <c>false</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? AllowBodyForAllHttpMethods { get; set; }
|
public bool? AllowBodyForAllHttpMethods { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Handle all requests synchronously. (default set to false).
|
/// Allow only a HttpStatus Code in the response which is defined. (default set to <c>false</c>).
|
||||||
|
/// - false : also null, 0, empty or invalid HttpStatus codes are allowed.
|
||||||
|
/// - true : only codes defined in <see cref="System.Net.HttpStatusCode"/> are allowed.
|
||||||
|
/// </summary>
|
||||||
|
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to true to disable Json deserialization when processing requests. (default set to <c>false</c>).
|
||||||
|
/// </summary>
|
||||||
|
public bool? DisableJsonBodyParsing { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Disable support for GZip and Deflate request body decompression. (default set to <c>false</c>).
|
||||||
|
/// </summary>
|
||||||
|
public bool? DisableRequestBodyDecompressing { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set to true to disable FormUrlEncoded deserializing when processing requests. (default set to <c>false</c>).
|
||||||
|
/// </summary>
|
||||||
|
public bool? DisableDeserializeFormUrlEncoded { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Handle all requests synchronously. (default set to <c>false</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? HandleRequestsSynchronously { get; set; }
|
public bool? HandleRequestsSynchronously { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Throw an exception when the Matcher fails because of invalid input. (default set to false).
|
/// Throw an exception when the Matcher fails because of invalid input. (default set to <c>false</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to true).
|
/// Use the RegexExtended instead of the default <see cref="Regex"/>. (default set to <c>true</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseRegexExtended { get; set; }
|
public bool? UseRegexExtended { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to false).
|
/// Save unmatched requests to a file using the <see cref="IFileSystemHandler"/>. (default set to <c>false</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? SaveUnmatchedRequests { get; set; }
|
public bool? SaveUnmatchedRequests { get; set; }
|
||||||
|
|
||||||
@@ -86,7 +108,7 @@ public class SettingsModel
|
|||||||
public HostingScheme? HostingScheme { get; set; }
|
public HostingScheme? HostingScheme { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to false).
|
/// Don't save the response-string in the LogEntry when WithBody(Func{IRequestMessage, string}) or WithBody(Func{IRequestMessage, Task{string}}) is used. (default set to <c>false</c>).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
public bool? DoNotSaveDynamicResponseInLogEntry { get; set; }
|
||||||
|
|
||||||
@@ -96,4 +118,16 @@ public class SettingsModel
|
|||||||
/// Default value = "All".
|
/// Default value = "All".
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
public QueryParameterMultipleValueSupport? QueryParameterMultipleValueSupport { get; set; }
|
||||||
|
|
||||||
|
#if NETSTANDARD1_3_OR_GREATER || NET461
|
||||||
|
/// <summary>
|
||||||
|
/// Server client certificate mode
|
||||||
|
/// </summary>
|
||||||
|
public ClientCertificateMode ClientCertificateMode { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Whether to accept any client certificate
|
||||||
|
/// </summary>
|
||||||
|
public bool AcceptAnyClientCertificate { get; set; }
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,139 @@
|
|||||||
|
using System;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// RequestModelBuilder
|
||||||
|
/// </summary>
|
||||||
|
public partial class RequestModelBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// UsingConnect: add HTTP Method matching on `CONNECT`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingConnect() => WithMethods("CONNECT");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingDelete: add HTTP Method matching on `DELETE`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingDelete() => WithMethods("DELETE");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingGet: add HTTP Method matching on `GET`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingGet() => WithMethods("GET");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingHead: Add HTTP Method matching on `HEAD`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingHead() => WithMethods("HEAD");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingPost: add HTTP Method matching on `POST`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingPost() => WithMethods("POST");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingPatch: add HTTP Method matching on `PATCH`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingPatch() => WithMethods("PATCH");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingPut: add HTTP Method matching on `OPTIONS`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingOptions() => WithMethods("OPTIONS");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingPut: add HTTP Method matching on `PUT`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingPut() => WithMethods("PUT");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingTrace: add HTTP Method matching on `TRACE`.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingTrace() => WithMethods("TRACE");
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UsingAnyMethod: add HTTP Method matching on any method.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>The <see cref="RequestModelBuilder"/>.</returns>
|
||||||
|
public RequestModelBuilder UsingAnyMethod() => this;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the ClientIP.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithClientIP(string value) => WithClientIP(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the ClientIP.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithClientIP(ClientIPModel value) => WithClientIP(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the ClientIP.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithClientIP(Action<ClientIPModelBuilder> action)
|
||||||
|
{
|
||||||
|
return WithClientIP(() =>
|
||||||
|
{
|
||||||
|
var builder = new ClientIPModelBuilder();
|
||||||
|
action(builder);
|
||||||
|
return builder.Build();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Path.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithPath(string value) => WithPath(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Path.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithPath(PathModel value) => WithPath(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Path.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithPath(Action<PathModelBuilder> action)
|
||||||
|
{
|
||||||
|
return WithPath(() =>
|
||||||
|
{
|
||||||
|
var builder = new PathModelBuilder();
|
||||||
|
action(builder);
|
||||||
|
return builder.Build();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Url.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithUrl(string value) => WithUrl(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Url.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithUrl(UrlModel value) => WithUrl(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Url.
|
||||||
|
/// </summary>
|
||||||
|
public RequestModelBuilder WithUrl(Action<UrlModelBuilder> action)
|
||||||
|
{
|
||||||
|
return WithUrl(() =>
|
||||||
|
{
|
||||||
|
var builder = new UrlModelBuilder();
|
||||||
|
action(builder);
|
||||||
|
return builder.Build();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,36 @@
|
|||||||
|
using System;
|
||||||
|
using System.Net;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ResponseModelBuilder
|
||||||
|
/// </summary>
|
||||||
|
public partial class ResponseModelBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Set the StatusCode.
|
||||||
|
/// </summary>
|
||||||
|
public ResponseModelBuilder WithStatusCode(int value) => WithStatusCode(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the StatusCode.
|
||||||
|
/// </summary>
|
||||||
|
public ResponseModelBuilder WithStatusCode(HttpStatusCode value) => WithStatusCode(() => value);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the Delay.
|
||||||
|
/// </summary>
|
||||||
|
public ResponseModelBuilder WithDelay(TimeSpan value) => WithDelay((int) value.TotalMilliseconds);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the MinimumRandomDelay.
|
||||||
|
/// </summary>
|
||||||
|
public ResponseModelBuilder WithMinimumRandomDelay(TimeSpan value) => WithMinimumRandomDelay((int)value.TotalMilliseconds);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Set the MaximumRandomDelay.
|
||||||
|
/// </summary>
|
||||||
|
public ResponseModelBuilder WithMaximumRandomDelay(TimeSpan value) => WithMaximumRandomDelay((int)value.TotalMilliseconds);
|
||||||
|
}
|
||||||
@@ -1,5 +1,8 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
#if NETSTANDARD1_3_OR_GREATER || NET461
|
||||||
|
using System.Security.Cryptography.X509Certificates;
|
||||||
|
#endif
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -75,6 +78,11 @@ public interface IRequestMessage
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
IDictionary<string, WireMockList<string>>? Query { get; }
|
IDictionary<string, WireMockList<string>>? Query { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the query.
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<string, WireMockList<string>>? QueryIgnoreCase { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the raw query.
|
/// Gets the raw query.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -134,4 +142,19 @@ public interface IRequestMessage
|
|||||||
/// Gets the origin
|
/// Gets the origin
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string Origin { get; }
|
string Origin { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get a query parameter.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="key">The key.</param>
|
||||||
|
/// <param name="ignoreCase">Defines if the key should be matched using case-ignore.</param>
|
||||||
|
/// <returns>The query parameter value as WireMockList or null when not found.</returns>
|
||||||
|
WireMockList<string>? GetParameter(string key, bool ignoreCase = false);
|
||||||
|
|
||||||
|
#if NETSTANDARD1_3_OR_GREATER || NET461
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the connection's client certificate
|
||||||
|
/// </summary>
|
||||||
|
X509Certificate2? ClientCertificate { get; }
|
||||||
|
#endif
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
@@ -38,6 +39,11 @@ public interface IBodyData
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
string? BodyAsString { get; set; }
|
string? BodyAsString { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The body as Form UrlEncoded dictionary.
|
||||||
|
/// </summary>
|
||||||
|
IDictionary<string, string>? BodyAsFormUrlEncoded { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The detected body type (detection based on body content).
|
/// The detected body type (detection based on body content).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,23 +1,23 @@
|
|||||||
namespace WireMock.ResponseBuilders
|
// ReSharper disable InconsistentNaming
|
||||||
|
namespace WireMock.ResponseBuilders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The FaultType enumeration
|
||||||
|
/// </summary>
|
||||||
|
public enum FaultType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The FaultType enumeration
|
/// No Fault
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum FaultType
|
NONE,
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// No Fault
|
|
||||||
/// </summary>
|
|
||||||
NONE,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Return a completely empty response.
|
/// Return a completely empty response.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
EMPTY_RESPONSE,
|
EMPTY_RESPONSE,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Send a defined status header, then garbage, then close the connection.
|
/// Send a defined status header, then garbage, then close the connection.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MALFORMED_RESPONSE_CHUNK
|
MALFORMED_RESPONSE_CHUNK
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -3,212 +3,232 @@ using System.Collections.Generic;
|
|||||||
using System.Collections.Specialized;
|
using System.Collections.Specialized;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Server
|
namespace WireMock.Server;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The fluent mock server interface.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWireMockServer : IDisposable
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The fluent mock server interface.
|
/// Gets a value indicating whether this server is started.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWireMockServer : IDisposable
|
bool IsStarted { get; }
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Gets a value indicating whether this server is started.
|
|
||||||
/// </summary>
|
|
||||||
bool IsStarted { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the request logs.
|
/// Gets a value indicating whether this server is started with the admin interface enabled.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IEnumerable<ILogEntry> LogEntries { get; }
|
bool IsStartedWithAdminInterface { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the mappings as MappingModels.
|
/// Gets the request logs.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
IEnumerable<MappingModel> MappingModels { get; }
|
IEnumerable<ILogEntry> LogEntries { get; }
|
||||||
|
|
||||||
// <summary>
|
/// <summary>
|
||||||
// Gets the mappings.
|
/// Gets the mappings as MappingModels.
|
||||||
// </summary>
|
/// </summary>
|
||||||
//[PublicAPI]
|
IEnumerable<MappingModel> MappingModels { get; }
|
||||||
//IEnumerable<IMapping> Mappings { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
// <summary>
|
||||||
/// Gets the ports.
|
// Gets the mappings.
|
||||||
/// </summary>
|
// </summary>
|
||||||
List<int> Ports { get; }
|
//[PublicAPI]
|
||||||
|
//IEnumerable<IMapping> Mappings { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the first port.
|
/// Gets the ports.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
int Port { get; }
|
List<int> Ports { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the urls.
|
/// Gets the first port.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string[] Urls { get; }
|
int Port { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the first url.
|
/// Gets the urls.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string? Url { get; }
|
string[] Urls { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the consumer.
|
/// Gets the first url.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string? Consumer { get; }
|
string? Url { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the provider.
|
/// Gets the consumer.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
string? Provider { get; }
|
string? Consumer { get; }
|
||||||
|
|
||||||
//ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
|
/// <summary>
|
||||||
|
/// Gets the provider.
|
||||||
|
/// </summary>
|
||||||
|
string? Provider { get; }
|
||||||
|
|
||||||
/// <summary>
|
//ConcurrentDictionary<string, ScenarioState> Scenarios { get; }
|
||||||
/// Occurs when [log entries changed].
|
|
||||||
/// </summary>
|
|
||||||
event NotifyCollectionChangedEventHandler LogEntriesChanged;
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Adds a 'catch all mapping'
|
/// Occurs when [log entries changed].
|
||||||
///
|
/// </summary>
|
||||||
/// - matches all Paths and any Methods
|
event NotifyCollectionChangedEventHandler LogEntriesChanged;
|
||||||
/// - priority is set to 1000
|
|
||||||
/// - responds with a 404 "No matching mapping found"
|
|
||||||
/// </summary>
|
|
||||||
void AddCatchAllMapping();
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The add request processing delay.
|
/// Adds a 'catch all mapping'
|
||||||
/// </summary>
|
///
|
||||||
/// <param name="delay">The delay.</param>
|
/// - matches all Paths and any Methods
|
||||||
void AddGlobalProcessingDelay(TimeSpan delay);
|
/// - priority is set to 1000
|
||||||
|
/// - responds with a 404 "No matching mapping found"
|
||||||
|
/// </summary>
|
||||||
|
void AddCatchAllMapping();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Allows the partial mapping.
|
/// The add request processing delay.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void AllowPartialMapping(bool allow = true);
|
/// <param name="delay">The delay.</param>
|
||||||
|
void AddGlobalProcessingDelay(TimeSpan delay);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes a LogEntry.
|
/// Allows the partial mapping.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The unique identifier.</param>
|
void AllowPartialMapping(bool allow = true);
|
||||||
bool DeleteLogEntry(Guid guid);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Deletes the mapping.
|
/// Deletes a LogEntry.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The unique identifier.</param>
|
/// <param name="guid">The unique identifier.</param>
|
||||||
bool DeleteMapping(Guid guid);
|
bool DeleteLogEntry(Guid guid);
|
||||||
|
|
||||||
//IEnumerable<LogEntry> FindLogEntries([NotNull] params IRequestMatcher[] matchers);
|
/// <summary>
|
||||||
|
/// Deletes the mapping.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guid">The unique identifier.</param>
|
||||||
|
bool DeleteMapping(Guid guid);
|
||||||
|
|
||||||
// IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
|
//IEnumerable<LogEntry> FindLogEntries([NotNull] params IRequestMatcher[] matchers);
|
||||||
|
|
||||||
/// <summary>
|
// IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
|
||||||
/// Reads a static mapping file and adds or updates a single mapping.
|
|
||||||
///
|
|
||||||
/// Calling this method manually forces WireMock.Net to read and apply the specified static mapping file.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to the static mapping file.</param>
|
|
||||||
bool ReadStaticMappingAndAddOrUpdate(string path);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Reads the static mappings from a folder.
|
/// Reads a static mapping file and adds or updates a single mapping.
|
||||||
/// (This method is also used when WireMockServerSettings.ReadStaticMappings is set to true.
|
///
|
||||||
///
|
/// Calling this method manually forces WireMock.Net to read and apply the specified static mapping file.
|
||||||
/// Calling this method manually forces WireMock.Net to read and apply all static mapping files in the specified folder.
|
/// </summary>
|
||||||
/// </summary>
|
/// <param name="path">The path to the static mapping file.</param>
|
||||||
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
bool ReadStaticMappingAndAddOrUpdate(string path);
|
||||||
void ReadStaticMappings(string? folder = null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Removes the authentication.
|
/// Reads the static mappings from a folder.
|
||||||
/// </summary>
|
/// (This method is also used when WireMockServerSettings.ReadStaticMappings is set to true.
|
||||||
void RemoveAuthentication();
|
///
|
||||||
|
/// Calling this method manually forces WireMock.Net to read and apply all static mapping files in the specified folder.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
||||||
|
void ReadStaticMappings(string? folder = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets LogEntries and Mappings.
|
/// Removes the authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Reset();
|
void RemoveAuthentication();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the Mappings.
|
/// Resets LogEntries and Mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ResetMappings();
|
void Reset();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets all Scenarios.
|
/// Resets the Mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ResetScenarios();
|
void ResetMappings();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets a specific Scenario by the name.
|
/// Resets all Scenarios.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
bool ResetScenario(string name);
|
void ResetScenarios();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Resets the LogEntries.
|
/// Resets a specific Scenario by the name.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void ResetLogEntries();
|
bool ResetScenario(string name);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Saves the static mappings.
|
/// Resets the LogEntries.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
void ResetLogEntries();
|
||||||
void SaveStaticMappings(string? folder = null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the basic authentication.
|
/// Saves the static mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="tenant">The Tenant.</param>
|
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
||||||
/// <param name="audience">The Audience or Resource.</param>
|
void SaveStaticMappings(string? folder = null);
|
||||||
void SetAzureADAuthentication(string tenant, string audience);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the basic authentication.
|
/// Sets the basic authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="username">The username.</param>
|
/// <param name="tenant">The Tenant.</param>
|
||||||
/// <param name="password">The password.</param>
|
/// <param name="audience">The Audience or Resource.</param>
|
||||||
void SetBasicAuthentication(string username, string password);
|
void SetAzureADAuthentication(string tenant, string audience);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets the maximum RequestLog count.
|
/// Sets the basic authentication.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="maxRequestLogCount">The maximum RequestLog count.</param>
|
/// <param name="username">The username.</param>
|
||||||
void SetMaxRequestLogCount(int? maxRequestLogCount);
|
/// <param name="password">The password.</param>
|
||||||
|
void SetBasicAuthentication(string username, string password);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Sets RequestLog expiration in hours.
|
/// Sets the maximum RequestLog count.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestLogExpirationDuration">The RequestLog expiration in hours.</param>
|
/// <param name="maxRequestLogCount">The maximum RequestLog count.</param>
|
||||||
void SetRequestLogExpirationDuration(int? requestLogExpirationDuration);
|
void SetMaxRequestLogCount(int? maxRequestLogCount);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Stop this server.
|
/// Sets RequestLog expiration in hours.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
void Stop();
|
/// <param name="requestLogExpirationDuration">The RequestLog expiration in hours.</param>
|
||||||
|
void SetRequestLogExpirationDuration(int? requestLogExpirationDuration);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Watches the static mappings for changes.
|
/// Stop this server.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
void Stop();
|
||||||
void WatchStaticMappings(string? folder = null);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register the mappings (via <see cref="MappingModel"/>).
|
/// Watches the static mappings for changes.
|
||||||
///
|
/// </summary>
|
||||||
/// This can be used if you have 1 or more <see cref="MappingModel"/> defined and want to register these in WireMock.Net directly instead of using the fluent syntax.
|
/// <param name="folder">The optional folder. If not defined, use {CurrentFolder}/__admin/mappings</param>
|
||||||
/// </summary>
|
void WatchStaticMappings(string? folder = null);
|
||||||
/// <param name="mappings">The MappingModels</param>
|
|
||||||
IWireMockServer WithMapping(params MappingModel[] mappings);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Register the mappings (via json string).
|
/// Register the mappings (via <see cref="MappingModel"/>).
|
||||||
///
|
///
|
||||||
/// This can be used if you the mappings as json string defined and want to register these in WireMock.Net directly instead of using the fluent syntax.
|
/// This can be used if you have 1 or more <see cref="MappingModel"/> defined and want to register these in WireMock.Net directly instead of using the fluent syntax.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mappings">The mapping(s) as json string.</param>
|
/// <param name="mappings">The MappingModels</param>
|
||||||
IWireMockServer WithMapping(string mappings);
|
IWireMockServer WithMapping(params MappingModel[] mappings);
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Register the mappings (via json string).
|
||||||
|
///
|
||||||
|
/// This can be used if you the mappings as json string defined and want to register these in WireMock.Net directly instead of using the fluent syntax.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mappings">The mapping(s) as json string.</param>
|
||||||
|
IWireMockServer WithMapping(string mappings);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the C# code for a mapping.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guid">The Mapping Guid.</param>
|
||||||
|
/// <param name="converterType">The <see cref="MappingConverterType"/></param>
|
||||||
|
/// <returns>C# code (null in case the mapping is not found)</returns>
|
||||||
|
string? MappingToCSharpCode(Guid guid, MappingConverterType converterType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the C# code for all mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="converterType">The <see cref="MappingConverterType"/></param>
|
||||||
|
/// <returns>C# code</returns>
|
||||||
|
public string MappingsToCSharpCode(MappingConverterType converterType);
|
||||||
}
|
}
|
||||||
@@ -1,38 +1,42 @@
|
|||||||
namespace WireMock.Types
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The BodyType
|
||||||
|
/// </summary>
|
||||||
|
public enum BodyType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The BodyType
|
/// No body present
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum BodyType
|
None,
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// No body present
|
|
||||||
/// </summary>
|
|
||||||
None,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body is a String
|
/// Body is a String
|
||||||
/// </summary>
|
/// </summary>
|
||||||
String,
|
String,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body is a Json object
|
/// Body is a Json object
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Json,
|
Json,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body is a Byte array
|
/// Body is a Byte array
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Bytes,
|
Bytes,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body is a File
|
/// Body is a File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
File,
|
File,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Body is a MultiPart
|
/// Body is a MultiPart
|
||||||
/// </summary>
|
/// </summary>
|
||||||
MultiPart
|
MultiPart,
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Body is a String which is x-www-form-urlencoded.
|
||||||
|
/// </summary>
|
||||||
|
FormUrlEncoded
|
||||||
}
|
}
|
||||||
31
src/WireMock.Net.Abstractions/Types/ClientCertificateMode.cs
Normal file
31
src/WireMock.Net.Abstractions/Types/ClientCertificateMode.cs
Normal file
@@ -0,0 +1,31 @@
|
|||||||
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
#if NETSTANDARD1_3_OR_GREATER || NET461
|
||||||
|
/// <summary>
|
||||||
|
/// Describes the client certificate requirements for a HTTPS connection.
|
||||||
|
/// This enum is the same as https://learn.microsoft.com/en-us/dotnet/api/microsoft.aspnetcore.server.kestrel.https.clientcertificatemode
|
||||||
|
/// </summary>
|
||||||
|
public enum ClientCertificateMode
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// A client certificate is not required and will not be requested from clients.
|
||||||
|
/// </summary>
|
||||||
|
NoCertificate,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A client certificate will be requested; however, authentication will not fail if a certificate is not provided by the client.
|
||||||
|
/// </summary>
|
||||||
|
AllowCertificate,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A client certificate will be requested, and the client must provide a valid certificate for authentication to succeed.
|
||||||
|
/// </summary>
|
||||||
|
RequireCertificate,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// A client certificate is not required and will not be requested from clients at the start of the connection.
|
||||||
|
/// It may be requested by the application later.
|
||||||
|
/// </summary>
|
||||||
|
DelayCertificate,
|
||||||
|
}
|
||||||
|
#endif
|
||||||
11
src/WireMock.Net.Abstractions/Types/MappingConverterType.cs
Normal file
11
src/WireMock.Net.Abstractions/Types/MappingConverterType.cs
Normal file
@@ -0,0 +1,11 @@
|
|||||||
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
///
|
||||||
|
/// </summary>
|
||||||
|
public enum MappingConverterType
|
||||||
|
{
|
||||||
|
Server,
|
||||||
|
|
||||||
|
Builder
|
||||||
|
}
|
||||||
@@ -1,36 +1,25 @@
|
|||||||
using System;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Types
|
/// <summary>
|
||||||
|
/// Logic to use when replace a JSON node using the Transformer.
|
||||||
|
/// </summary>
|
||||||
|
public enum ReplaceNodeOptions
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Flags to use when replace a JSON node using the Transformer.
|
/// Try to evaluate a templated value.
|
||||||
|
/// In case this is valid, return the value and if the value can be converted to a primitive type, use that value.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Flags]
|
EvaluateAndTryToConvert = 0,
|
||||||
public enum ReplaceNodeOptions
|
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Default
|
|
||||||
/// </summary>
|
|
||||||
None = 0
|
|
||||||
|
|
||||||
///// <summary>
|
/// <summary>
|
||||||
///// Replace boolean string value to a real boolean value. (This is used by default to maintain backward compatibility.)
|
/// Try to evaluate a templated value.
|
||||||
///// </summary>
|
/// In case this is valid, return the value, else fallback to the parse behavior.
|
||||||
//Bool = 0b00000001,
|
/// </summary>
|
||||||
|
Evaluate = 1,
|
||||||
|
|
||||||
///// <summary>
|
/// <summary>
|
||||||
///// Replace integer string value to a real integer value.
|
/// Parse templated string to a templated string.
|
||||||
///// </summary>
|
/// (keep a templated string value as string value).
|
||||||
//Integer = 0b00000010,
|
/// </summary>
|
||||||
|
Parse = 2
|
||||||
///// <summary>
|
|
||||||
///// Replace long string value to a real long value.
|
|
||||||
///// </summary>
|
|
||||||
//Long = 0b00000100,
|
|
||||||
|
|
||||||
///// <summary>
|
|
||||||
///// Replace all string values to a real values.
|
|
||||||
///// </summary>
|
|
||||||
//All = Bool | Integer | Long
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,23 +1,22 @@
|
|||||||
namespace WireMock.Types
|
namespace WireMock.Types;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The ResponseMessage Transformers
|
||||||
|
/// </summary>
|
||||||
|
public enum TransformerType
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The ResponseMessage Transformers
|
/// https://github.com/Handlebars-Net/Handlebars.Net
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum TransformerType
|
Handlebars,
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// https://github.com/Handlebars-Net/Handlebars.Net
|
|
||||||
/// </summary>
|
|
||||||
Handlebars,
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://github.com/scriban/scriban : default
|
/// https://github.com/scriban/scriban : default
|
||||||
/// </summary>
|
/// </summary>
|
||||||
Scriban,
|
Scriban,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// https://github.com/scriban/scriban : DotLiquid
|
/// https://github.com/scriban/scriban : DotLiquid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
ScribanDotLiquid
|
ScribanDotLiquid
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
|
||||||
namespace WireMock.Types;
|
namespace WireMock.Types;
|
||||||
|
|
||||||
@@ -63,7 +64,8 @@ public class WireMockList<T> : List<T>
|
|||||||
return this[0]?.ToString();
|
return this[0]?.ToString();
|
||||||
|
|
||||||
default:
|
default:
|
||||||
return base.ToString();
|
var strings = this.Select(x => x as string ?? x?.ToString());
|
||||||
|
return string.Join(", ", strings);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Description>Commonly used models, enumerations and types.</Description>
|
<Description>Commonly used models, enumerations and types.</Description>
|
||||||
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.Abstractions</AssemblyTitle>
|
||||||
<Authors>Stef Heyenrath</Authors>
|
<Authors>Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net45;net451;netstandard1.0;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net45;net451;net461;netstandard1.0;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<NoWarn>$(NoWarn);1591;8603</NoWarn>
|
<NoWarn>$(NoWarn);1591;8603</NoWarn>
|
||||||
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
<AssemblyName>WireMock.Net.Abstractions</AssemblyName>
|
||||||
@@ -35,17 +35,21 @@
|
|||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
|
|
||||||
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
|
<!-- See also https://mstack.nl/blog/20210801-source-generators -->
|
||||||
<PackageReference Include="FluentBuilder" Version="0.7.0">
|
<PackageReference Include="FluentBuilder" Version="0.9.0">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<!--<ItemGroup Condition="'$(TargetFramework)' == 'net45'">
|
<ItemGroup Condition="$(TargetFramework.StartsWith('netstandard')) and '$(TargetFramework)' != 'netstandard1.0'">
|
||||||
<PackageReference Include="Nullable" Version="1.2.1">
|
<PackageReference Include="System.Security.Cryptography.X509Certificates" Version="4.3.0" />
|
||||||
|
</ItemGroup>
|
||||||
|
|
||||||
|
<ItemGroup Condition="'$(TargetFramework)' == 'net461'">
|
||||||
|
<PackageReference Include="Microsoft.NETFramework.ReferenceAssemblies.net46" Version="1.0.2">
|
||||||
<PrivateAssets>all</PrivateAssets>
|
<PrivateAssets>all</PrivateAssets>
|
||||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
<IncludeAssets>runtime; build; native; contentfiles; analyzers; buildtransitive</IncludeAssets>
|
||||||
</PackageReference>
|
</PackageReference>
|
||||||
</ItemGroup>-->
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -1,49 +1,49 @@
|
|||||||
<Project Sdk="Microsoft.NET.Sdk">
|
<Project Sdk="Microsoft.NET.Sdk">
|
||||||
|
|
||||||
<PropertyGroup>
|
<PropertyGroup>
|
||||||
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
<Description>FluentAssertions extensions for WireMock.Net</Description>
|
||||||
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
<AssemblyTitle>WireMock.Net.FluentAssertions</AssemblyTitle>
|
||||||
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
<Authors>Mahmoud Ali;Stef Heyenrath</Authors>
|
||||||
<TargetFrameworks>net451;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net451;net47;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
<AssemblyName>WireMock.Net.FluentAssertions</AssemblyName>
|
||||||
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
<PackageId>WireMock.Net.FluentAssertions</PackageId>
|
||||||
<PackageTags>wiremock;FluentAssertions;UnitTest;Assert;Assertions</PackageTags>
|
<PackageTags>wiremock;FluentAssertions;UnitTest;Assert;Assertions</PackageTags>
|
||||||
<RootNamespace>WireMock.FluentAssertions</RootNamespace>
|
<RootNamespace>WireMock.FluentAssertions</RootNamespace>
|
||||||
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A95}</ProjectGuid>
|
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A95}</ProjectGuid>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
|
||||||
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
<EmbedUntrackedSources>true</EmbedUntrackedSources>
|
||||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||||
<SignAssembly>true</SignAssembly>
|
<SignAssembly>true</SignAssembly>
|
||||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||||
<!--<DelaySign>true</DelaySign>-->
|
<!--<DelaySign>true</DelaySign>-->
|
||||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||||
<LangVersion>10</LangVersion>
|
<LangVersion>10</LangVersion>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||||
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
<GeneratePackageOnBuild>true</GeneratePackageOnBuild>
|
||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
<PackageReference Include="JetBrains.Annotations" Version="2022.3.1" PrivateAssets="All" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
|
<ItemGroup Condition="'$(TargetFramework)' == 'net451' or '$(TargetFramework)' == 'netstandard1.3'">
|
||||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
|
<ItemGroup Condition="'$(TargetFramework)' != 'net451' and '$(TargetFramework)' != 'netstandard1.3'">
|
||||||
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
<PackageReference Include="FluentAssertions" Version="6.5.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
<ProjectReference Include="..\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
</Project>
|
</Project>
|
||||||
@@ -31,13 +31,13 @@ public static class WireMockServerExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="server">The WireMockServer instance</param>
|
/// <param name="server">The WireMockServer instance</param>
|
||||||
/// <param name="path">Path containing OpenAPI file to parse and use the mappings.</param>
|
/// <param name="path">Path containing OpenAPI file to parse and use the mappings.</param>
|
||||||
/// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
|
|
||||||
/// <param name="settings">Additional settings</param>
|
/// <param name="settings">Additional settings</param>
|
||||||
|
/// <param name="diagnostic">Returns diagnostic object containing errors detected during parsing</param>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiFile(this IWireMockServer server, string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
public static IWireMockServer WithMappingFromOpenApiFile(this IWireMockServer server, string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
Guard.NotNull(server, nameof(server));
|
Guard.NotNull(server);
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
Guard.NotNullOrEmpty(path);
|
||||||
|
|
||||||
var mappings = new WireMockOpenApiParser().FromFile(path, settings, out diagnostic);
|
var mappings = new WireMockOpenApiParser().FromFile(path, settings, out diagnostic);
|
||||||
|
|
||||||
@@ -80,9 +80,9 @@ public static class WireMockServerExtensions
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="server">The WireMockServer instance</param>
|
/// <param name="server">The WireMockServer instance</param>
|
||||||
/// <param name="document">The OpenAPI document to use as mappings.</param>
|
/// <param name="document">The OpenAPI document to use as mappings.</param>
|
||||||
/// <param name="settings">Additional settings [optional]</param>
|
/// <param name="settings">Additional settings [optional].</param>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public static IWireMockServer WithMappingFromOpenApiDocument(this IWireMockServer server, OpenApiDocument document, WireMockOpenApiParserSettings settings)
|
public static IWireMockServer WithMappingFromOpenApiDocument(this IWireMockServer server, OpenApiDocument document, WireMockOpenApiParserSettings? settings = null)
|
||||||
{
|
{
|
||||||
Guard.NotNull(server);
|
Guard.NotNull(server);
|
||||||
Guard.NotNull(document);
|
Guard.NotNull(document);
|
||||||
|
|||||||
@@ -5,53 +5,69 @@ using Microsoft.OpenApi.Readers;
|
|||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Net.OpenApiParser.Settings;
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser
|
namespace WireMock.Net.OpenApiParser;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Parse a OpenApi/Swagger/V2/V3 or Raml to WireMock MappingModels.
|
||||||
|
/// </summary>
|
||||||
|
public interface IWireMockOpenApiParser
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Parse a OpenApi/Swagger/V2/V3 or Raml to WireMock MappingModels.
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a file-path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public interface IWireMockOpenApiParser
|
/// <param name="path">The path to read the OpenApi/Swagger/V2/V3 or Raml file.</param>
|
||||||
{
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
/// <summary>
|
/// <returns>MappingModel</returns>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from a file-path.
|
IReadOnlyList<MappingModel> FromFile(string path, out OpenApiDiagnostic diagnostic);
|
||||||
/// </summary>
|
|
||||||
/// <param name="path">The path to read the OpenApi/Swagger/V2/V3 or Raml file.</param>
|
|
||||||
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
|
||||||
/// <returns>MappingModel</returns>
|
|
||||||
IEnumerable<MappingModel> FromFile(string path, out OpenApiDiagnostic diagnostic);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from a file-path.
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a file-path.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="path">The path to read the OpenApi/Swagger/V2/V3 or Raml file.</param>
|
/// <param name="path">The path to read the OpenApi/Swagger/V2/V3 or Raml file.</param>
|
||||||
/// <param name="settings">Additional settings</param>
|
/// <param name="settings">Additional settings</param>
|
||||||
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <returns>MappingModel</returns>
|
||||||
IEnumerable<MappingModel> FromFile(string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic);
|
IReadOnlyList<MappingModel> FromFile(string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from an <seealso cref="OpenApiDocument"/>.
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from an <seealso cref="OpenApiDocument"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="document">The source OpenApiDocument</param>
|
/// <param name="document">The source OpenApiDocument</param>
|
||||||
/// <param name="settings">Additional settings [optional]</param>
|
/// <param name="settings">Additional settings [optional]</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <returns>MappingModel</returns>
|
||||||
IEnumerable<MappingModel> FromDocument(OpenApiDocument document, WireMockOpenApiParserSettings? settings = null);
|
IReadOnlyList<MappingModel> FromDocument(OpenApiDocument document, WireMockOpenApiParserSettings? settings = null);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from a <seealso cref="Stream"/>.
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a <seealso cref="Stream"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">The source stream</param>
|
/// <param name="stream">The source stream</param>
|
||||||
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <returns>MappingModel</returns>
|
||||||
IEnumerable<MappingModel> FromStream(Stream stream, out OpenApiDiagnostic diagnostic);
|
IReadOnlyList<MappingModel> FromStream(Stream stream, out OpenApiDiagnostic diagnostic);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Generate <see cref="IEnumerable{MappingModel}"/> from a <seealso cref="Stream"/>.
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a <seealso cref="Stream"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="stream">The source stream</param>
|
/// <param name="stream">The source stream</param>
|
||||||
/// <param name="settings">Additional settings</param>
|
/// <param name="settings">Additional settings</param>
|
||||||
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <returns>MappingModel</returns>
|
||||||
IEnumerable<MappingModel> FromStream(Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic);
|
IReadOnlyList<MappingModel> FromStream(Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic);
|
||||||
}
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a <seealso cref="string"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The source text</param>
|
||||||
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
|
/// <returns>MappingModel</returns>
|
||||||
|
IReadOnlyList<MappingModel> FromText(string text, out OpenApiDiagnostic diagnostic);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Generate <see cref="IReadOnlyList{MappingModel}"/> from a <seealso cref="string"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The source text</param>
|
||||||
|
/// <param name="settings">Additional settings</param>
|
||||||
|
/// <param name="diagnostic">OpenApiDiagnostic output</param>
|
||||||
|
/// <returns>MappingModel</returns>
|
||||||
|
IReadOnlyList<MappingModel> FromText(string text, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic);
|
||||||
}
|
}
|
||||||
@@ -23,27 +23,28 @@ internal class OpenApiPathsMapper
|
|||||||
private const string HeaderContentType = "Content-Type";
|
private const string HeaderContentType = "Content-Type";
|
||||||
|
|
||||||
private readonly WireMockOpenApiParserSettings _settings;
|
private readonly WireMockOpenApiParserSettings _settings;
|
||||||
private readonly ExampleValueGenerator _exampleValueGenerator;
|
private readonly IExampleValueGenerator _exampleValueGenerator;
|
||||||
|
private readonly IExampleValueGenerator _regexExampleValueGenerator;
|
||||||
|
|
||||||
public OpenApiPathsMapper(WireMockOpenApiParserSettings settings)
|
public OpenApiPathsMapper(WireMockOpenApiParserSettings settings)
|
||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings);
|
_settings = Guard.NotNull(settings);
|
||||||
_exampleValueGenerator = new ExampleValueGenerator(settings);
|
_exampleValueGenerator = new ExampleValueGenerator(settings);
|
||||||
|
_regexExampleValueGenerator = new RegexExampleValueGenerator(settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
public IEnumerable<MappingModel> ToMappingModels(OpenApiPaths paths, IList<OpenApiServer> servers)
|
public IReadOnlyList<MappingModel> ToMappingModels(OpenApiPaths? paths, IList<OpenApiServer> servers)
|
||||||
{
|
{
|
||||||
return paths.Select(p => MapPath(p.Key, p.Value, servers)).SelectMany(x => x);
|
return paths?
|
||||||
|
.OrderBy(p => p.Key)
|
||||||
|
.Select(p => MapPath(p.Key, p.Value, servers))
|
||||||
|
.SelectMany(x => x)
|
||||||
|
.ToArray() ?? Array.Empty<MappingModel>();
|
||||||
}
|
}
|
||||||
|
|
||||||
private IEnumerable<MappingModel> MapPaths(OpenApiPaths paths, IList<OpenApiServer> servers)
|
private IReadOnlyList<MappingModel> MapPath(string path, OpenApiPathItem pathItem, IList<OpenApiServer> servers)
|
||||||
{
|
{
|
||||||
return paths.Select(p => MapPath(p.Key, p.Value, servers)).SelectMany(x => x);
|
return pathItem.Operations.Select(o => MapOperationToMappingModel(path, o.Key.ToString().ToUpperInvariant(), o.Value, servers)).ToArray();
|
||||||
}
|
|
||||||
|
|
||||||
private IEnumerable<MappingModel> MapPath(string path, OpenApiPathItem pathItem, IList<OpenApiServer> servers)
|
|
||||||
{
|
|
||||||
return pathItem.Operations.Select(o => MapOperationToMappingModel(path, o.Key.ToString().ToUpperInvariant(), o.Value, servers));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private MappingModel MapOperationToMappingModel(string path, string httpMethod, OpenApiOperation operation, IList<OpenApiServer> servers)
|
private MappingModel MapOperationToMappingModel(string path, string httpMethod, OpenApiOperation operation, IList<OpenApiServer> servers)
|
||||||
@@ -123,7 +124,7 @@ internal class OpenApiPathsMapper
|
|||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private bool TryGetContent(IDictionary<string, OpenApiMediaType>? contents, [NotNullWhen(true)] out OpenApiMediaType? openApiMediaType, [NotNullWhen(true)] out string? contentType)
|
private static bool TryGetContent(IDictionary<string, OpenApiMediaType>? contents, [NotNullWhen(true)] out OpenApiMediaType? openApiMediaType, [NotNullWhen(true)] out string? contentType)
|
||||||
{
|
{
|
||||||
openApiMediaType = null;
|
openApiMediaType = null;
|
||||||
contentType = null;
|
contentType = null;
|
||||||
@@ -270,54 +271,19 @@ internal class OpenApiPathsMapper
|
|||||||
return newPath;
|
return newPath;
|
||||||
}
|
}
|
||||||
|
|
||||||
private string MapBasePath(IList<OpenApiServer>? servers)
|
private IDictionary<string, object>? MapHeaders(string? responseContentType, IDictionary<string, OpenApiHeader>? headers)
|
||||||
{
|
{
|
||||||
if (servers == null || servers.Count == 0)
|
var mappedHeaders = headers?.ToDictionary(
|
||||||
{
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
OpenApiServer server = servers.First();
|
|
||||||
if (Uri.TryCreate(server.Url, UriKind.RelativeOrAbsolute, out Uri uriResult))
|
|
||||||
{
|
|
||||||
return uriResult.IsAbsoluteUri ? uriResult.AbsolutePath : uriResult.ToString();
|
|
||||||
}
|
|
||||||
|
|
||||||
return string.Empty;
|
|
||||||
}
|
|
||||||
|
|
||||||
private JToken? MapOpenApiAnyToJToken(IOpenApiAny? any)
|
|
||||||
{
|
|
||||||
if (any == null)
|
|
||||||
{
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
|
|
||||||
using var outputString = new StringWriter();
|
|
||||||
var writer = new OpenApiJsonWriter(outputString);
|
|
||||||
any.Write(writer, OpenApiSpecVersion.OpenApi3_0);
|
|
||||||
|
|
||||||
if (any.AnyType == AnyType.Array)
|
|
||||||
{
|
|
||||||
return JArray.Parse(outputString.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
return JObject.Parse(outputString.ToString());
|
|
||||||
}
|
|
||||||
|
|
||||||
private IDictionary<string, object?>? MapHeaders(string responseContentType, IDictionary<string, OpenApiHeader> headers)
|
|
||||||
{
|
|
||||||
var mappedHeaders = headers.ToDictionary(
|
|
||||||
item => item.Key,
|
item => item.Key,
|
||||||
_ => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern
|
_ => GetExampleMatcherModel(null, _settings.HeaderPatternToUse).Pattern!
|
||||||
);
|
);
|
||||||
|
|
||||||
if (!string.IsNullOrEmpty(responseContentType))
|
if (!string.IsNullOrEmpty(responseContentType))
|
||||||
{
|
{
|
||||||
mappedHeaders.TryAdd(HeaderContentType, responseContentType);
|
mappedHeaders.TryAdd(HeaderContentType, responseContentType!);
|
||||||
}
|
}
|
||||||
|
|
||||||
return mappedHeaders.Keys.Any() ? mappedHeaders : null;
|
return mappedHeaders?.Keys.Any() == true ? mappedHeaders : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private IList<ParamModel>? MapQueryParameters(IEnumerable<OpenApiParameter> queryParameters)
|
private IList<ParamModel>? MapQueryParameters(IEnumerable<OpenApiParameter> queryParameters)
|
||||||
@@ -356,19 +322,38 @@ internal class OpenApiPathsMapper
|
|||||||
return list.Any() ? list : null;
|
return list.Any() ? list : null;
|
||||||
}
|
}
|
||||||
|
|
||||||
private MatcherModel GetExampleMatcherModel(OpenApiSchema? schema, ExampleValueType type)
|
private MatcherModel GetExampleMatcherModel(OpenApiSchema? schema, ExampleValueType exampleValueType)
|
||||||
{
|
{
|
||||||
return type switch
|
return exampleValueType switch
|
||||||
{
|
{
|
||||||
ExampleValueType.Value => new MatcherModel { Name = "ExactMatcher", Pattern = GetExampleValueAsStringForSchemaType(schema), IgnoreCase = _settings.IgnoreCaseExampleValues },
|
ExampleValueType.Value => new MatcherModel
|
||||||
|
{
|
||||||
|
Name = "ExactMatcher",
|
||||||
|
Pattern = GetExampleValueAsStringForSchemaType(schema, exampleValueType),
|
||||||
|
IgnoreCase = _settings.IgnoreCaseExampleValues
|
||||||
|
},
|
||||||
|
|
||||||
_ => new MatcherModel { Name = "WildcardMatcher", Pattern = "*" }
|
ExampleValueType.Regex => new MatcherModel
|
||||||
|
{
|
||||||
|
Name = "RegexMatcher",
|
||||||
|
Pattern = GetExampleValueAsStringForSchemaType(schema, exampleValueType),
|
||||||
|
IgnoreCase = _settings.IgnoreCaseExampleValues
|
||||||
|
},
|
||||||
|
|
||||||
|
_ => new MatcherModel
|
||||||
|
{
|
||||||
|
Name = "WildcardMatcher",
|
||||||
|
Pattern = "*",
|
||||||
|
IgnoreCase = _settings.IgnoreCaseExampleValues
|
||||||
|
}
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private string GetExampleValueAsStringForSchemaType(OpenApiSchema? schema)
|
private string GetExampleValueAsStringForSchemaType(OpenApiSchema? schema, ExampleValueType exampleValueType)
|
||||||
{
|
{
|
||||||
var value = _exampleValueGenerator.GetExampleValue(schema);
|
var value = exampleValueType == ExampleValueType.Regex ?
|
||||||
|
_regexExampleValueGenerator.GetExampleValue(schema) :
|
||||||
|
_exampleValueGenerator.GetExampleValue(schema);
|
||||||
|
|
||||||
return value switch
|
return value switch
|
||||||
{
|
{
|
||||||
@@ -377,4 +362,39 @@ internal class OpenApiPathsMapper
|
|||||||
_ => value.ToString(),
|
_ => value.ToString(),
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private static string MapBasePath(IList<OpenApiServer>? servers)
|
||||||
|
{
|
||||||
|
if (servers == null || servers.Count == 0)
|
||||||
|
{
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
var server = servers.First();
|
||||||
|
if (Uri.TryCreate(server.Url, UriKind.RelativeOrAbsolute, out Uri uriResult))
|
||||||
|
{
|
||||||
|
return uriResult.IsAbsoluteUri ? uriResult.AbsolutePath : uriResult.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
return string.Empty;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static JToken? MapOpenApiAnyToJToken(IOpenApiAny? any)
|
||||||
|
{
|
||||||
|
if (any == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
using var outputString = new StringWriter();
|
||||||
|
var writer = new OpenApiJsonWriter(outputString);
|
||||||
|
any.Write(writer, OpenApiSpecVersion.OpenApi3_0);
|
||||||
|
|
||||||
|
if (any.AnyType == AnyType.Array)
|
||||||
|
{
|
||||||
|
return JArray.Parse(outputString.ToString());
|
||||||
|
}
|
||||||
|
|
||||||
|
return JObject.Parse(outputString.ToString());
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -36,5 +36,5 @@ public class WireMockOpenApiParserExampleValues : IWireMockOpenApiParserExampleV
|
|||||||
public virtual string String { get; set; } = "example-string";
|
public virtual string String { get; set; } = "example-string";
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public virtual OpenApiSchema? Schema { get; set; } = new OpenApiSchema();
|
public virtual OpenApiSchema? Schema { get; set; } = new();
|
||||||
}
|
}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
namespace WireMock.Net.OpenApiParser.Types;
|
namespace WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The example value to use
|
/// The (example) value pattern to use.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public enum ExampleValueType
|
public enum ExampleValueType
|
||||||
{
|
{
|
||||||
@@ -12,6 +12,11 @@ public enum ExampleValueType
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Value,
|
Value,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Build a Regex based on the SchemaType.
|
||||||
|
/// </summary>
|
||||||
|
Regex,
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Just use a Wildcard (*) character.
|
/// Just use a Wildcard (*) character.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
|||||||
@@ -1,5 +1,4 @@
|
|||||||
using System;
|
using System.Linq;
|
||||||
using System.Collections.Generic;
|
|
||||||
using Microsoft.OpenApi.Any;
|
using Microsoft.OpenApi.Any;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
@@ -9,118 +8,110 @@ using WireMock.Net.OpenApiParser.Types;
|
|||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser.Utils;
|
namespace WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
internal class ExampleValueGenerator
|
internal class ExampleValueGenerator : IExampleValueGenerator
|
||||||
{
|
{
|
||||||
private readonly WireMockOpenApiParserSettings _settings;
|
private readonly IWireMockOpenApiParserExampleValues _exampleValues;
|
||||||
|
|
||||||
public ExampleValueGenerator(WireMockOpenApiParserSettings settings)
|
public ExampleValueGenerator(WireMockOpenApiParserSettings settings)
|
||||||
{
|
{
|
||||||
_settings = Guard.NotNull(settings);
|
Guard.NotNull(settings);
|
||||||
|
|
||||||
// Check if user provided an own implementation
|
// Check if user provided an own implementation
|
||||||
if (settings.ExampleValues is null)
|
if (settings.ExampleValues is null)
|
||||||
{
|
{
|
||||||
if (_settings.DynamicExamples)
|
if (settings.DynamicExamples)
|
||||||
{
|
{
|
||||||
_settings.ExampleValues = new WireMockOpenApiParserDynamicExampleValues();
|
_exampleValues = new WireMockOpenApiParserDynamicExampleValues();
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_settings.ExampleValues = new WireMockOpenApiParserExampleValues();
|
_exampleValues = new WireMockOpenApiParserExampleValues();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_exampleValues = settings.ExampleValues;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public object GetExampleValue(OpenApiSchema? schema)
|
public object GetExampleValue(OpenApiSchema? schema)
|
||||||
{
|
{
|
||||||
var schemaExample = schema?.Example;
|
var schemaExample = schema?.Example;
|
||||||
var schemaEnum = GetRandomEnumValue(schema?.Enum);
|
var schemaEnum = schema?.Enum?.FirstOrDefault();
|
||||||
|
|
||||||
_settings.ExampleValues.Schema = schema;
|
_exampleValues.Schema = schema;
|
||||||
|
|
||||||
switch (schema?.GetSchemaType())
|
switch (schema?.GetSchemaType())
|
||||||
{
|
{
|
||||||
case SchemaType.Boolean:
|
case SchemaType.Boolean:
|
||||||
var exampleBoolean = schemaExample as OpenApiBoolean;
|
var exampleBoolean = schemaExample as OpenApiBoolean;
|
||||||
return exampleBoolean is null ? _settings.ExampleValues.Boolean : exampleBoolean.Value;
|
return exampleBoolean?.Value ?? _exampleValues.Boolean;
|
||||||
|
|
||||||
case SchemaType.Integer:
|
case SchemaType.Integer:
|
||||||
switch (schema?.GetSchemaFormat())
|
switch (schema?.GetSchemaFormat())
|
||||||
{
|
{
|
||||||
case SchemaFormat.Int64:
|
case SchemaFormat.Int64:
|
||||||
var exampleLong = (OpenApiLong)schemaExample;
|
var exampleLong = schemaExample as OpenApiLong;
|
||||||
var enumLong = (OpenApiLong)schemaEnum;
|
var enumLong = schemaEnum as OpenApiLong;
|
||||||
var valueLongEnumOrExample = enumLong is null ? exampleLong?.Value : enumLong?.Value;
|
var valueLongEnumOrExample = enumLong?.Value ?? exampleLong?.Value;
|
||||||
return valueLongEnumOrExample ?? _settings.ExampleValues.Integer;
|
return valueLongEnumOrExample ?? _exampleValues.Integer;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var exampleInteger = (OpenApiInteger)schemaExample;
|
var exampleInteger = schemaExample as OpenApiInteger;
|
||||||
var enumInteger = (OpenApiInteger)schemaEnum;
|
var enumInteger = schemaEnum as OpenApiInteger;
|
||||||
var valueIntegerEnumOrExample = enumInteger is null ? exampleInteger?.Value : enumInteger?.Value;
|
var valueIntegerEnumOrExample = enumInteger?.Value ?? exampleInteger?.Value;
|
||||||
return valueIntegerEnumOrExample ?? _settings.ExampleValues.Integer;
|
return valueIntegerEnumOrExample ?? _exampleValues.Integer;
|
||||||
}
|
}
|
||||||
|
|
||||||
case SchemaType.Number:
|
case SchemaType.Number:
|
||||||
switch (schema?.GetSchemaFormat())
|
switch (schema?.GetSchemaFormat())
|
||||||
{
|
{
|
||||||
case SchemaFormat.Float:
|
case SchemaFormat.Float:
|
||||||
var exampleFloat = (OpenApiFloat)schemaExample;
|
var exampleFloat = schemaExample as OpenApiFloat;
|
||||||
var enumFloat = (OpenApiFloat)schemaEnum;
|
var enumFloat = schemaEnum as OpenApiFloat;
|
||||||
var valueFloatEnumOrExample = enumFloat is null ? exampleFloat?.Value : enumFloat?.Value;
|
var valueFloatEnumOrExample = enumFloat?.Value ?? exampleFloat?.Value;
|
||||||
return valueFloatEnumOrExample ?? _settings.ExampleValues.Float;
|
return valueFloatEnumOrExample ?? _exampleValues.Float;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var exampleDouble = (OpenApiDouble)schemaExample;
|
var exampleDouble = schemaExample as OpenApiDouble;
|
||||||
var enumDouble = (OpenApiDouble)schemaEnum;
|
var enumDouble = schemaEnum as OpenApiDouble;
|
||||||
var valueDoubleEnumOrExample = enumDouble is null ? exampleDouble?.Value : enumDouble?.Value;
|
var valueDoubleEnumOrExample = enumDouble?.Value ?? exampleDouble?.Value;
|
||||||
return valueDoubleEnumOrExample ?? _settings.ExampleValues.Double;
|
return valueDoubleEnumOrExample ?? _exampleValues.Double;
|
||||||
}
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
switch (schema?.GetSchemaFormat())
|
switch (schema?.GetSchemaFormat())
|
||||||
{
|
{
|
||||||
case SchemaFormat.Date:
|
case SchemaFormat.Date:
|
||||||
var exampleDate = (OpenApiDate)schemaExample;
|
var exampleDate = schemaExample as OpenApiDate;
|
||||||
var enumDate = (OpenApiDate)schemaEnum;
|
var enumDate = schemaEnum as OpenApiDate;
|
||||||
var valueDateEnumOrExample = enumDate is null ? exampleDate?.Value : enumDate?.Value;
|
var valueDateEnumOrExample = enumDate?.Value ?? exampleDate?.Value;
|
||||||
return DateTimeUtils.ToRfc3339Date(valueDateEnumOrExample ?? _settings.ExampleValues.Date());
|
return DateTimeUtils.ToRfc3339Date(valueDateEnumOrExample ?? _exampleValues.Date());
|
||||||
|
|
||||||
case SchemaFormat.DateTime:
|
case SchemaFormat.DateTime:
|
||||||
var exampleDateTime = (OpenApiDateTime)schemaExample;
|
var exampleDateTime = schemaExample as OpenApiDateTime;
|
||||||
var enumDateTime = (OpenApiDateTime)schemaEnum;
|
var enumDateTime = schemaEnum as OpenApiDateTime;
|
||||||
var valueDateTimeEnumOrExample = enumDateTime is null ? exampleDateTime?.Value : enumDateTime?.Value;
|
var valueDateTimeEnumOrExample = enumDateTime?.Value ?? exampleDateTime?.Value;
|
||||||
return DateTimeUtils.ToRfc3339DateTime(valueDateTimeEnumOrExample?.DateTime ?? _settings.ExampleValues.DateTime());
|
return DateTimeUtils.ToRfc3339DateTime(valueDateTimeEnumOrExample?.DateTime ?? _exampleValues.DateTime());
|
||||||
|
|
||||||
case SchemaFormat.Byte:
|
case SchemaFormat.Byte:
|
||||||
var exampleByte = (OpenApiByte)schemaExample;
|
var exampleByte = schemaExample as OpenApiByte;
|
||||||
var enumByte = (OpenApiByte)schemaEnum;
|
var enumByte = schemaEnum as OpenApiByte;
|
||||||
var valueByteEnumOrExample = enumByte is null ? exampleByte?.Value : enumByte?.Value;
|
var valueByteEnumOrExample = enumByte?.Value ?? exampleByte?.Value;
|
||||||
return valueByteEnumOrExample ?? _settings.ExampleValues.Bytes;
|
return valueByteEnumOrExample ?? _exampleValues.Bytes;
|
||||||
|
|
||||||
case SchemaFormat.Binary:
|
case SchemaFormat.Binary:
|
||||||
var exampleBinary = (OpenApiBinary)schemaExample;
|
var exampleBinary = schemaExample as OpenApiBinary;
|
||||||
var enumBinary = (OpenApiBinary)schemaEnum;
|
var enumBinary = schemaEnum as OpenApiBinary;
|
||||||
var valueBinaryEnumOrExample = enumBinary is null ? exampleBinary?.Value : enumBinary?.Value;
|
var valueBinaryEnumOrExample = enumBinary?.Value ?? exampleBinary?.Value;
|
||||||
return valueBinaryEnumOrExample ?? _settings.ExampleValues.Object;
|
return valueBinaryEnumOrExample ?? _exampleValues.Object;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
var exampleString = (OpenApiString)schemaExample;
|
var exampleString = schemaExample as OpenApiString;
|
||||||
var enumString = (OpenApiString)schemaEnum;
|
var enumString = schemaEnum as OpenApiString;
|
||||||
var valueStringEnumOrExample = enumString is null ? exampleString?.Value : enumString?.Value;
|
var valueStringEnumOrExample = enumString?.Value ?? exampleString?.Value;
|
||||||
return valueStringEnumOrExample ?? _settings.ExampleValues.String;
|
return valueStringEnumOrExample ?? _exampleValues.String;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private static IOpenApiAny? GetRandomEnumValue(IList<IOpenApiAny>? schemaEnum)
|
|
||||||
{
|
|
||||||
if (schemaEnum?.Count > 0)
|
|
||||||
{
|
|
||||||
int maxValue = schemaEnum.Count - 1;
|
|
||||||
int randomEnum = new Random().Next(0, maxValue);
|
|
||||||
return schemaEnum[randomEnum];
|
|
||||||
}
|
|
||||||
|
|
||||||
return null;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,8 @@
|
|||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
|
||||||
|
namespace WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
|
internal interface IExampleValueGenerator
|
||||||
|
{
|
||||||
|
object GetExampleValue(OpenApiSchema? schema);
|
||||||
|
}
|
||||||
@@ -0,0 +1,40 @@
|
|||||||
|
using Microsoft.OpenApi.Models;
|
||||||
|
using Stef.Validation;
|
||||||
|
using WireMock.Net.OpenApiParser.Extensions;
|
||||||
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
|
namespace WireMock.Net.OpenApiParser.Utils;
|
||||||
|
|
||||||
|
internal class RegexExampleValueGenerator : IExampleValueGenerator
|
||||||
|
{
|
||||||
|
public RegexExampleValueGenerator(WireMockOpenApiParserSettings settings)
|
||||||
|
{
|
||||||
|
Guard.NotNull(settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
public object GetExampleValue(OpenApiSchema? schema)
|
||||||
|
{
|
||||||
|
switch (schema?.GetSchemaType())
|
||||||
|
{
|
||||||
|
case SchemaType.Boolean:
|
||||||
|
return @"(true|false)";
|
||||||
|
|
||||||
|
case SchemaType.Integer:
|
||||||
|
return @"-?\d+";
|
||||||
|
|
||||||
|
case SchemaType.Number:
|
||||||
|
return @"[-+]?[0-9]*\.?[0-9]+([eE][-+]?[0-9]+)?";
|
||||||
|
|
||||||
|
default:
|
||||||
|
return schema?.GetSchemaFormat() switch
|
||||||
|
{
|
||||||
|
SchemaFormat.Date => @"(\d{4})-([01]\d)-([0-3]\d)",
|
||||||
|
SchemaFormat.DateTime => @"(\d{4})-([01]\d)-([0-3]\d)T([0-2]\d):([0-5]\d):([0-5]\d)(\.\d+)?(Z|[+-][0-2]\d:[0-5]\d)",
|
||||||
|
SchemaFormat.Byte => @"(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)",
|
||||||
|
SchemaFormat.Binary => @"[a-zA-Z0-9\+/]*={0,3}",
|
||||||
|
_ => ".*"
|
||||||
|
};
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -4,7 +4,7 @@
|
|||||||
<Description>An OpenApi (swagger) parser to generate MappingModel or mapping.json file.</Description>
|
<Description>An OpenApi (swagger) parser to generate MappingModel or mapping.json file.</Description>
|
||||||
<TargetFrameworks>net46;netstandard2.0;netstandard2.1</TargetFrameworks>
|
<TargetFrameworks>net46;netstandard2.0;netstandard2.1</TargetFrameworks>
|
||||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||||
<PackageTags>wiremock;openapi;OAS;converter;parser;openapiparser</PackageTags>
|
<PackageTags>wiremock;openapi;OAS;raml;converter;parser;openapiparser</PackageTags>
|
||||||
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5AADAD}</ProjectGuid>
|
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5AADAD}</ProjectGuid>
|
||||||
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
<PublishRepositoryUrl>true</PublishRepositoryUrl>
|
||||||
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.IO;
|
using System.IO;
|
||||||
|
using System.Text;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using Microsoft.OpenApi.Models;
|
using Microsoft.OpenApi.Models;
|
||||||
using Microsoft.OpenApi.Readers;
|
using Microsoft.OpenApi.Readers;
|
||||||
@@ -8,6 +9,7 @@ using RamlToOpenApiConverter;
|
|||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Net.OpenApiParser.Mappers;
|
using WireMock.Net.OpenApiParser.Mappers;
|
||||||
using WireMock.Net.OpenApiParser.Settings;
|
using WireMock.Net.OpenApiParser.Settings;
|
||||||
|
using WireMock.Net.OpenApiParser.Types;
|
||||||
|
|
||||||
namespace WireMock.Net.OpenApiParser;
|
namespace WireMock.Net.OpenApiParser;
|
||||||
|
|
||||||
@@ -16,18 +18,25 @@ namespace WireMock.Net.OpenApiParser;
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public class WireMockOpenApiParser : IWireMockOpenApiParser
|
public class WireMockOpenApiParser : IWireMockOpenApiParser
|
||||||
{
|
{
|
||||||
private readonly OpenApiStreamReader _reader = new OpenApiStreamReader();
|
private readonly WireMockOpenApiParserSettings _wireMockOpenApiParserSettings = new WireMockOpenApiParserSettings
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromFile(string, out OpenApiDiagnostic)" />
|
|
||||||
[PublicAPI]
|
|
||||||
public IEnumerable<MappingModel> FromFile(string path, out OpenApiDiagnostic diagnostic)
|
|
||||||
{
|
{
|
||||||
return FromFile(path, new WireMockOpenApiParserSettings(), out diagnostic);
|
HeaderPatternToUse = ExampleValueType.Regex,
|
||||||
|
QueryParameterPatternToUse = ExampleValueType.Regex,
|
||||||
|
PathPatternToUse = ExampleValueType.Regex
|
||||||
|
};
|
||||||
|
|
||||||
|
private readonly OpenApiStreamReader _reader = new();
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[PublicAPI]
|
||||||
|
public IReadOnlyList<MappingModel> FromFile(string path, out OpenApiDiagnostic diagnostic)
|
||||||
|
{
|
||||||
|
return FromFile(path, _wireMockOpenApiParserSettings, out diagnostic);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromFile(string, WireMockOpenApiParserSettings, out OpenApiDiagnostic)" />
|
/// <inheritdoc />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IEnumerable<MappingModel> FromFile(string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
public IReadOnlyList<MappingModel> FromFile(string path, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
OpenApiDocument document;
|
OpenApiDocument document;
|
||||||
if (Path.GetExtension(path).EndsWith("raml", StringComparison.OrdinalIgnoreCase))
|
if (Path.GetExtension(path).EndsWith("raml", StringComparison.OrdinalIgnoreCase))
|
||||||
@@ -44,24 +53,38 @@ public class WireMockOpenApiParser : IWireMockOpenApiParser
|
|||||||
return FromDocument(document, settings);
|
return FromDocument(document, settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromStream(Stream, out OpenApiDiagnostic)" />
|
/// <inheritdoc />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IEnumerable<MappingModel> FromStream(Stream stream, out OpenApiDiagnostic diagnostic)
|
public IReadOnlyList<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings? settings = null)
|
||||||
|
{
|
||||||
|
return new OpenApiPathsMapper(settings ?? _wireMockOpenApiParserSettings).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[PublicAPI]
|
||||||
|
public IReadOnlyList<MappingModel> FromStream(Stream stream, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return FromDocument(_reader.Read(stream, out diagnostic));
|
return FromDocument(_reader.Read(stream, out diagnostic));
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromStream(Stream, WireMockOpenApiParserSettings, out OpenApiDiagnostic)" />
|
/// <inheritdoc />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IEnumerable<MappingModel> FromStream(Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
public IReadOnlyList<MappingModel> FromStream(Stream stream, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return FromDocument(_reader.Read(stream, out diagnostic), settings);
|
return FromDocument(_reader.Read(stream, out diagnostic), settings);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IWireMockOpenApiParser.FromDocument(OpenApiDocument, WireMockOpenApiParserSettings)" />
|
/// <inheritdoc />
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IEnumerable<MappingModel> FromDocument(OpenApiDocument openApiDocument, WireMockOpenApiParserSettings? settings = null)
|
public IReadOnlyList<MappingModel> FromText(string text, out OpenApiDiagnostic diagnostic)
|
||||||
{
|
{
|
||||||
return new OpenApiPathsMapper(settings).ToMappingModels(openApiDocument.Paths, openApiDocument.Servers);
|
return FromStream(new MemoryStream(Encoding.UTF8.GetBytes(text)), out diagnostic);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
[PublicAPI]
|
||||||
|
public IReadOnlyList<MappingModel> FromText(string text, WireMockOpenApiParserSettings settings, out OpenApiDiagnostic diagnostic)
|
||||||
|
{
|
||||||
|
return FromStream(new MemoryStream(Encoding.UTF8.GetBytes(text)), settings, out diagnostic);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -0,0 +1,58 @@
|
|||||||
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Threading;
|
||||||
|
using System.Threading.Tasks;
|
||||||
|
using Stef.Validation;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
namespace WireMock.Client.Builders;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AdminApiMappingBuilder
|
||||||
|
/// </summary>
|
||||||
|
public class AdminApiMappingBuilder
|
||||||
|
{
|
||||||
|
private readonly List<Action<MappingModelBuilder>> _mappingModelBuilderActions = new();
|
||||||
|
|
||||||
|
private readonly IWireMockAdminApi _api;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// AdminApiMappingBuilder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">The <see cref="IWireMockAdminApi"/>.</param>
|
||||||
|
public AdminApiMappingBuilder(IWireMockAdminApi api)
|
||||||
|
{
|
||||||
|
_api = Guard.NotNull(api);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The Given
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="mappingModelBuilderAction">The action.</param>
|
||||||
|
public void Given(Action<MappingModelBuilder> mappingModelBuilderAction)
|
||||||
|
{
|
||||||
|
_mappingModelBuilderActions.Add(Guard.NotNull(mappingModelBuilderAction));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Build the mappings and post these using the <see cref="IWireMockAdminApi"/> to the WireMock.Net server.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="cancellationToken">The optional CancellationToken.</param>
|
||||||
|
/// <returns><see cref="StatusModel"/></returns>
|
||||||
|
public Task<StatusModel> BuildAndPostAsync(CancellationToken cancellationToken = default)
|
||||||
|
{
|
||||||
|
var modelMappings = new List<MappingModel>();
|
||||||
|
|
||||||
|
foreach (var mappingModelBuilderAction in _mappingModelBuilderActions)
|
||||||
|
{
|
||||||
|
cancellationToken.ThrowIfCancellationRequested();
|
||||||
|
|
||||||
|
var mappingModelBuilder = new MappingModelBuilder();
|
||||||
|
mappingModelBuilderAction(mappingModelBuilder);
|
||||||
|
|
||||||
|
modelMappings.Add(mappingModelBuilder.Build());
|
||||||
|
}
|
||||||
|
|
||||||
|
return _api.PostMappingsAsync(modelMappings, cancellationToken);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,46 @@
|
|||||||
|
using System.Text;
|
||||||
|
using JsonConverter.Abstractions;
|
||||||
|
using JsonConverter.Newtonsoft.Json;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
|
||||||
|
namespace WireMock.Client.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// ResponseModelBuilder
|
||||||
|
/// </summary>
|
||||||
|
public static class ResponseModelBuilderExtensions
|
||||||
|
{
|
||||||
|
private static readonly Encoding Utf8NoBom = new UTF8Encoding(false);
|
||||||
|
private static readonly IJsonConverter JsonConverter = new NewtonsoftJsonConverter();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WithBodyAsJson
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The ResponseModelBuilder.</param>
|
||||||
|
/// <param name="body">The body.</param>
|
||||||
|
/// <param name="encoding">The body encoding.</param>
|
||||||
|
/// <param name="indented">Define whether child objects to be indented.</param>
|
||||||
|
public static ResponseModelBuilder WithBodyAsJson(this ResponseModelBuilder builder, object body, Encoding? encoding = null, bool? indented = null)
|
||||||
|
{
|
||||||
|
return builder.WithBodyAsBytes(() =>
|
||||||
|
{
|
||||||
|
var options = new JsonConverterOptions
|
||||||
|
{
|
||||||
|
WriteIndented = indented == true
|
||||||
|
};
|
||||||
|
var jsonBody = JsonConverter.Serialize(body, options);
|
||||||
|
return (encoding ?? Utf8NoBom).GetBytes(jsonBody);
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WithBodyAsJson
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="builder">The ResponseModelBuilder.</param>
|
||||||
|
/// <param name="body">The body.</param>
|
||||||
|
/// <param name="indented">Define whether child objects to be indented.</param>
|
||||||
|
public static ResponseModelBuilder WithBodyAsJson(this ResponseModelBuilder builder, object body, bool indented)
|
||||||
|
{
|
||||||
|
return builder.WithBodyAsJson(body, null, indented);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,19 @@
|
|||||||
|
using WireMock.Client.Builders;
|
||||||
|
|
||||||
|
namespace WireMock.Client.Extensions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Some extensions for <see cref="IWireMockAdminApi"/>.
|
||||||
|
/// </summary>
|
||||||
|
public static class WireMockAdminApiExtensions
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Get a new <see cref="AdminApiMappingBuilder"/> for the <see cref="IWireMockAdminApi"/>.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="api">See <see cref="IWireMockAdminApi"/>.</param>
|
||||||
|
/// <returns></returns>
|
||||||
|
public static AdminApiMappingBuilder GetMappingBuilder(this IWireMockAdminApi api)
|
||||||
|
{
|
||||||
|
return new AdminApiMappingBuilder(api);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,233 +1,299 @@
|
|||||||
using RestEase;
|
|
||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
|
using System.Threading;
|
||||||
using System.Threading.Tasks;
|
using System.Threading.Tasks;
|
||||||
|
using RestEase;
|
||||||
using WireMock.Admin.Mappings;
|
using WireMock.Admin.Mappings;
|
||||||
using WireMock.Admin.Requests;
|
using WireMock.Admin.Requests;
|
||||||
using WireMock.Admin.Scenarios;
|
using WireMock.Admin.Scenarios;
|
||||||
using WireMock.Admin.Settings;
|
using WireMock.Admin.Settings;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
namespace WireMock.Client
|
namespace WireMock.Client;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The RestEase interface which defines all admin commands.
|
||||||
|
/// </summary>
|
||||||
|
[BasePath("__admin")]
|
||||||
|
public interface IWireMockAdminApi
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The RestEase interface which defines all admin commands.
|
/// Authentication header
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[BasePath("__admin")]
|
[Header("Authorization")]
|
||||||
public interface IWireMockAdminApi
|
AuthenticationHeaderValue Authorization { get; set; }
|
||||||
{
|
|
||||||
/// <summary>
|
|
||||||
/// Authentication header
|
|
||||||
/// </summary>
|
|
||||||
[Header("Authorization")]
|
|
||||||
AuthenticationHeaderValue Authorization { get; set; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the settings.
|
/// Get the settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>SettingsModel</returns>
|
/// <returns>SettingsModel</returns>
|
||||||
[Get("settings")]
|
[Get("settings")]
|
||||||
Task<SettingsModel> GetSettingsAsync();
|
Task<SettingsModel> GetSettingsAsync();
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the settings.
|
/// Update the settings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settings">SettingsModel</param>
|
/// <param name="settings">SettingsModel</param>
|
||||||
[Put("settings")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Header("Content-Type", "application/json")]
|
[Put("settings")]
|
||||||
Task<StatusModel> PutSettingsAsync([Body] SettingsModel settings);
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> PutSettingsAsync([Body] SettingsModel settings, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update the settings
|
/// Update the settings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="settings">SettingsModel</param>
|
/// <param name="settings">SettingsModel</param>
|
||||||
[Post("settings")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Header("Content-Type", "application/json")]
|
[Post("settings")]
|
||||||
Task<StatusModel> PostSettingsAsync([Body] SettingsModel settings);
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> PostSettingsAsync([Body] SettingsModel settings, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the mappings.
|
/// Get the mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>MappingModels</returns>
|
/// <returns>MappingModels</returns>
|
||||||
[Get("mappings")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<IList<MappingModel>> GetMappingsAsync();
|
[Get("mappings")]
|
||||||
|
Task<IList<MappingModel>> GetMappingsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add a new mapping.
|
/// Get the C# code from all mappings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mapping">MappingModel</param>
|
/// <returns>C# code</returns>
|
||||||
[Post("mappings")]
|
/// <param name="mappingConverterType">The <see cref="MappingConverterType"/>, default is Server.</param>
|
||||||
[Header("Content-Type", "application/json")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<StatusModel> PostMappingAsync([Body] MappingModel mapping);
|
[Get("mappings/code")]
|
||||||
|
Task<string> GetMappingsCodeAsync([Query] MappingConverterType mappingConverterType = MappingConverterType.Server, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Add new mappings.
|
/// Add a new mapping.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mappings">MappingModels</param>
|
/// <param name="mapping">MappingModel</param>
|
||||||
[Post("mappings")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Header("Content-Type", "application/json")]
|
[Post("mappings")]
|
||||||
Task<StatusModel> PostMappingsAsync([Body] IList<MappingModel> mappings);
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> PostMappingAsync([Body] MappingModel mapping, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete all mappings.
|
/// Add new mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Delete("mappings")]
|
/// <param name="mappings">MappingModels</param>
|
||||||
Task<StatusModel> DeleteMappingsAsync();
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("mappings")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> PostMappingsAsync([Body] IList<MappingModel> mappings, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete mappings according to GUIDs
|
/// Delete all mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="mappings">MappingModels</param>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Delete("mappings")]
|
[Delete("mappings")]
|
||||||
[Header("Content-Type", "application/json")]
|
Task<StatusModel> DeleteMappingsAsync(CancellationToken cancellationToken = default);
|
||||||
Task<StatusModel> DeleteMappingsAsync([Body] IList<MappingModel> mappings);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) all mappings.
|
/// Delete mappings according to GUIDs
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="reloadStaticMappings">A value indicating whether to reload the static mappings after the reset.</param>
|
/// <param name="mappings">MappingModels</param>
|
||||||
[Post("mappings/reset")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false);
|
[Delete("mappings")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> DeleteMappingsAsync([Body] IList<MappingModel> mappings, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a mapping based on the guid
|
/// Delete (reset) all mappings.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The Guid</param>
|
/// <param name="reloadStaticMappings">A value indicating whether to reload the static mappings after the reset.</param>
|
||||||
/// <returns>MappingModel</returns>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Get("mappings/{guid}")]
|
[Post("mappings/reset")]
|
||||||
Task<MappingModel> GetMappingAsync([Path] Guid guid);
|
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update a mapping based on the guid
|
/// Get a mapping based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The Guid</param>
|
/// <param name="guid">The Guid</param>
|
||||||
/// <param name="mapping">MappingModel</param>
|
/// <returns>MappingModel</returns>
|
||||||
[Put("mappings/{guid}")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Header("Content-Type", "application/json")]
|
[Get("mappings/{guid}")]
|
||||||
Task<StatusModel> PutMappingAsync([Path] Guid guid, [Body] MappingModel mapping);
|
Task<MappingModel> GetMappingAsync([Path] Guid guid, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a mapping based on the guid
|
/// Get the C# code from a mapping based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The Guid</param>
|
/// <param name="guid">The Guid</param>
|
||||||
[Delete("mappings/{guid}")]
|
/// <param name="mappingConverterType">The optional mappingConverterType (can be Server or Builder)</param>
|
||||||
Task<StatusModel> DeleteMappingAsync([Path] Guid guid);
|
/// <returns>C# code</returns>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Get("mappings/code/{guid}")]
|
||||||
|
Task<string> GetMappingCodeAsync([Path] Guid guid, [Query] MappingConverterType mappingConverterType = MappingConverterType.Server, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Save the mappings
|
/// Update a mapping based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Post("mappings/save")]
|
/// <param name="guid">The Guid</param>
|
||||||
Task<StatusModel> SaveMappingAsync();
|
/// <param name="mapping">MappingModel</param>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Put("mappings/{guid}")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<StatusModel> PutMappingAsync([Path] Guid guid, [Body] MappingModel mapping, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the requests.
|
/// Delete a mapping based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <returns>LogRequestModels</returns>
|
/// <param name="guid">The Guid</param>
|
||||||
[Get("requests")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<IList<LogEntryModel>> GetRequestsAsync();
|
[Delete("mappings/{guid}")]
|
||||||
|
Task<StatusModel> DeleteMappingAsync([Path] Guid guid, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete all requests.
|
/// Save the mappings
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Delete("requests")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<StatusModel> DeleteRequestsAsync();
|
[Post("mappings/save")]
|
||||||
|
Task<StatusModel> SaveMappingAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) all requests.
|
/// Get the requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Post("requests/reset")]
|
/// <returns>LogRequestModels</returns>
|
||||||
Task<StatusModel> ResetRequestsAsync();
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Get("requests")]
|
||||||
|
Task<IList<LogEntryModel>> GetRequestsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get a request based on the guid
|
/// Delete all requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The Guid</param>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
/// <returns>MappingModel</returns>
|
[Delete("requests")]
|
||||||
[Get("requests/{guid}")]
|
Task<StatusModel> DeleteRequestsAsync(CancellationToken cancellationToken = default);
|
||||||
Task<LogEntryModel> GetRequestAsync([Path] Guid guid);
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete a request based on the guid
|
/// Delete (reset) all requests.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The Guid</param>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Delete("requests/{guid}")]
|
[Post("requests/reset")]
|
||||||
Task<StatusModel> DeleteRequestAsync([Path] Guid guid);
|
Task<StatusModel> ResetRequestsAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Find a request based on the criteria
|
/// Get a request based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="model">The RequestModel</param>
|
/// <param name="guid">The Guid</param>
|
||||||
[Post("requests/find")]
|
/// <returns>MappingModel</returns>
|
||||||
[Header("Content-Type", "application/json")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<IList<LogEntryModel>> FindRequestsAsync([Body] RequestModel model);
|
[Get("requests/{guid}")]
|
||||||
|
Task<LogEntryModel> GetRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get all scenarios
|
/// Delete a request based on the guid
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Get("scenarios")]
|
/// <param name="guid">The Guid</param>
|
||||||
Task<IList<ScenarioStateModel>> GetScenariosAsync();
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Delete("requests/{guid}")]
|
||||||
|
Task<StatusModel> DeleteRequestAsync([Path] Guid guid, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) all scenarios
|
/// Find a request based on the criteria
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Delete("scenarios")]
|
/// <param name="model">The RequestModel</param>
|
||||||
Task<StatusModel> DeleteScenariosAsync();
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("requests/find")]
|
||||||
|
[Header("Content-Type", "application/json")]
|
||||||
|
Task<IList<LogEntryModel>> FindRequestsAsync([Body] RequestModel model, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) all scenarios
|
/// Get all scenarios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Post("scenarios")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task<StatusModel> ResetScenariosAsync();
|
[Get("scenarios")]
|
||||||
|
Task<IList<ScenarioStateModel>> GetScenariosAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) a specific scenario
|
/// Delete (reset) all scenarios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Delete("scenarios/{name}")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[AllowAnyStatusCode]
|
[Delete("scenarios")]
|
||||||
Task<StatusModel> DeleteScenarioAsync([Path] string name);
|
Task<StatusModel> DeleteScenariosAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete (reset) all scenarios
|
/// Delete (reset) all scenarios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
[Post("scenarios/{name}/reset")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[AllowAnyStatusCode]
|
[Post("scenarios")]
|
||||||
Task<StatusModel> ResetScenarioAsync([Path] string name);
|
Task<StatusModel> ResetScenariosAsync(CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Create a new File
|
/// Delete (reset) a specific scenario
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename</param>
|
/// <param name="name">Scenario name.</param>
|
||||||
/// <param name="body">The body</param>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Post("files/{filename}")]
|
[Delete("scenarios/{name}")]
|
||||||
Task<StatusModel> PostFileAsync([Path] string filename, [Body] string body);
|
[AllowAnyStatusCode]
|
||||||
|
Task<StatusModel> DeleteScenarioAsync([Path] string name, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Update an existing File
|
/// Delete (reset) all scenarios
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename</param>
|
/// <param name="name">Scenario name.</param>
|
||||||
/// <param name="body">The body</param>
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
[Put("files/{filename}")]
|
[Post("scenarios/{name}/reset")]
|
||||||
Task<StatusModel> PutFileAsync([Path] string filename, [Body] string body);
|
[AllowAnyStatusCode]
|
||||||
|
Task<StatusModel> ResetScenarioAsync([Path] string name, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Get the content of an existing File
|
/// Create a new File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename</param>
|
/// <param name="filename">The filename</param>
|
||||||
[Get("files/{filename}")]
|
/// <param name="body">The body</param>
|
||||||
Task<string> GetFileAsync([Path] string filename);
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("files/{filename}")]
|
||||||
|
Task<StatusModel> PostFileAsync([Path] string filename, [Body] string body, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Delete an existing File
|
/// Update an existing File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename</param>
|
/// <param name="filename">The filename</param>
|
||||||
[Delete("files/{filename}")]
|
/// <param name="body">The body</param>
|
||||||
Task<StatusModel> DeleteFileAsync([Path] string filename);
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Put("files/{filename}")]
|
||||||
|
Task<StatusModel> PutFileAsync([Path] string filename, [Body] string body, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Check if a file exists
|
/// Get the content of an existing File
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="filename">The filename</param>
|
/// <param name="filename">The filename</param>
|
||||||
[Head("files/{filename}")]
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
Task FileExistsAsync([Path] string filename);
|
[Get("files/{filename}")]
|
||||||
}
|
Task<string> GetFileAsync([Path] string filename, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Delete an existing File
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">The filename</param>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Delete("files/{filename}")]
|
||||||
|
Task<StatusModel> DeleteFileAsync([Path] string filename, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Check if a file exists
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="filename">The filename</param>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Head("files/{filename}")]
|
||||||
|
Task FileExistsAsync([Path] string filename, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an OpenApi / RAML document to mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The OpenApi or RAML document as text.</param>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("openapi/convert")]
|
||||||
|
Task<IReadOnlyList<MappingModel>> OpenApiConvertAsync([Body] string text, CancellationToken cancellationToken = default);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert an OpenApi / RAML document to mappings and save these.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="text">The OpenApi or RAML document as text.</param>
|
||||||
|
/// <param name="cancellationToken">The optional cancellationToken.</param>
|
||||||
|
[Post("openapi/save")]
|
||||||
|
Task<StatusModel> OpenApiSaveAsync([Body] string text, CancellationToken cancellationToken = default);
|
||||||
}
|
}
|
||||||
@@ -30,8 +30,10 @@
|
|||||||
</PropertyGroup>
|
</PropertyGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
<PackageReference Include="JsonConverter.Newtonsoft.Json" Version="0.3.0" />
|
||||||
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.1.1" PrivateAssets="All" />
|
||||||
<PackageReference Include="RestEase" Version="1.5.7" />
|
<PackageReference Include="RestEase" Version="1.5.7" />
|
||||||
|
<PackageReference Include="Stef.Validation" Version="0.1.1" />
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
|
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
|
|||||||
17
src/WireMock.Net/.filenesting.json
Normal file
17
src/WireMock.Net/.filenesting.json
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
{
|
||||||
|
"help": "https://go.microsoft.com/fwlink/?linkid=866610",
|
||||||
|
"root": true,
|
||||||
|
|
||||||
|
"dependentFileProviders": {
|
||||||
|
"add": {
|
||||||
|
"addedExtension": {},
|
||||||
|
"pathSegment": {
|
||||||
|
"add": {
|
||||||
|
".*": [
|
||||||
|
".cs"
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
15
src/WireMock.Net/Compatibility/StringExtensions.cs
Normal file
15
src/WireMock.Net/Compatibility/StringExtensions.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
#if NET451 || NET452 || NET46 || NET451 || NET461 || NETSTANDARD1_3 || NETSTANDARD2_0
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
|
|
||||||
|
// ReSharper disable once CheckNamespace
|
||||||
|
namespace System;
|
||||||
|
|
||||||
|
internal static class StringExtensions
|
||||||
|
{
|
||||||
|
public static string Replace(this string text, string oldValue, string newValue, StringComparison stringComparison)
|
||||||
|
{
|
||||||
|
var options = stringComparison == StringComparison.OrdinalIgnoreCase ? RegexOptions.IgnoreCase : RegexOptions.None;
|
||||||
|
return Regex.Replace(text, oldValue, newValue, options);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
#endif
|
||||||
@@ -7,4 +7,5 @@ internal static class WireMockConstants
|
|||||||
public const int ProxyPriority = -2_000_000;
|
public const int ProxyPriority = -2_000_000;
|
||||||
|
|
||||||
public const string ContentTypeJson = "application/json";
|
public const string ContentTypeJson = "application/json";
|
||||||
|
public const string ContentTypeTextPlain = "text/plain";
|
||||||
}
|
}
|
||||||
@@ -1,35 +1,34 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WireMock.Exceptions
|
namespace WireMock.Exceptions;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// WireMockException
|
||||||
|
/// </summary>
|
||||||
|
/// <seealso cref="Exception" />
|
||||||
|
public class WireMockException : Exception
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// WireMockException
|
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <seealso cref="Exception" />
|
public WireMockException()
|
||||||
public class WireMockException : Exception
|
|
||||||
{
|
{
|
||||||
/// <summary>
|
}
|
||||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
|
||||||
/// </summary>
|
|
||||||
public WireMockException()
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message that describes the error.</param>
|
/// <param name="message">The message that describes the error.</param>
|
||||||
public WireMockException(string message) : base(message)
|
public WireMockException(string message) : base(message)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
/// Initializes a new instance of the <see cref="WireMockException"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="message">The message.</param>
|
/// <param name="message">The message.</param>
|
||||||
/// <param name="inner">The inner.</param>
|
/// <param name="inner">The inner.</param>
|
||||||
public WireMockException(string message, Exception inner) : base(message, inner)
|
public WireMockException(string message, Exception inner) : base(message, inner)
|
||||||
{
|
{
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
20
src/WireMock.Net/Extensions/EnumExtensions.cs
Normal file
20
src/WireMock.Net/Extensions/EnumExtensions.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
using System;
|
||||||
|
using System.Reflection;
|
||||||
|
|
||||||
|
namespace WireMock.Extensions;
|
||||||
|
|
||||||
|
internal static class EnumExtensions
|
||||||
|
{
|
||||||
|
public static string GetFullyQualifiedEnumValue<T>(this T enumValue)
|
||||||
|
where T : struct, IConvertible
|
||||||
|
{
|
||||||
|
var type = typeof(T);
|
||||||
|
|
||||||
|
if (!type.GetTypeInfo().IsEnum)
|
||||||
|
{
|
||||||
|
throw new ArgumentException("T must be an enum");
|
||||||
|
}
|
||||||
|
|
||||||
|
return $"{type.Namespace}.{type.Name}.{enumValue}";
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -3,179 +3,178 @@ using System.IO;
|
|||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
|
||||||
namespace WireMock.Handlers
|
namespace WireMock.Handlers;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Default implementation for a handler to interact with the local file system to read and write static mapping files.
|
||||||
|
/// </summary>
|
||||||
|
public class LocalFileSystemHandler : IFileSystemHandler
|
||||||
{
|
{
|
||||||
|
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
|
||||||
|
private static readonly string UnmatchedRequestsFolder = Path.Combine("requests", "unmatched");
|
||||||
|
|
||||||
|
private readonly string _rootFolder;
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Default implementation for a handler to interact with the local file system to read and write static mapping files.
|
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class LocalFileSystemHandler : IFileSystemHandler
|
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
|
||||||
{
|
{
|
||||||
private static readonly string AdminMappingsFolder = Path.Combine("__admin", "mappings");
|
}
|
||||||
private static readonly string UnmatchedRequestsFolder = Path.Combine("requests", "unmatched");
|
|
||||||
|
|
||||||
private readonly string _rootFolder;
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="rootFolder">The root folder.</param>
|
||||||
|
public LocalFileSystemHandler(string rootFolder)
|
||||||
|
{
|
||||||
|
_rootFolder = rootFolder;
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
|
||||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
public virtual bool FolderExists(string path)
|
||||||
/// </summary>
|
{
|
||||||
public LocalFileSystemHandler() : this(Directory.GetCurrentDirectory())
|
Guard.NotNullOrEmpty(path);
|
||||||
|
|
||||||
|
return Directory.Exists(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
|
||||||
|
public virtual void CreateFolder(string path)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path);
|
||||||
|
|
||||||
|
Directory.CreateDirectory(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
||||||
|
public virtual IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path);
|
||||||
|
|
||||||
|
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
||||||
|
public virtual string GetMappingFolder()
|
||||||
|
{
|
||||||
|
return Path.Combine(_rootFolder, AdminMappingsFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
|
||||||
|
public virtual string ReadMappingFile(string path)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path);
|
||||||
|
|
||||||
|
return File.ReadAllText(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile(string, string)"/>
|
||||||
|
public virtual void WriteMappingFile(string path, string text)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path, nameof(path));
|
||||||
|
Guard.NotNull(text, nameof(text));
|
||||||
|
|
||||||
|
File.WriteAllText(path, text);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
||||||
|
public virtual byte[] ReadResponseBodyAsFile(string path)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path);
|
||||||
|
path = PathUtils.CleanPath(path);
|
||||||
|
// If the file exists at the given path relative to the MappingsFolder, then return that.
|
||||||
|
// Else the path will just be as-is.
|
||||||
|
return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
||||||
|
public virtual string ReadResponseBodyAsString(string path)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(path);
|
||||||
|
path = PathUtils.CleanPath(path);
|
||||||
|
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
||||||
|
// Else the path will just be as-is.
|
||||||
|
return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
||||||
|
public virtual bool FileExists(string filename)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
|
||||||
|
return File.Exists(AdjustPathForMappingFolder(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void WriteFile(string filename, byte[] bytes)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
Guard.NotNull(bytes);
|
||||||
|
|
||||||
|
File.WriteAllBytes(AdjustPathForMappingFolder(filename), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public virtual void WriteFile(string folder, string filename, byte[] bytes)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(folder);
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
Guard.NotNull(bytes);
|
||||||
|
|
||||||
|
File.WriteAllBytes(PathUtils.Combine(folder, filename), bytes);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
||||||
|
public virtual void DeleteFile(string filename)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
|
||||||
|
File.Delete(AdjustPathForMappingFolder(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
||||||
|
public virtual byte[] ReadFile(string filename)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
|
||||||
|
return File.ReadAllBytes(AdjustPathForMappingFolder(filename));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
|
||||||
|
public virtual string ReadFileAsString(string filename)
|
||||||
|
{
|
||||||
|
return File.ReadAllText(AdjustPathForMappingFolder(Guard.NotNullOrEmpty(filename, nameof(filename))));
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.GetUnmatchedRequestsFolder"/>
|
||||||
|
public virtual string GetUnmatchedRequestsFolder()
|
||||||
|
{
|
||||||
|
return Path.Combine(_rootFolder, UnmatchedRequestsFolder);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IFileSystemHandler.WriteUnmatchedRequest"/>
|
||||||
|
public virtual void WriteUnmatchedRequest(string filename, string text)
|
||||||
|
{
|
||||||
|
Guard.NotNullOrEmpty(filename);
|
||||||
|
Guard.NotNull(text);
|
||||||
|
|
||||||
|
var folder = GetUnmatchedRequestsFolder();
|
||||||
|
if (!FolderExists(folder))
|
||||||
{
|
{
|
||||||
|
CreateFolder(folder);
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <summary>
|
File.WriteAllText(Path.Combine(folder, filename), text);
|
||||||
/// Initializes a new instance of the <see cref="LocalFileSystemHandler"/> class.
|
}
|
||||||
/// </summary>
|
|
||||||
/// <param name="rootFolder">The root folder.</param>
|
|
||||||
public LocalFileSystemHandler(string rootFolder)
|
|
||||||
{
|
|
||||||
_rootFolder = rootFolder;
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.FolderExists"/>
|
/// <summary>
|
||||||
public virtual bool FolderExists(string path)
|
/// Adjusts the path to the MappingFolder.
|
||||||
{
|
/// </summary>
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
/// <param name="filename">The path.</param>
|
||||||
|
/// <returns>Adjusted path</returns>
|
||||||
return Directory.Exists(path);
|
private string AdjustPathForMappingFolder(string filename)
|
||||||
}
|
{
|
||||||
|
return Path.Combine(GetMappingFolder(), filename);
|
||||||
/// <inheritdoc cref="IFileSystemHandler.CreateFolder"/>
|
|
||||||
public virtual void CreateFolder(string path)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
|
|
||||||
Directory.CreateDirectory(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.EnumerateFiles"/>
|
|
||||||
public virtual IEnumerable<string> EnumerateFiles(string path, bool includeSubdirectories)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
|
|
||||||
return includeSubdirectories ? Directory.EnumerateFiles(path, "*", SearchOption.AllDirectories) : Directory.EnumerateFiles(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.GetMappingFolder"/>
|
|
||||||
public virtual string GetMappingFolder()
|
|
||||||
{
|
|
||||||
return Path.Combine(_rootFolder, AdminMappingsFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.ReadMappingFile"/>
|
|
||||||
public virtual string ReadMappingFile(string path)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
|
|
||||||
return File.ReadAllText(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.WriteMappingFile(string, string)"/>
|
|
||||||
public virtual void WriteMappingFile(string path, string text)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
Guard.NotNull(text, nameof(text));
|
|
||||||
|
|
||||||
File.WriteAllText(path, text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsFile"/>
|
|
||||||
public virtual byte[] ReadResponseBodyAsFile(string path)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
path = PathUtils.CleanPath(path);
|
|
||||||
// If the file exists at the given path relative to the MappingsFolder, then return that.
|
|
||||||
// Else the path will just be as-is.
|
|
||||||
return File.ReadAllBytes(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.ReadResponseBodyAsString"/>
|
|
||||||
public virtual string ReadResponseBodyAsString(string path)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(path, nameof(path));
|
|
||||||
path = PathUtils.CleanPath(path);
|
|
||||||
// In case the path is a filename, the path will be adjusted to the MappingFolder.
|
|
||||||
// Else the path will just be as-is.
|
|
||||||
return File.ReadAllText(File.Exists(PathUtils.Combine(GetMappingFolder(), path)) ? PathUtils.Combine(GetMappingFolder(), path) : path);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.FileExists"/>
|
|
||||||
public virtual bool FileExists(string filename)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
|
||||||
|
|
||||||
return File.Exists(AdjustPathForMappingFolder(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public virtual void WriteFile(string filename, byte[] bytes)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
|
||||||
Guard.NotNull(bytes, nameof(bytes));
|
|
||||||
|
|
||||||
File.WriteAllBytes(AdjustPathForMappingFolder(filename), bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
|
||||||
public virtual void WriteFile(string folder, string filename, byte[] bytes)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(folder);
|
|
||||||
Guard.NotNullOrEmpty(filename);
|
|
||||||
Guard.NotNull(bytes);
|
|
||||||
|
|
||||||
File.WriteAllBytes(PathUtils.Combine(folder, filename), bytes);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.DeleteFile"/>
|
|
||||||
public virtual void DeleteFile(string filename)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
|
||||||
|
|
||||||
File.Delete(AdjustPathForMappingFolder(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.ReadFile"/>
|
|
||||||
public virtual byte[] ReadFile(string filename)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
|
||||||
|
|
||||||
return File.ReadAllBytes(AdjustPathForMappingFolder(filename));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.ReadFileAsString"/>
|
|
||||||
public virtual string ReadFileAsString(string filename)
|
|
||||||
{
|
|
||||||
return File.ReadAllText(AdjustPathForMappingFolder(Guard.NotNullOrEmpty(filename, nameof(filename))));
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.GetUnmatchedRequestsFolder"/>
|
|
||||||
public virtual string GetUnmatchedRequestsFolder()
|
|
||||||
{
|
|
||||||
return Path.Combine(_rootFolder, UnmatchedRequestsFolder);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <inheritdoc cref="IFileSystemHandler.WriteUnmatchedRequest"/>
|
|
||||||
public virtual void WriteUnmatchedRequest(string filename, string text)
|
|
||||||
{
|
|
||||||
Guard.NotNullOrEmpty(filename, nameof(filename));
|
|
||||||
Guard.NotNull(text, nameof(text));
|
|
||||||
|
|
||||||
var folder = GetUnmatchedRequestsFolder();
|
|
||||||
if (!FolderExists(folder))
|
|
||||||
{
|
|
||||||
CreateFolder(folder);
|
|
||||||
}
|
|
||||||
|
|
||||||
File.WriteAllText(Path.Combine(folder, filename), text);
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Adjusts the path to the MappingFolder.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="filename">The path.</param>
|
|
||||||
/// <returns>Adjusted path</returns>
|
|
||||||
private string AdjustPathForMappingFolder(string filename)
|
|
||||||
{
|
|
||||||
return Path.Combine(GetMappingFolder(), filename);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -35,9 +35,14 @@ internal static class HttpClientBuilder
|
|||||||
{
|
{
|
||||||
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
||||||
|
|
||||||
var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName);
|
var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName!);
|
||||||
handler.ClientCertificates.Add(x509Certificate2);
|
handler.ClientCertificates.Add(x509Certificate2);
|
||||||
}
|
}
|
||||||
|
else if (settings.Certificate != null)
|
||||||
|
{
|
||||||
|
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
||||||
|
handler.ClientCertificates.Add(settings.Certificate);
|
||||||
|
}
|
||||||
|
|
||||||
handler.AllowAutoRedirect = settings.AllowAutoRedirect == true;
|
handler.AllowAutoRedirect = settings.AllowAutoRedirect == true;
|
||||||
|
|
||||||
|
|||||||
@@ -28,7 +28,7 @@ internal static class HttpRequestMessageHelper
|
|||||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.Bytes:
|
case BodyType.Bytes:
|
||||||
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes, contentType);
|
httpRequestMessage.Content = ByteArrayContentHelper.Create(requestMessage.BodyData.BodyAsBytes!, contentType);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
@@ -36,7 +36,8 @@ internal static class HttpRequestMessageHelper
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString, contentType);
|
case BodyType.FormUrlEncoded:
|
||||||
|
httpRequestMessage.Content = StringContentHelper.Create(requestMessage.BodyData.BodyAsString!, contentType);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -15,7 +15,8 @@ internal static class HttpResponseMessageHelper
|
|||||||
Uri requiredUri,
|
Uri requiredUri,
|
||||||
Uri originalUri,
|
Uri originalUri,
|
||||||
bool deserializeJson,
|
bool deserializeJson,
|
||||||
bool decompressGzipAndDeflate)
|
bool decompressGzipAndDeflate,
|
||||||
|
bool deserializeFormUrlEncoded)
|
||||||
{
|
{
|
||||||
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
|
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
|
||||||
|
|
||||||
@@ -44,7 +45,8 @@ internal static class HttpResponseMessageHelper
|
|||||||
ContentType = contentTypeHeader?.FirstOrDefault(),
|
ContentType = contentTypeHeader?.FirstOrDefault(),
|
||||||
DeserializeJson = deserializeJson,
|
DeserializeJson = deserializeJson,
|
||||||
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
|
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
|
||||||
DecompressGZipAndDeflate = decompressGzipAndDeflate
|
DecompressGZipAndDeflate = decompressGzipAndDeflate,
|
||||||
|
DeserializeFormUrlEncoded = deserializeFormUrlEncoded
|
||||||
};
|
};
|
||||||
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
responseMessage.BodyData = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
@@ -55,7 +57,7 @@ internal static class HttpResponseMessageHelper
|
|||||||
// If Location header contains absolute redirect URL, and base URL is one that we proxy to,
|
// If Location header contains absolute redirect URL, and base URL is one that we proxy to,
|
||||||
// we need to replace it to original one.
|
// we need to replace it to original one.
|
||||||
if (string.Equals(header.Key, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase)
|
if (string.Equals(header.Key, HttpKnownHeaderNames.Location, StringComparison.OrdinalIgnoreCase)
|
||||||
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out Uri absoluteLocationUri)
|
&& Uri.TryCreate(header.Value.First(), UriKind.Absolute, out var absoluteLocationUri)
|
||||||
&& string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
|
&& string.Equals(absoluteLocationUri.Host, requiredUri.Host, StringComparison.OrdinalIgnoreCase))
|
||||||
{
|
{
|
||||||
var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
|
var replacedLocationUri = new Uri(originalUri, absoluteLocationUri.PathAndQuery);
|
||||||
|
|||||||
@@ -51,14 +51,14 @@ internal class WebhookSender
|
|||||||
switch (webhookRequest.TransformerType)
|
switch (webhookRequest.TransformerType)
|
||||||
{
|
{
|
||||||
case TransformerType.Handlebars:
|
case TransformerType.Handlebars:
|
||||||
var factoryHandlebars = new HandlebarsContextFactory(_settings.FileSystemHandler, _settings.HandlebarsRegistrationCallback);
|
var factoryHandlebars = new HandlebarsContextFactory(_settings);
|
||||||
transformer = new Transformer(factoryHandlebars);
|
transformer = new Transformer(_settings, factoryHandlebars);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case TransformerType.Scriban:
|
case TransformerType.Scriban:
|
||||||
case TransformerType.ScribanDotLiquid:
|
case TransformerType.ScribanDotLiquid:
|
||||||
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
|
var factoryDotLiquid = new ScribanContextFactory(_settings.FileSystemHandler, webhookRequest.TransformerType);
|
||||||
transformer = new Transformer(factoryDotLiquid);
|
transformer = new Transformer(_settings, factoryDotLiquid);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
default:
|
default:
|
||||||
|
|||||||
@@ -17,6 +17,11 @@ public interface IMapping
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
Guid Guid { get; }
|
Guid Guid { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The datetime when this mapping was created or updated.
|
||||||
|
/// </summary>
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the TimeSettings (Start, End and TTL).
|
/// Gets the TimeSettings (Start, End and TTL).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -115,7 +120,21 @@ public interface IMapping
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Use Fire and Forget for the defined webhook(s). [Optional]
|
/// Use Fire and Forget for the defined webhook(s). [Optional]
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public bool? UseWebhooksFireAndForget { get; set; }
|
bool? UseWebhooksFireAndForget { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Data Object which can be used when WithTransformer is used.
|
||||||
|
/// e.g. lookup an path in this object using
|
||||||
|
/// <example>
|
||||||
|
/// lookup data "1"
|
||||||
|
/// </example>
|
||||||
|
/// </summary>
|
||||||
|
object? Data { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The probability when this request should be matched. Value is between 0 and 1. [Optional]
|
||||||
|
/// </summary>
|
||||||
|
double? Probability { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// ProvideResponseAsync
|
/// ProvideResponseAsync
|
||||||
|
|||||||
60
src/WireMock.Net/IMappingBuilder.cs
Normal file
60
src/WireMock.Net/IMappingBuilder.cs
Normal file
@@ -0,0 +1,60 @@
|
|||||||
|
using System;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Server;
|
||||||
|
using WireMock.Types;
|
||||||
|
|
||||||
|
namespace WireMock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// IMappingBuilder
|
||||||
|
/// </summary>
|
||||||
|
public interface IMappingBuilder
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// The given.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="requestMatcher">The request matcher.</param>
|
||||||
|
/// <param name="saveToFile">Optional boolean to indicate if this mapping should be saved as static mapping file.</param>
|
||||||
|
/// <returns>The <see cref="IRespondWithAProvider"/>.</returns>
|
||||||
|
IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets all the mappings as a list.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>A list from <see cref="MappingModel"/>s.</returns>
|
||||||
|
MappingModel[] GetMappings();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all mappings to JSON.
|
||||||
|
/// </summary>
|
||||||
|
/// <returns>JSON</returns>
|
||||||
|
string ToJson();
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save all mappings as a single JSON to a file.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="path">The file to write to.</param>
|
||||||
|
void SaveMappingsToFile(string path);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Save all mappings as multiple JSON files (each file is 1 mapping).
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="folder">The folder to write the files to.</param>
|
||||||
|
void SaveMappingsToFolder(string folder);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the C# code for a mapping.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="guid">The Mapping Guid.</param>
|
||||||
|
/// <param name="converterType">The <see cref="MappingConverterType"/></param>
|
||||||
|
/// <returns>C# code (null in case the mapping is not found)</returns>
|
||||||
|
string? ToCSharpCode(Guid guid, MappingConverterType converterType);
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Get the C# code for all mappings.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="converterType">The <see cref="MappingConverterType"/></param>
|
||||||
|
/// <returns>C# code</returns>
|
||||||
|
public string ToCSharpCode(MappingConverterType converterType);
|
||||||
|
}
|
||||||
10
src/WireMock.Net/Json/DynamicJsonClassOptions.cs
Normal file
10
src/WireMock.Net/Json/DynamicJsonClassOptions.cs
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
// Copied from https://github.com/Handlebars-Net/Handlebars.Net.Helpers/blob/master/src/Handlebars.Net.Helpers.DynamicLinq
|
||||||
|
|
||||||
|
namespace WireMock.Json;
|
||||||
|
|
||||||
|
internal class DynamicJsonClassOptions
|
||||||
|
{
|
||||||
|
public IntegerBehavior IntegerConvertBehavior { get; set; } = IntegerBehavior.UseLong;
|
||||||
|
|
||||||
|
public FloatBehavior FloatConvertBehavior { get; set; } = FloatBehavior.UseDouble;
|
||||||
|
}
|
||||||
15
src/WireMock.Net/Json/DynamicPropertyWithValue.cs
Normal file
15
src/WireMock.Net/Json/DynamicPropertyWithValue.cs
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
// Copied from https://github.com/Handlebars-Net/Handlebars.Net.Helpers/blob/master/src/Handlebars.Net.Helpers.DynamicLinq
|
||||||
|
|
||||||
|
using System.Linq.Dynamic.Core;
|
||||||
|
|
||||||
|
namespace WireMock.Json;
|
||||||
|
|
||||||
|
internal class DynamicPropertyWithValue : DynamicProperty
|
||||||
|
{
|
||||||
|
public object? Value { get; }
|
||||||
|
|
||||||
|
public DynamicPropertyWithValue(string name, object? value) : base(name, value?.GetType() ?? typeof(object))
|
||||||
|
{
|
||||||
|
Value = value;
|
||||||
|
}
|
||||||
|
}
|
||||||
24
src/WireMock.Net/Json/FloatBehavior.cs
Normal file
24
src/WireMock.Net/Json/FloatBehavior.cs
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
// Copied from https://github.com/Handlebars-Net/Handlebars.Net.Helpers/blob/master/src/Handlebars.Net.Helpers.DynamicLinq
|
||||||
|
|
||||||
|
namespace WireMock.Json;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum to define how to convert an Float in the Json Object.
|
||||||
|
/// </summary>
|
||||||
|
internal enum FloatBehavior
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all Float types in the Json Object to a double. (default)
|
||||||
|
/// </summary>
|
||||||
|
UseDouble = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all Float types in the Json Object to a float (unless overflow).
|
||||||
|
/// </summary>
|
||||||
|
UseFloat = 1,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all Float types in the Json Object to a decimal (unless overflow).
|
||||||
|
/// </summary>
|
||||||
|
UseDecimal = 2
|
||||||
|
}
|
||||||
20
src/WireMock.Net/Json/IntegerBehavior.cs
Normal file
20
src/WireMock.Net/Json/IntegerBehavior.cs
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
// Copied from https://github.com/Handlebars-Net/Handlebars.Net.Helpers/blob/master/src/Handlebars.Net.Helpers.DynamicLinq
|
||||||
|
|
||||||
|
namespace WireMock.Json;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Enum to define how to convert an Integer in the Json Object.
|
||||||
|
/// </summary>
|
||||||
|
internal enum IntegerBehavior
|
||||||
|
{
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all Integer types in the Json Object to a int (unless overflow).
|
||||||
|
/// (default)
|
||||||
|
/// </summary>
|
||||||
|
UseInt = 0,
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Convert all Integer types in the Json Object to a long.
|
||||||
|
/// </summary>
|
||||||
|
UseLong = 1
|
||||||
|
}
|
||||||
202
src/WireMock.Net/Json/JObjectExtensions.cs
Normal file
202
src/WireMock.Net/Json/JObjectExtensions.cs
Normal file
@@ -0,0 +1,202 @@
|
|||||||
|
// Copied from https://github.com/Handlebars-Net/Handlebars.Net.Helpers/blob/master/src/Handlebars.Net.Helpers.DynamicLinq
|
||||||
|
|
||||||
|
using System;
|
||||||
|
using System.Collections;
|
||||||
|
using System.Collections.Generic;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Linq.Dynamic.Core;
|
||||||
|
using System.Reflection;
|
||||||
|
using Newtonsoft.Json.Linq;
|
||||||
|
|
||||||
|
namespace WireMock.Json;
|
||||||
|
|
||||||
|
internal static class JObjectExtensions
|
||||||
|
{
|
||||||
|
private class JTokenResolvers : Dictionary<JTokenType, Func<JToken, DynamicJsonClassOptions?, object?>>
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly JTokenResolvers Resolvers = new()
|
||||||
|
{
|
||||||
|
{ JTokenType.Array, ConvertJTokenArray },
|
||||||
|
{ JTokenType.Boolean, (jToken, _) => jToken.Value<bool>() },
|
||||||
|
{ JTokenType.Bytes, (jToken, _) => jToken.Value<byte[]>() },
|
||||||
|
{ JTokenType.Date, (jToken, _) => jToken.Value<DateTime>() },
|
||||||
|
{ JTokenType.Float, ConvertJTokenFloat },
|
||||||
|
{ JTokenType.Guid, (jToken, _) => jToken.Value<Guid>() },
|
||||||
|
{ JTokenType.Integer, ConvertJTokenInteger },
|
||||||
|
{ JTokenType.None, (_, _) => null },
|
||||||
|
{ JTokenType.Null, (_, _) => null },
|
||||||
|
{ JTokenType.Object, ConvertJObject },
|
||||||
|
{ JTokenType.Property, ConvertJTokenProperty },
|
||||||
|
{ JTokenType.String, (jToken, _) => jToken.Value<string>() },
|
||||||
|
{ JTokenType.TimeSpan, (jToken, _) => jToken.Value<TimeSpan>() },
|
||||||
|
{ JTokenType.Undefined, (_, _) => null },
|
||||||
|
{ JTokenType.Uri, (o, _) => o.Value<Uri>() },
|
||||||
|
};
|
||||||
|
|
||||||
|
internal static DynamicClass? ToDynamicJsonClass(this JObject? src, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (src == null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var dynamicPropertyWithValues = new List<DynamicPropertyWithValue>();
|
||||||
|
|
||||||
|
foreach (var prop in src.Properties())
|
||||||
|
{
|
||||||
|
var value = Resolvers[prop.Type](prop.Value, options);
|
||||||
|
if (value != null)
|
||||||
|
{
|
||||||
|
dynamicPropertyWithValues.Add(new DynamicPropertyWithValue(prop.Name, value));
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return CreateInstance(dynamicPropertyWithValues);
|
||||||
|
}
|
||||||
|
|
||||||
|
internal static IEnumerable ToDynamicClassArray(this JArray? src, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (src == null)
|
||||||
|
{
|
||||||
|
return EmptyArray<object?>.Value;
|
||||||
|
}
|
||||||
|
|
||||||
|
return ConvertJTokenArray(src, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object? ConvertJObject(JToken arg, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (arg is JObject asJObject)
|
||||||
|
{
|
||||||
|
return asJObject.ToDynamicJsonClass(options);
|
||||||
|
}
|
||||||
|
|
||||||
|
return GetResolverFor(arg)(arg, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object PassThrough(JToken arg, DynamicJsonClassOptions? options)
|
||||||
|
{
|
||||||
|
return arg;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Func<JToken, DynamicJsonClassOptions?, object?> GetResolverFor(JToken arg)
|
||||||
|
{
|
||||||
|
return Resolvers.TryGetValue(arg.Type, out var result) ? result : PassThrough;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ConvertJTokenFloat(JToken arg, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (arg.Type != JTokenType.Float)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Unable to convert {nameof(JToken)} of type: {arg.Type} to double or float.");
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.FloatConvertBehavior == FloatBehavior.UseFloat)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return arg.Value<float>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return arg.Value<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (options?.FloatConvertBehavior == FloatBehavior.UseDecimal)
|
||||||
|
{
|
||||||
|
try
|
||||||
|
{
|
||||||
|
return arg.Value<decimal>();
|
||||||
|
}
|
||||||
|
catch
|
||||||
|
{
|
||||||
|
return arg.Value<double>();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
return arg.Value<double>();
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object ConvertJTokenInteger(JToken arg, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (arg.Type != JTokenType.Integer)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Unable to convert {nameof(JToken)} of type: {arg.Type} to long or int.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var longValue = arg.Value<long>();
|
||||||
|
|
||||||
|
if (options is null || options.IntegerConvertBehavior == IntegerBehavior.UseInt)
|
||||||
|
{
|
||||||
|
if (longValue is >= int.MinValue and <= int.MaxValue)
|
||||||
|
{
|
||||||
|
return Convert.ToInt32(longValue);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return longValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static object? ConvertJTokenProperty(JToken arg, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
var resolver = GetResolverFor(arg);
|
||||||
|
if (resolver is null)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Unable to handle {nameof(JToken)} of type: {arg.Type}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
return resolver(arg, options);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable ConvertJTokenArray(JToken arg, DynamicJsonClassOptions? options = null)
|
||||||
|
{
|
||||||
|
if (arg is not JArray array)
|
||||||
|
{
|
||||||
|
throw new InvalidOperationException($"Unable to convert {nameof(JToken)} of type: {arg.Type} to {nameof(JArray)}.");
|
||||||
|
}
|
||||||
|
|
||||||
|
var result = new List<object?>();
|
||||||
|
foreach (var item in array)
|
||||||
|
{
|
||||||
|
result.Add(ConvertJObject(item));
|
||||||
|
}
|
||||||
|
|
||||||
|
var distinctType = FindSameTypeOf(result);
|
||||||
|
return distinctType == null ? result.ToArray() : ConvertToTypedArray(result, distinctType);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static Type? FindSameTypeOf(IEnumerable<object?> src)
|
||||||
|
{
|
||||||
|
var types = src.Select(o => o?.GetType()).Distinct().OfType<Type>().ToArray();
|
||||||
|
return types.Length == 1 ? types[0] : null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static IEnumerable ConvertToTypedArray(IEnumerable<object?> src, Type newType)
|
||||||
|
{
|
||||||
|
var method = ConvertToTypedArrayGenericMethod.MakeGenericMethod(newType);
|
||||||
|
return (IEnumerable)method.Invoke(null, new object[] { src })!;
|
||||||
|
}
|
||||||
|
|
||||||
|
private static readonly MethodInfo ConvertToTypedArrayGenericMethod = typeof(JObjectExtensions).GetMethod(nameof(ConvertToTypedArrayGeneric), BindingFlags.NonPublic | BindingFlags.Static)!;
|
||||||
|
|
||||||
|
private static T[] ConvertToTypedArrayGeneric<T>(IEnumerable<object> src)
|
||||||
|
{
|
||||||
|
return src.Cast<T>().ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
public static DynamicClass CreateInstance(IList<DynamicPropertyWithValue> dynamicPropertiesWithValue, bool createParameterCtor = true)
|
||||||
|
{
|
||||||
|
var type = DynamicClassFactory.CreateType(dynamicPropertiesWithValue.Cast<DynamicProperty>().ToArray(), createParameterCtor);
|
||||||
|
var dynamicClass = (DynamicClass)Activator.CreateInstance(type);
|
||||||
|
foreach (var dynamicPropertyWithValue in dynamicPropertiesWithValue.Where(p => p.Value != null))
|
||||||
|
{
|
||||||
|
dynamicClass.SetDynamicPropertyValue(dynamicPropertyWithValue.Name, dynamicPropertyWithValue.Value!);
|
||||||
|
}
|
||||||
|
|
||||||
|
return dynamicClass;
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -15,6 +15,9 @@ public class Mapping : IMapping
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public Guid Guid { get; }
|
public Guid Guid { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public DateTime? UpdatedAt { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string? Title { get; }
|
public string? Title { get; }
|
||||||
|
|
||||||
@@ -64,15 +67,22 @@ public class Mapping : IMapping
|
|||||||
public IWebhook[]? Webhooks { get; }
|
public IWebhook[]? Webhooks { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public bool? UseWebhooksFireAndForget { get; set; }
|
public bool? UseWebhooksFireAndForget { get; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public ITimeSettings? TimeSettings { get; }
|
public ITimeSettings? TimeSettings { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public object? Data { get; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public double? Probability { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
/// Initializes a new instance of the <see cref="Mapping"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="guid">The unique identifier.</param>
|
/// <param name="guid">The unique identifier.</param>
|
||||||
|
/// <param name="updatedAt">The datetime when this mapping was created.</param>
|
||||||
/// <param name="title">The unique title (can be null).</param>
|
/// <param name="title">The unique title (can be null).</param>
|
||||||
/// <param name="description">The description (can be null).</param>
|
/// <param name="description">The description (can be null).</param>
|
||||||
/// <param name="path">The full file path from this mapping title (can be null).</param>
|
/// <param name="path">The full file path from this mapping title (can be null).</param>
|
||||||
@@ -87,8 +97,11 @@ public class Mapping : IMapping
|
|||||||
/// <param name="webhooks">The Webhooks. [Optional]</param>
|
/// <param name="webhooks">The Webhooks. [Optional]</param>
|
||||||
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
|
/// <param name="useWebhooksFireAndForget">Use Fire and Forget for the defined webhook(s). [Optional]</param>
|
||||||
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
|
/// <param name="timeSettings">The TimeSettings. [Optional]</param>
|
||||||
|
/// <param name="data">The data object. [Optional]</param>
|
||||||
|
/// <param name="probability">Define the probability when this request should be matched. [Optional]</param>
|
||||||
public Mapping(
|
public Mapping(
|
||||||
Guid guid,
|
Guid guid,
|
||||||
|
DateTime updatedAt,
|
||||||
string? title,
|
string? title,
|
||||||
string? description,
|
string? description,
|
||||||
string? path,
|
string? path,
|
||||||
@@ -102,9 +115,12 @@ public class Mapping : IMapping
|
|||||||
int? stateTimes,
|
int? stateTimes,
|
||||||
IWebhook[]? webhooks,
|
IWebhook[]? webhooks,
|
||||||
bool? useWebhooksFireAndForget,
|
bool? useWebhooksFireAndForget,
|
||||||
ITimeSettings? timeSettings)
|
ITimeSettings? timeSettings,
|
||||||
|
object? data,
|
||||||
|
double? probability)
|
||||||
{
|
{
|
||||||
Guid = guid;
|
Guid = guid;
|
||||||
|
UpdatedAt = updatedAt;
|
||||||
Title = title;
|
Title = title;
|
||||||
Description = description;
|
Description = description;
|
||||||
Path = path;
|
Path = path;
|
||||||
@@ -119,6 +135,8 @@ public class Mapping : IMapping
|
|||||||
Webhooks = webhooks;
|
Webhooks = webhooks;
|
||||||
UseWebhooksFireAndForget = useWebhooksFireAndForget;
|
UseWebhooksFireAndForget = useWebhooksFireAndForget;
|
||||||
TimeSettings = timeSettings;
|
TimeSettings = timeSettings;
|
||||||
|
Data = data;
|
||||||
|
Probability = probability;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||||
|
|||||||
155
src/WireMock.Net/MappingBuilder.cs
Normal file
155
src/WireMock.Net/MappingBuilder.cs
Normal file
@@ -0,0 +1,155 @@
|
|||||||
|
using System;
|
||||||
|
using System.Linq;
|
||||||
|
using System.Text;
|
||||||
|
using Newtonsoft.Json;
|
||||||
|
using Stef.Validation;
|
||||||
|
using WireMock.Admin.Mappings;
|
||||||
|
using WireMock.Matchers.Request;
|
||||||
|
using WireMock.Owin;
|
||||||
|
using WireMock.Serialization;
|
||||||
|
using WireMock.Server;
|
||||||
|
using WireMock.Settings;
|
||||||
|
using WireMock.Types;
|
||||||
|
using WireMock.Util;
|
||||||
|
|
||||||
|
namespace WireMock;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// MappingBuilder
|
||||||
|
/// </summary>
|
||||||
|
public class MappingBuilder : IMappingBuilder
|
||||||
|
{
|
||||||
|
private readonly WireMockServerSettings _settings;
|
||||||
|
private readonly IWireMockMiddlewareOptions _options;
|
||||||
|
private readonly MappingConverter _mappingConverter;
|
||||||
|
private readonly MappingToFileSaver _mappingToFileSaver;
|
||||||
|
private readonly IGuidUtils _guidUtils;
|
||||||
|
private readonly IDateTimeUtils _dateTimeUtils;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Create a MappingBuilder
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="settings">The optional <see cref="WireMockServerSettings"/>.</param>
|
||||||
|
public MappingBuilder(WireMockServerSettings? settings = null)
|
||||||
|
{
|
||||||
|
_settings = settings ?? new WireMockServerSettings();
|
||||||
|
_options = WireMockMiddlewareOptionsHelper.InitFromSettings(_settings);
|
||||||
|
|
||||||
|
var matcherMapper = new MatcherMapper(_settings);
|
||||||
|
_mappingConverter = new MappingConverter(matcherMapper);
|
||||||
|
_mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter);
|
||||||
|
|
||||||
|
_guidUtils = new GuidUtils();
|
||||||
|
_dateTimeUtils = new DateTimeUtils();
|
||||||
|
}
|
||||||
|
|
||||||
|
internal MappingBuilder(
|
||||||
|
WireMockServerSettings settings,
|
||||||
|
IWireMockMiddlewareOptions options,
|
||||||
|
MappingConverter mappingConverter,
|
||||||
|
MappingToFileSaver mappingToFileSaver,
|
||||||
|
IGuidUtils guidUtils,
|
||||||
|
IDateTimeUtils dateTimeUtils
|
||||||
|
)
|
||||||
|
{
|
||||||
|
_settings = Guard.NotNull(settings);
|
||||||
|
_options = Guard.NotNull(options);
|
||||||
|
_mappingConverter = Guard.NotNull(mappingConverter);
|
||||||
|
_mappingToFileSaver = Guard.NotNull(mappingToFileSaver);
|
||||||
|
_guidUtils = Guard.NotNull(guidUtils);
|
||||||
|
_dateTimeUtils = Guard.NotNull(dateTimeUtils);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false)
|
||||||
|
{
|
||||||
|
return new RespondWithAProvider(RegisterMapping, Guard.NotNull(requestMatcher), _settings, _guidUtils, _dateTimeUtils, saveToFile);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public MappingModel[] GetMappings()
|
||||||
|
{
|
||||||
|
return GetNonAdminMappings().Select(_mappingConverter.ToMappingModel).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string ToJson()
|
||||||
|
{
|
||||||
|
return ToJson(GetMappings());
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string? ToCSharpCode(Guid guid, MappingConverterType converterType)
|
||||||
|
{
|
||||||
|
var mapping = GetNonAdminMappings().FirstOrDefault(m => m.Guid == guid);
|
||||||
|
if (mapping is null)
|
||||||
|
{
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
var settings = new MappingConverterSettings { AddStart = true, ConverterType = converterType };
|
||||||
|
return _mappingConverter.ToCSharpCode(mapping, settings);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public string ToCSharpCode(MappingConverterType converterType)
|
||||||
|
{
|
||||||
|
var sb = new StringBuilder();
|
||||||
|
bool addStart = true;
|
||||||
|
foreach (var mapping in GetNonAdminMappings())
|
||||||
|
{
|
||||||
|
sb.AppendLine(_mappingConverter.ToCSharpCode(mapping, new MappingConverterSettings { AddStart = addStart, ConverterType = converterType }));
|
||||||
|
|
||||||
|
if (addStart)
|
||||||
|
{
|
||||||
|
addStart = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return sb.ToString();
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void SaveMappingsToFile(string path)
|
||||||
|
{
|
||||||
|
_mappingToFileSaver.SaveMappingsToFile(GetNonAdminMappings(), path);
|
||||||
|
}
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public void SaveMappingsToFolder(string? folder)
|
||||||
|
{
|
||||||
|
foreach (var mapping in GetNonAdminMappings())
|
||||||
|
{
|
||||||
|
_mappingToFileSaver.SaveMappingToFile(mapping, folder);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private IMapping[] GetNonAdminMappings()
|
||||||
|
{
|
||||||
|
return _options.Mappings.Values.Where(m => !m.IsAdminInterface).OrderBy(m => m.UpdatedAt).ToArray();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void RegisterMapping(IMapping mapping, bool saveToFile)
|
||||||
|
{
|
||||||
|
// Check a mapping exists with the same Guid. If so, update the datetime and replace it.
|
||||||
|
if (_options.Mappings.ContainsKey(mapping.Guid))
|
||||||
|
{
|
||||||
|
mapping.UpdatedAt = _dateTimeUtils.UtcNow;
|
||||||
|
_options.Mappings[mapping.Guid] = mapping;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (saveToFile)
|
||||||
|
{
|
||||||
|
_mappingToFileSaver.SaveMappingToFile(mapping);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private static string ToJson(object value)
|
||||||
|
{
|
||||||
|
return JsonConvert.SerializeObject(value, JsonSerializationConstants.JsonSerializerSettingsDefault);
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Net.Http.Headers;
|
using System.Net.Http.Headers;
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
|
|
||||||
namespace WireMock.Matchers;
|
namespace WireMock.Matchers;
|
||||||
|
|||||||
@@ -5,8 +5,8 @@ using AnyOfTypes;
|
|||||||
using Newtonsoft.Json.Linq;
|
using Newtonsoft.Json.Linq;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Extensions;
|
using WireMock.Extensions;
|
||||||
|
using WireMock.Json;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
using WireMock.Util;
|
|
||||||
|
|
||||||
namespace WireMock.Matchers;
|
namespace WireMock.Matchers;
|
||||||
|
|
||||||
@@ -100,38 +100,55 @@ public class LinqMatcher : IObjectMatcher, IStringMatcher
|
|||||||
{
|
{
|
||||||
double match = MatchScores.Mismatch;
|
double match = MatchScores.Mismatch;
|
||||||
|
|
||||||
JObject value;
|
JArray jArray;
|
||||||
switch (input)
|
try
|
||||||
{
|
{
|
||||||
case JObject valueAsJObject:
|
jArray = new JArray { input };
|
||||||
value = valueAsJObject;
|
}
|
||||||
break;
|
catch
|
||||||
|
{
|
||||||
case { } valueAsObject:
|
jArray = new JArray { JToken.FromObject(input) };
|
||||||
value = JObject.FromObject(valueAsObject);
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
return MatchScores.Mismatch;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//enumerable = jArray.ToDynamicClassArray();
|
||||||
|
|
||||||
|
//JObject value;
|
||||||
|
//switch (input)
|
||||||
|
//{
|
||||||
|
// case JObject valueAsJObject:
|
||||||
|
// value = valueAsJObject;
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// case { } valueAsObject:
|
||||||
|
// value = JObject.FromObject(valueAsObject);
|
||||||
|
// break;
|
||||||
|
|
||||||
|
// default:
|
||||||
|
// return MatchScores.Mismatch;
|
||||||
|
//}
|
||||||
|
|
||||||
// Convert a single object to a Queryable JObject-list with 1 entry.
|
// Convert a single object to a Queryable JObject-list with 1 entry.
|
||||||
var queryable1 = new[] { value }.AsQueryable();
|
//var queryable1 = new[] { value }.AsQueryable();
|
||||||
|
var queryable = jArray.ToDynamicClassArray().AsQueryable();
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
// Generate the DynamicLinq select statement.
|
// Generate the DynamicLinq select statement.
|
||||||
string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
|
//string dynamicSelect = JsonUtils.GenerateDynamicLinqStatement(value);
|
||||||
|
|
||||||
// Execute DynamicLinq Select statement.
|
// Execute DynamicLinq Select statement.
|
||||||
var queryable2 = queryable1.Select(dynamicSelect);
|
//var queryable2 = queryable1.Select(dynamicSelect);
|
||||||
|
|
||||||
// Use the Any(...) method to check if the result matches.
|
// Use the Any(...) method to check if the result matches.
|
||||||
match = MatchScores.ToScore(_patterns.Select(pattern => queryable2.Any(pattern)).ToArray(), MatchOperator);
|
|
||||||
|
var patternsAsStringArray = _patterns.Select(p => p.GetPattern()).ToArray();
|
||||||
|
var scores = patternsAsStringArray.Select(p => queryable.Any(p)).ToArray();
|
||||||
|
|
||||||
|
match = MatchScores.ToScore(_patterns.Select(pattern => queryable.Any(pattern.GetPattern())).ToArray(), MatchOperator);
|
||||||
|
|
||||||
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
return MatchBehaviourHelper.Convert(MatchBehaviour, match);
|
||||||
}
|
}
|
||||||
catch
|
catch (Exception e)
|
||||||
{
|
{
|
||||||
if (ThrowException)
|
if (ThrowException)
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System;
|
using System;
|
||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Diagnostics.CodeAnalysis;
|
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
|
|
||||||
namespace WireMock.Matchers;
|
namespace WireMock.Matchers;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AnyOfTypes;
|
using AnyOfTypes;
|
||||||
using WireMock.Models;
|
using WireMock.Models;
|
||||||
@@ -62,7 +63,7 @@ public class NotNullOrEmptyMatcher : IObjectMatcher, IStringMatcher
|
|||||||
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
/// <inheritdoc cref="IStringMatcher.GetPatterns"/>
|
||||||
public AnyOf<string, StringPattern>[] GetPatterns()
|
public AnyOf<string, StringPattern>[] GetPatterns()
|
||||||
{
|
{
|
||||||
return new AnyOf<string, StringPattern>[0];
|
return EmptyArray<AnyOf<string, StringPattern>>.Value;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
|
|||||||
@@ -1,8 +1,7 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using AnyOfTypes;
|
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Models;
|
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
@@ -33,6 +32,11 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
public Func<IBodyData?, bool>? BodyDataFunc { get; }
|
public Func<IBodyData?, bool>? BodyDataFunc { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// The body data function for FormUrlEncoded
|
||||||
|
/// </summary>
|
||||||
|
public Func<IDictionary<string, string>?, bool>? FormUrlEncodedFunc { get; }
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// The matchers.
|
/// The matchers.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -109,6 +113,15 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
BodyDataFunc = Guard.NotNull(func);
|
BodyDataFunc = Guard.NotNull(func);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="func">The function.</param>
|
||||||
|
public RequestMessageBodyMatcher(Func<IDictionary<string, string>?, bool> func)
|
||||||
|
{
|
||||||
|
FormUrlEncodedFunc = Guard.NotNull(func);
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
/// Initializes a new instance of the <see cref="RequestMessageBodyMatcher"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
@@ -144,6 +157,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
{
|
{
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
return notNullOrEmptyMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||||
|
|
||||||
case BodyType.Bytes:
|
case BodyType.Bytes:
|
||||||
@@ -158,7 +172,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
{
|
{
|
||||||
// If the body is a byte array, try to match.
|
// If the body is a byte array, try to match.
|
||||||
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
|
var detectedBodyType = requestMessage.BodyData?.DetectedBodyType;
|
||||||
if (detectedBodyType is BodyType.Bytes or BodyType.String)
|
if (detectedBodyType is BodyType.Bytes or BodyType.String or BodyType.FormUrlEncoded)
|
||||||
{
|
{
|
||||||
return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
|
return exactObjectMatcher.IsMatch(requestMessage.BodyData?.BodyAsBytes);
|
||||||
}
|
}
|
||||||
@@ -184,7 +198,7 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
if (matcher is IStringMatcher stringMatcher)
|
if (matcher is IStringMatcher stringMatcher)
|
||||||
{
|
{
|
||||||
// If the body is a Json or a String, use the BodyAsString to match on.
|
// If the body is a Json or a String, use the BodyAsString to match on.
|
||||||
if (requestMessage?.BodyData?.DetectedBodyType == BodyType.Json || requestMessage?.BodyData?.DetectedBodyType == BodyType.String)
|
if (requestMessage?.BodyData?.DetectedBodyType is BodyType.Json or BodyType.String or BodyType.FormUrlEncoded)
|
||||||
{
|
{
|
||||||
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
return stringMatcher.IsMatch(requestMessage.BodyData.BodyAsString);
|
||||||
}
|
}
|
||||||
@@ -206,6 +220,11 @@ public class RequestMessageBodyMatcher : IRequestMatcher
|
|||||||
return MatchScores.ToScore(Func(requestMessage.BodyData?.BodyAsString));
|
return MatchScores.ToScore(Func(requestMessage.BodyData?.BodyAsString));
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (FormUrlEncodedFunc != null)
|
||||||
|
{
|
||||||
|
return MatchScores.ToScore(FormUrlEncodedFunc(requestMessage.BodyData?.BodyAsFormUrlEncoded));
|
||||||
|
}
|
||||||
|
|
||||||
if (JsonFunc != null)
|
if (JsonFunc != null)
|
||||||
{
|
{
|
||||||
return MatchScores.ToScore(JsonFunc(requestMessage.BodyData?.BodyAsJson));
|
return MatchScores.ToScore(JsonFunc(requestMessage.BodyData?.BodyAsJson));
|
||||||
|
|||||||
@@ -1,6 +1,5 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using JetBrains.Annotations;
|
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
|
||||||
namespace WireMock.Matchers.Request;
|
namespace WireMock.Matchers.Request;
|
||||||
@@ -25,9 +24,9 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="requestMatchers">The request matchers.</param>
|
/// <param name="requestMatchers">The request matchers.</param>
|
||||||
/// <param name="type">The CompositeMatcherType type (Defaults to 'And')</param>
|
/// <param name="type">The CompositeMatcherType type (Defaults to 'And')</param>
|
||||||
protected RequestMessageCompositeMatcher([NotNull] IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
protected RequestMessageCompositeMatcher(IEnumerable<IRequestMatcher> requestMatchers, CompositeMatcherType type = CompositeMatcherType.And)
|
||||||
{
|
{
|
||||||
Guard.NotNull(requestMatchers, nameof(requestMatchers));
|
Guard.NotNull(requestMatchers);
|
||||||
|
|
||||||
_type = type;
|
_type = type;
|
||||||
RequestMatchers = requestMatchers;
|
RequestMatchers = requestMatchers;
|
||||||
|
|||||||
@@ -1,3 +1,4 @@
|
|||||||
|
using System.Collections.Generic;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WireMock.Types;
|
using WireMock.Types;
|
||||||
|
|
||||||
@@ -14,6 +15,9 @@ public class BodyData : IBodyData
|
|||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public string? BodyAsString { get; set; }
|
public string? BodyAsString { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc />
|
||||||
|
public IDictionary<string, string>? BodyAsFormUrlEncoded { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc cref="IBodyData.BodyAsJson" />
|
/// <inheritdoc cref="IBodyData.BodyAsJson" />
|
||||||
public object? BodyAsJson { get; set; }
|
public object? BodyAsJson { get; set; }
|
||||||
|
|
||||||
|
|||||||
@@ -1,19 +1,18 @@
|
|||||||
using System;
|
using System;
|
||||||
|
|
||||||
namespace WireMock.Models
|
namespace WireMock.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// TimeSettingsModel: Start, End and TTL
|
||||||
|
/// </summary>
|
||||||
|
public class TimeSettings : ITimeSettings
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <inheritdoc />
|
||||||
/// TimeSettingsModel: Start, End and TTL
|
public DateTime? Start { get; set; }
|
||||||
/// </summary>
|
|
||||||
public class TimeSettings : ITimeSettings
|
|
||||||
{
|
|
||||||
/// <inheritdoc />
|
|
||||||
public DateTime? Start { get; set; }
|
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public DateTime? End { get; set; }
|
public DateTime? End { get; set; }
|
||||||
|
|
||||||
/// <inheritdoc />
|
/// <inheritdoc />
|
||||||
public int? TTL { get; set; }
|
public int? TTL { get; set; }
|
||||||
}
|
|
||||||
}
|
}
|
||||||
@@ -1,51 +1,47 @@
|
|||||||
using System;
|
using System;
|
||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
|
|
||||||
namespace WireMock.Models
|
namespace WireMock.Models;
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// UrlDetails
|
||||||
|
/// </summary>
|
||||||
|
public class UrlDetails
|
||||||
{
|
{
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// UrlDetails
|
/// Gets the url (relative).
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public class UrlDetails
|
public Uri Url { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Gets the AbsoluteUrl.
|
||||||
|
/// </summary>
|
||||||
|
public Uri AbsoluteUrl { get; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
||||||
|
/// </summary>
|
||||||
|
/// <param name="url">The URL.</param>
|
||||||
|
public UrlDetails(string url) : this(new Uri(url))
|
||||||
{
|
{
|
||||||
/// <summary>
|
}
|
||||||
/// Gets the url (relative).
|
|
||||||
/// </summary>
|
|
||||||
public Uri Url { get; }
|
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Gets the AbsoluteUrl.
|
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Uri AbsoluteUrl { get; }
|
/// <param name="url">The URL.</param>
|
||||||
|
public UrlDetails(Uri url) : this(url, url)
|
||||||
|
{
|
||||||
|
}
|
||||||
|
|
||||||
/// <summary>
|
/// <summary>
|
||||||
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="url">The URL.</param>
|
/// <param name="absoluteUrl">The absolute URL.</param>
|
||||||
public UrlDetails(string url) : this(new Uri(url))
|
/// <param name="url">The URL (relative).</param>
|
||||||
{
|
public UrlDetails(Uri absoluteUrl, Uri url)
|
||||||
}
|
{
|
||||||
|
AbsoluteUrl = Guard.NotNull(absoluteUrl);
|
||||||
/// <summary>
|
Url = Guard.NotNull(url);
|
||||||
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="url">The URL.</param>
|
|
||||||
public UrlDetails(Uri url) : this(url, url)
|
|
||||||
{
|
|
||||||
}
|
|
||||||
|
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="UrlDetails"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="absoluteUrl">The absolute URL.</param>
|
|
||||||
/// <param name="url">The URL (relative).</param>
|
|
||||||
public UrlDetails(Uri absoluteUrl, Uri url)
|
|
||||||
{
|
|
||||||
Guard.NotNull(absoluteUrl, nameof(absoluteUrl));
|
|
||||||
Guard.NotNull(url, nameof(url));
|
|
||||||
|
|
||||||
AbsoluteUrl = absoluteUrl;
|
|
||||||
Url = url;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -2,9 +2,10 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.HttpsCertificate;
|
using CertificateLoader = WireMock.HttpsCertificate.CertificateLoader;
|
||||||
|
|
||||||
namespace WireMock.Owin
|
namespace WireMock.Owin
|
||||||
{
|
{
|
||||||
@@ -26,21 +27,25 @@ namespace WireMock.Owin
|
|||||||
{
|
{
|
||||||
kestrelOptions.ListenAnyIP(urlDetail.Port, listenOptions =>
|
kestrelOptions.ListenAnyIP(urlDetail.Port, listenOptions =>
|
||||||
{
|
{
|
||||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
listenOptions.UseHttps(options =>
|
||||||
{
|
{
|
||||||
listenOptions.UseHttps(CertificateLoader.LoadCertificate(
|
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||||
wireMockMiddlewareOptions.X509StoreName,
|
{
|
||||||
wireMockMiddlewareOptions.X509StoreLocation,
|
options.ServerCertificate = CertificateLoader.LoadCertificate(
|
||||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
wireMockMiddlewareOptions.X509StoreName,
|
||||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
wireMockMiddlewareOptions.X509StoreLocation,
|
||||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||||
urlDetail.Host)
|
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||||
);
|
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||||
}
|
urlDetail.Host);
|
||||||
else
|
}
|
||||||
{
|
|
||||||
listenOptions.UseHttps();
|
options.ClientCertificateMode = (ClientCertificateMode) wireMockMiddlewareOptions.ClientCertificateMode;
|
||||||
}
|
if (wireMockMiddlewareOptions.AcceptAnyClientCertificate)
|
||||||
|
{
|
||||||
|
options.ClientCertificateValidation = (_, _, _) => true;
|
||||||
|
}
|
||||||
|
});
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
using System.Collections.Generic;
|
using System.Collections.Generic;
|
||||||
using Microsoft.AspNetCore.Hosting;
|
using Microsoft.AspNetCore.Hosting;
|
||||||
using Microsoft.AspNetCore.Server.Kestrel;
|
using Microsoft.AspNetCore.Server.Kestrel;
|
||||||
|
using Microsoft.AspNetCore.Server.Kestrel.Https;
|
||||||
using Microsoft.Extensions.Configuration;
|
using Microsoft.Extensions.Configuration;
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
using WireMock.HttpsCertificate;
|
using WireMock.HttpsCertificate;
|
||||||
@@ -23,21 +24,22 @@ internal partial class AspNetCoreSelfHost
|
|||||||
{
|
{
|
||||||
if (urlDetail.IsHttps)
|
if (urlDetail.IsHttps)
|
||||||
{
|
{
|
||||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
options.UseHttps(new HttpsConnectionFilterOptions
|
||||||
{
|
{
|
||||||
options.UseHttps(CertificateLoader.LoadCertificate(
|
ServerCertificate = wireMockMiddlewareOptions.CustomCertificateDefined
|
||||||
wireMockMiddlewareOptions.X509StoreName,
|
? CertificateLoader.LoadCertificate(
|
||||||
wireMockMiddlewareOptions.X509StoreLocation,
|
wireMockMiddlewareOptions.X509StoreName,
|
||||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
wireMockMiddlewareOptions.X509StoreLocation,
|
||||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||||
urlDetail.Host)
|
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||||
);
|
urlDetail.Host)
|
||||||
}
|
: PublicCertificateHelper.GetX509Certificate2(),
|
||||||
else
|
ClientCertificateMode = (ClientCertificateMode) wireMockMiddlewareOptions.ClientCertificateMode,
|
||||||
{
|
ClientCertificateValidation = wireMockMiddlewareOptions.AcceptAnyClientCertificate
|
||||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
? (_, _, _) => true
|
||||||
}
|
: null,
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,7 @@ using Microsoft.Extensions.DependencyInjection;
|
|||||||
using Stef.Validation;
|
using Stef.Validation;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Owin.Mappers;
|
using WireMock.Owin.Mappers;
|
||||||
|
using WireMock.Services;
|
||||||
using WireMock.Util;
|
using WireMock.Util;
|
||||||
|
|
||||||
namespace WireMock.Owin
|
namespace WireMock.Owin
|
||||||
@@ -66,6 +67,7 @@ namespace WireMock.Owin
|
|||||||
{
|
{
|
||||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||||
|
services.AddSingleton<IRandomizerDoubleBetween0And1, RandomizerDoubleBetween0And1>();
|
||||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||||
|
|
||||||
|
|||||||
@@ -42,6 +42,10 @@ internal interface IWireMockMiddlewareOptions
|
|||||||
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
Action<IServiceCollection>? AdditionalServiceRegistration { get; set; }
|
||||||
|
|
||||||
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
CorsPolicyOptions? CorsPolicyOptions { get; set; }
|
||||||
|
|
||||||
|
ClientCertificateMode ClientCertificateMode { get; set; }
|
||||||
|
|
||||||
|
bool AcceptAnyClientCertificate { get; set; }
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
IFileSystemHandler? FileSystemHandler { get; set; }
|
IFileSystemHandler? FileSystemHandler { get; set; }
|
||||||
|
|||||||
@@ -68,7 +68,21 @@ namespace WireMock.Owin.Mappers
|
|||||||
body = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
body = await BodyParser.ParseAsync(bodyParserSettings).ConfigureAwait(false);
|
||||||
}
|
}
|
||||||
|
|
||||||
return new RequestMessage(options, urlDetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };
|
return new RequestMessage(
|
||||||
|
options,
|
||||||
|
urlDetails,
|
||||||
|
method,
|
||||||
|
clientIP,
|
||||||
|
body,
|
||||||
|
headers,
|
||||||
|
cookies
|
||||||
|
#if USE_ASPNETCORE
|
||||||
|
, await request.HttpContext.Connection.GetClientCertificateAsync()
|
||||||
|
#endif
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DateTime = DateTime.UtcNow
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
|
private static (UrlDetails UrlDetails, string ClientIP) ParseRequest(IRequest request)
|
||||||
|
|||||||
@@ -62,11 +62,11 @@ namespace WireMock.Owin.Mappers
|
|||||||
switch (responseMessage.FaultType)
|
switch (responseMessage.FaultType)
|
||||||
{
|
{
|
||||||
case FaultType.EMPTY_RESPONSE:
|
case FaultType.EMPTY_RESPONSE:
|
||||||
bytes = IsFault(responseMessage) ? new byte[0] : GetNormalBody(responseMessage);
|
bytes = IsFault(responseMessage) ? EmptyArray<byte>.Value : GetNormalBody(responseMessage);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case FaultType.MALFORMED_RESPONSE_CHUNK:
|
case FaultType.MALFORMED_RESPONSE_CHUNK:
|
||||||
bytes = GetNormalBody(responseMessage) ?? new byte[0];
|
bytes = GetNormalBody(responseMessage) ?? EmptyArray<byte>.Value;
|
||||||
if (IsFault(responseMessage))
|
if (IsFault(responseMessage))
|
||||||
{
|
{
|
||||||
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
|
bytes = bytes.Take(bytes.Length / 2).Union(_randomizerBytes.Generate()).ToArray();
|
||||||
@@ -87,7 +87,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
|
|
||||||
case { } typeAsString when typeAsString == typeof(string):
|
case { } typeAsString when typeAsString == typeof(string):
|
||||||
// Note: this case will also match on null
|
// Note: this case will also match on null
|
||||||
int.TryParse(responseMessage.StatusCode as string, out int result);
|
int.TryParse(responseMessage.StatusCode as string, out var result);
|
||||||
response.StatusCode = MapStatusCode(result);
|
response.StatusCode = MapStatusCode(result);
|
||||||
break;
|
break;
|
||||||
|
|
||||||
@@ -130,6 +130,7 @@ namespace WireMock.Owin.Mappers
|
|||||||
switch (responseMessage.BodyData?.DetectedBodyType)
|
switch (responseMessage.BodyData?.DetectedBodyType)
|
||||||
{
|
{
|
||||||
case BodyType.String:
|
case BodyType.String:
|
||||||
|
case BodyType.FormUrlEncoded:
|
||||||
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
return (responseMessage.BodyData.Encoding ?? _utf8NoBom).GetBytes(responseMessage.BodyData.BodyAsString!);
|
||||||
|
|
||||||
case BodyType.Json:
|
case BodyType.Json:
|
||||||
|
|||||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user