Compare commits
59 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fa08d0e617 | ||
|
|
65e7dbfbd3 | ||
|
|
35565f6aa8 | ||
|
|
04d55b00a7 | ||
|
|
63f2715db3 | ||
|
|
3dfee689b5 | ||
|
|
933bd7d046 | ||
|
|
fd62c52669 | ||
|
|
db2caadf70 | ||
|
|
3e0c6cce5f | ||
|
|
8861b8a3f0 | ||
|
|
2363cc1311 | ||
|
|
1f99834ae3 | ||
|
|
8659b352a3 | ||
|
|
8f3aa12086 | ||
|
|
9b64dbcae3 | ||
|
|
33fd383612 | ||
|
|
01d8dc6b86 | ||
|
|
6af127e9f2 | ||
|
|
a3629a4147 | ||
|
|
e222a0a9c3 | ||
|
|
00a6fec7b4 | ||
|
|
47b1d1ab43 | ||
|
|
e7b6e12855 | ||
|
|
94e5e99207 | ||
|
|
37a89cbaa4 | ||
|
|
323d0f9dae | ||
|
|
16e939746a | ||
|
|
85dabc7638 | ||
|
|
f0bddf0604 | ||
|
|
3829a5a7f9 | ||
|
|
37d81aabad | ||
|
|
d1afba5058 | ||
|
|
bc19a1c6b9 | ||
|
|
45713eb0d9 | ||
|
|
4fb455a1b1 | ||
|
|
bde3126f81 | ||
|
|
0d7de47848 | ||
|
|
548fc2c2c8 | ||
|
|
2d95167866 | ||
|
|
b14bc01bf2 | ||
|
|
c104b8beba | ||
|
|
09533f1e3a | ||
|
|
a0fdc002c8 | ||
|
|
e107b5cfca | ||
|
|
5d3cbdbfc6 | ||
|
|
b8cbeb55b9 | ||
|
|
5b083d753e | ||
|
|
99dbb3f9b6 | ||
|
|
6b3bbd8540 | ||
|
|
c465ecdd40 | ||
|
|
1750d4e1ad | ||
|
|
94e176dd85 | ||
|
|
65e01937a6 | ||
|
|
c880dcfc31 | ||
|
|
c02dbeb5ee | ||
|
|
477f3b5cd3 | ||
|
|
b303f7cf89 | ||
|
|
0964eb2c2d |
3
.gitignore
vendored
@@ -252,3 +252,6 @@ paket-files/
|
||||
*.sln.iml
|
||||
|
||||
./report/coverlet/
|
||||
/test/WireMock.Net.Tests/coverage.opencover.xml
|
||||
/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
||||
/test/WireMock.Net.Tests/coverage.net5.0.opencover.xml
|
||||
|
||||
1283
CHANGELOG.md
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.3.1</VersionPrefix>
|
||||
<VersionPrefix>1.3.9</VersionPrefix>
|
||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
@@ -14,6 +14,10 @@
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
<!-- The environment variable `Prerelease` is set in the azure-pipelines.yml file. -->
|
||||
<When Condition=" '$(Prerelease)' != '' ">
|
||||
@@ -23,4 +27,4 @@
|
||||
</PropertyGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.3.1
|
||||
GitHubReleaseNotes --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.3.9
|
||||
12
README.md
@@ -1,6 +1,8 @@
|
||||
# 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).
|
||||
|
||||
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
|
||||
* HTTP response stubbing, matchable on URL/Path, headers, cookies and body content patterns
|
||||
* Library can be used in unit tests and integration tests
|
||||
@@ -21,9 +23,9 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
|
||||
| | |
|
||||
| ***Quality*** | |
|
||||
| **Build Azure** | [](https://stef.visualstudio.com/WireMock.Net/_build/latest?definitionId=7) |
|
||||
| **Quality** | [](https://sonarcloud.io/project/issues?id=wiremock) [](https://www.codefactor.io/repository/github/wiremock-net/wiremock.net) |
|
||||
| **Sonar Bugs** | [](https://sonarcloud.io/project/issues?id=wiremock&resolved=false&types=BUG) [](https://sonarcloud.io/project/issues?id=wiremock&resolved=false&types=CODE_SMELL) |
|
||||
| **Coverage** | [](https://sonarcloud.io/component_measures?id=wiremock&metric=coverage) [](https://codecov.io/gh/WireMock-Net/WireMock.Net) [](https://coveralls.io/github/WireMock-Net/WireMock.Net?branch=master) |
|
||||
| **Quality** | [](https://sonarcloud.io/project/issues?id=WireMock-Net_WireMock.Net) [](https://www.codefactor.io/repository/github/wiremock-net/wiremock.net) |
|
||||
| **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)|
|
||||
|
||||
### NuGet packages
|
||||
|
||||
@@ -57,9 +59,13 @@ WireMock.Net can be used in several ways:
|
||||
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).
|
||||
|
||||
|
||||
@@ -30,6 +30,7 @@ Project("{2150E333-8FDC-42A3-9474-1A3956D46DE8}") = "Solution Items", "Solution
|
||||
CHANGELOG.md = CHANGELOG.md
|
||||
Directory.Build.props = Directory.Build.props
|
||||
GitHubReleaseNotes.txt = GitHubReleaseNotes.txt
|
||||
nuget.config = nuget.config
|
||||
README.md = README.md
|
||||
EndProjectSection
|
||||
EndProject
|
||||
@@ -47,8 +48,6 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.StandAlone.NET
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net452", "examples\WireMock.Net.StandAlone.Net452\WireMock.Net.StandAlone.Net452.csproj", "{668F689E-57B4-422E-8846-C0FF643CA999}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NETCore2", "examples\WireMock.Net.WebApplication\WireMock.Net.WebApplication.NETCore2.csproj", "{049539C1-7A66-4559-AD7A-B1C73B97CBB0}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.Proxy.Net452", "examples\WireMock.Net.Console.Proxy.Net452\WireMock.Net.Console.Proxy.Net452.csproj", "{26433A8F-BF01-4962-97EB-81BFFBB61096}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.StandAlone.Net461", "examples\WireMock.Net.StandAlone.Net461\WireMock.Net.StandAlone.Net461.csproj", "{3C279524-DB73-4DE3-BEF1-F2B2958C9F65}"
|
||||
@@ -69,6 +68,16 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.OpenApiParser.
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.FluentAssertions", "src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj", "{B6269AAC-170A-4346-8B9A-579DED3D9A95}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NETCore2", "examples\WireMock.Net.WebApplication.NETCore2\WireMock.Net.WebApplication.NETCore2.csproj", "{6F38CB3A-6DA1-408A-AECD-E434523C2838}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NETCore3", "examples\WireMock.Net.WebApplication.NETCore3\WireMock.Net.WebApplication.NETCore3.csproj", "{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NETCoreApp3WithCertificate", "examples\WireMock.Net.Console.NETCoreApp3WithCertificate\WireMock.Net.Console.NETCoreApp3WithCertificate.csproj", "{925E421A-1B3F-4202-B48F-734743573A4B}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "dotnet-WireMock", "src\dotnet-WireMock.Net\dotnet-WireMock.csproj", "{40BF24B5-12E6-4610-9489-138798632E28}"
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.Console.NET5", "examples\WireMock.Net.Console.NET5\WireMock.Net.Console.NET5.csproj", "{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -123,10 +132,6 @@ Global
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{049539C1-7A66-4559-AD7A-B1C73B97CBB0}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{26433A8F-BF01-4962-97EB-81BFFBB61096}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
@@ -167,6 +172,26 @@ Global
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{40BF24B5-12E6-4610-9489-138798632E28}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -184,7 +209,6 @@ Global
|
||||
{1995E414-F197-4AB4-90C2-68D806B5AF59} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{10E16614-61CA-48D8-8BDD-664C13913DED} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{668F689E-57B4-422E-8846-C0FF643CA999} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{049539C1-7A66-4559-AD7A-B1C73B97CBB0} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{26433A8F-BF01-4962-97EB-81BFFBB61096} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{3C279524-DB73-4DE3-BEF1-F2B2958C9F65} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{7F0B2446-0363-4720-AF46-F47F83B557DC} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
@@ -195,6 +219,11 @@ Global
|
||||
{D3804228-91F4-4502-9595-39584E5AADAD} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{5C09FB93-1535-4F92-AF26-21E8A061EE4A} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{40BF24B5-12E6-4610-9489-138798632E28} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{3F8CF0AE-5F24-4A54-89E7-A3EE829DB5F8} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
pool:
|
||||
vmImage: 'Ubuntu 16.04'
|
||||
vmImage: 'Ubuntu-latest'
|
||||
|
||||
variables:
|
||||
buildConfiguration: 'Release'
|
||||
|
||||
@@ -1,91 +1,136 @@
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
variables:
|
||||
Prerelease: 'ci'
|
||||
buildId: "1$(Build.BuildId)"
|
||||
buildProjects: '**/src/**/*.csproj'
|
||||
|
||||
steps:
|
||||
# Print buildId
|
||||
- script: |
|
||||
echo "BuildId = $(buildId)"
|
||||
displayName: 'Print buildId'
|
||||
jobs:
|
||||
- job: Linux_Build_Test_SonarCloud
|
||||
|
||||
# Install Tools (SonarScanner)
|
||||
- script: |
|
||||
dotnet tool install --global dotnet-sonarscanner
|
||||
displayName: Install Tools (SonarScanner)
|
||||
pool:
|
||||
vmImage: 'Ubuntu-latest'
|
||||
|
||||
# Begin SonarScanner
|
||||
# See also
|
||||
# - https://docs.microsoft.com/en-us/dotnet/core/tools/global-tools, else you get this error: `Since you just installed the .NET Core SDK, you will need to reopen the Command Prompt window before running the tool you installed.`
|
||||
# - https://github.com/dotnet/cli/issues/8368
|
||||
# - https://github.com/Microsoft/vsts-tasks/issues/8291
|
||||
#
|
||||
- script: |
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner begin /k:"wiremock" /o:"stefh-github" /d:sonar.host.url="https://sonarcloud.io" /d:sonar.login="$(SONAR_TOKEN)" /v:"$(buildId)" /d:sonar.cs.opencover.reportsPaths="**\coverage.opencover.xml"
|
||||
displayName: Begin SonarScanner
|
||||
condition: and(succeeded(), eq(variables['RUN_SONAR'], 'yes'))
|
||||
steps:
|
||||
- script: |
|
||||
echo "BuildId = $(buildId)"
|
||||
displayName: 'Print buildId'
|
||||
|
||||
# Build source, tests and run tests for net452 and netcoreapp3.1 (with coverage)
|
||||
- script: |
|
||||
dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --framework net452
|
||||
dotnet test ./test/WireMock.Net.Tests/WireMock.Net.Tests.csproj --configuration Debug --framework netcoreapp3.1 --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover
|
||||
displayName: 'Build source, tests and run tests for net452 and netcoreapp3.1 (with coverage)'
|
||||
- task: PowerShell@2
|
||||
displayName: "Use JDK11 by default"
|
||||
inputs:
|
||||
targetType: 'inline'
|
||||
script: |
|
||||
$jdkPath = $env:JAVA_HOME_11_X64
|
||||
Write-Host "##vso[task.setvariable variable=JAVA_HOME]$jdkPath"
|
||||
|
||||
# End SonarScanner
|
||||
- script: |
|
||||
%USERPROFILE%\.dotnet\tools\dotnet-sonarscanner end /d:sonar.login="$(SONAR_TOKEN)"
|
||||
displayName: End SonarScanner
|
||||
condition: and(succeeded(), eq(variables['RUN_SONAR'], 'yes'))
|
||||
- script: |
|
||||
dotnet dev-certs https --trust || true
|
||||
displayName: 'dotnet dev-certs https'
|
||||
|
||||
- task: SonarCloudPrepare@1
|
||||
displayName: 'Prepare analysis on SonarCloud'
|
||||
inputs:
|
||||
SonarCloud: SonarCloud
|
||||
organization: wiremock-net
|
||||
projectKey: 'WireMock-Net_WireMock.Net'
|
||||
projectName: 'WireMock.Net'
|
||||
extraProperties: |
|
||||
sonar.cs.opencover.reportsPaths=**/coverage.netcoreapp3.1.opencover.xml
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Build Unit tests'
|
||||
inputs:
|
||||
command: 'build'
|
||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||
arguments: '--configuration Debug --framework netcoreapp3.1'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Execute Unit tests'
|
||||
inputs:
|
||||
command: 'test'
|
||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||
arguments: '--no-build --configuration Debug --framework netcoreapp3.1 --collect:"XPlat Code Coverage" --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover'
|
||||
|
||||
- task: SonarCloudAnalyze@1
|
||||
displayName: 'SonarCloud: Run Code Analysis'
|
||||
|
||||
- task: SonarCloudPublish@1
|
||||
displayName: 'SonarCloud: Publish Quality Gate Result'
|
||||
|
||||
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
|
||||
displayName: 'WhiteSource Bolt'
|
||||
condition: and(succeeded(), eq(variables['RUN_WHITESOURCE'], 'yes'))
|
||||
|
||||
- script: |
|
||||
bash <(curl https://codecov.io/bash) -t $(CODECOV_TOKEN) -f ./test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml
|
||||
displayName: 'codecov'
|
||||
|
||||
- task: PublishTestResults@2
|
||||
condition: and(succeeded(), eq(variables['PUBLISH_TESTRESULTS'], 'yes'))
|
||||
inputs:
|
||||
testRunner: VSTest
|
||||
testResultsFiles: '**/*.trx'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish coverage file
|
||||
inputs:
|
||||
PathtoPublish: '/home/vsts/work/1/s/test/WireMock.Net.Tests/coverage.netcoreapp3.1.opencover.xml'
|
||||
|
||||
- task: whitesource.ws-bolt.bolt.wss.WhiteSource Bolt@19
|
||||
displayName: 'WhiteSource Bolt'
|
||||
condition: and(succeeded(), eq(variables['RUN_WHITESOURCE'], 'yes'))
|
||||
- job: Windows_Build_Test
|
||||
dependsOn: Linux_Build_Test_SonarCloud
|
||||
|
||||
# Upload coverage to codecov.io
|
||||
- script: |
|
||||
%USERPROFILE%\.nuget\packages\codecov\1.10.0\tools\codecov.exe -f "./test/WireMock.Net.Tests/coverage.opencover.xml" -t $(CODECOV_TOKEN)
|
||||
displayName: Upload coverage to codecov.io
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
# https://github.com/microsoft/azure-pipelines-tasks/issues/12212
|
||||
- task: PublishTestResults@2
|
||||
condition: and(succeeded(), eq(variables['PUBLISH_TESTRESULTS'], 'yes'))
|
||||
inputs:
|
||||
testRunner: VSTest
|
||||
testResultsFiles: '**/*.trx'
|
||||
steps:
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Build Unit tests'
|
||||
inputs:
|
||||
command: 'build'
|
||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||
arguments: '--configuration Debug --framework netcoreapp3.1'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: 'Execute Unit tests'
|
||||
inputs:
|
||||
command: 'test'
|
||||
projects: './test/WireMock.Net.Tests/WireMock.Net.Tests.csproj'
|
||||
arguments: '--no-build --configuration Debug --framework netcoreapp3.1 --collect:"XPlat Code Coverage" --logger trx /p:CollectCoverage=true /p:CoverletOutputFormat=opencover'
|
||||
|
||||
- job: Windows_Release_to_MyGet
|
||||
dependsOn: Windows_Build_Test
|
||||
|
||||
# Based on https://whereslou.com/2018/09/versioning-and-publishing-nuget-packages-automatically-using-azure-devops-pipelines/
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Build Release
|
||||
inputs:
|
||||
command: 'build'
|
||||
arguments: /p:Configuration=Release # https://github.com/MicrosoftDocs/vsts-docs/issues/1976
|
||||
projects: $(buildProjects)
|
||||
pool:
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Pack
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: pack
|
||||
configuration: 'Release'
|
||||
packagesToPack: $(buildProjects)
|
||||
nobuild: true
|
||||
packDirectory: '$(Build.ArtifactStagingDirectory)/packages'
|
||||
verbosityPack: 'normal'
|
||||
steps:
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Build Release
|
||||
inputs:
|
||||
command: 'build'
|
||||
arguments: /p:Configuration=Release
|
||||
projects: $(buildProjects)
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifacts
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
# https://github.com/NuGet/Home/issues/8148
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Push to MyGet
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: custom
|
||||
custom: nuget
|
||||
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg -n true -s https://www.myget.org/F/wiremock-net/api/v3/index.json -k $(MyGetKey)
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Pack
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: pack
|
||||
configuration: 'Release'
|
||||
packagesToPack: $(buildProjects)
|
||||
nobuild: true
|
||||
packDirectory: '$(Build.ArtifactStagingDirectory)/packages'
|
||||
verbosityPack: 'normal'
|
||||
|
||||
- task: PublishBuildArtifacts@1
|
||||
displayName: Publish Artifacts
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
PathtoPublish: '$(Build.ArtifactStagingDirectory)'
|
||||
|
||||
- task: DotNetCoreCLI@2
|
||||
displayName: Push to MyGet
|
||||
condition: and(succeeded(), ne(variables['Build.Reason'], 'PullRequest')) # Do not run for PullRequests
|
||||
inputs:
|
||||
command: custom
|
||||
custom: nuget
|
||||
arguments: push $(Build.ArtifactStagingDirectory)\packages\*.nupkg -n true -s https://www.myget.org/F/wiremock-net/api/v3/index.json -k $(MyGetKey)
|
||||
@@ -1,5 +1,5 @@
|
||||
pool:
|
||||
vmImage: 'vs2017-win2016'
|
||||
vmImage: 'windows-2019'
|
||||
|
||||
variables:
|
||||
Prerelease: ''
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Include="..\WireMock.Net.Console.Net452.Classic\MainApp.cs" Link="MainApp.cs" />
|
||||
<Compile Include="..\WireMock.Net.Console.Net452.Classic\CustomFileSystemFileHandler.cs" Link="CustomFileSystemFileHandler.cs" />
|
||||
<Compile Include="..\WireMock.Net.Console.NETCoreApp\Program.cs" Link="Program.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Include="__admin\mappings\*.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Remove="__admin\mappings\1.cs" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="__admin\mappings\array.json" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.1.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<!--<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="3.4.0" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="log4net.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="nlog.config">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\791a3f31-6946-4ce7-8e6f-0237c7443275.json">
|
||||
<CopyToOutputDirectory>Never</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
1
examples/WireMock.Net.Console.NET5/__admin/mappings/1.cs
Normal file
@@ -0,0 +1 @@
|
||||
// C# Hello
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/static/mapping"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "body": "static mapping" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json",
|
||||
"Test-X": [ "test 1", "test 2" ]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,29 @@
|
||||
{
|
||||
"Guid": "791a3f31-6946-4ce7-8e6f-0237c7443275",
|
||||
"Title": "",
|
||||
"Priority": 0,
|
||||
"Request": {
|
||||
"Path": "/proxy-google-test-post",
|
||||
"Methods": [
|
||||
"post"
|
||||
],
|
||||
"Body": {}
|
||||
},
|
||||
"Response": {
|
||||
"StatusCode": 404,
|
||||
"Body": "<!DOCTYPE html>\n<html lang=en>\n <meta charset=utf-8>\n <meta name=viewport content=\"initial-scale=1, minimum-scale=1, width=device-width\">\n <title>Error 404 (Not Found)!!1</title>\n <style>\n *{margin:0;padding:0}html,code{font:15px/22px arial,sans-serif}html{background:#fff;color:#222;padding:15px}body{margin:7% auto 0;max-width:390px;min-height:180px;padding:30px 0 15px}* > body{background:url(//www.google.com/images/errors/robot.png) 100% 5px no-repeat;padding-right:205px}p{margin:11px 0 22px;overflow:hidden}ins{color:#777;text-decoration:none}a img{border:0}@media screen and (max-width:772px){body{background:none;margin-top:0;max-width:none;padding-right:0}}#logo{background:url(//www.google.com/images/branding/googlelogo/1x/googlelogo_color_150x54dp.png) no-repeat;margin-left:-5px}@media only screen and (min-resolution:192dpi){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat 0% 0%/100% 100%;-moz-border-image:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) 0}}@media only screen and (-webkit-min-device-pixel-ratio:2){#logo{background:url(//www.google.com/images/branding/googlelogo/2x/googlelogo_color_150x54dp.png) no-repeat;-webkit-background-size:100% 100%}}#logo{display:inline-block;height:54px;width:150px}\n </style>\n <a href=//www.google.com/><span id=logo aria-label=Google></span></a>\n <p><b>404.</b> <ins>That’s an error.</ins>\n <p>The requested URL <code>/proxy-google-test-post</code> was not found on this server. <ins>That’s all we know.</ins>\n",
|
||||
"BodyAsBytes": "PCFET0NUWVBFIGh0bWw+CjxodG1sIGxhbmc9ZW4+CiAgPG1ldGEgY2hhcnNldD11dGYtOD4KICA8bWV0YSBuYW1lPXZpZXdwb3J0IGNvbnRlbnQ9ImluaXRpYWwtc2NhbGU9MSwgbWluaW11bS1zY2FsZT0xLCB3aWR0aD1kZXZpY2Utd2lkdGgiPgogIDx0aXRsZT5FcnJvciA0MDQgKE5vdCBGb3VuZCkhITE8L3RpdGxlPgogIDxzdHlsZT4KICAgICp7bWFyZ2luOjA7cGFkZGluZzowfWh0bWwsY29kZXtmb250OjE1cHgvMjJweCBhcmlhbCxzYW5zLXNlcmlmfWh0bWx7YmFja2dyb3VuZDojZmZmO2NvbG9yOiMyMjI7cGFkZGluZzoxNXB4fWJvZHl7bWFyZ2luOjclIGF1dG8gMDttYXgtd2lkdGg6MzkwcHg7bWluLWhlaWdodDoxODBweDtwYWRkaW5nOjMwcHggMCAxNXB4fSogPiBib2R5e2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2Vycm9ycy9yb2JvdC5wbmcpIDEwMCUgNXB4IG5vLXJlcGVhdDtwYWRkaW5nLXJpZ2h0OjIwNXB4fXB7bWFyZ2luOjExcHggMCAyMnB4O292ZXJmbG93OmhpZGRlbn1pbnN7Y29sb3I6Izc3Nzt0ZXh0LWRlY29yYXRpb246bm9uZX1hIGltZ3tib3JkZXI6MH1AbWVkaWEgc2NyZWVuIGFuZCAobWF4LXdpZHRoOjc3MnB4KXtib2R5e2JhY2tncm91bmQ6bm9uZTttYXJnaW4tdG9wOjA7bWF4LXdpZHRoOm5vbmU7cGFkZGluZy1yaWdodDowfX0jbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzF4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7bWFyZ2luLWxlZnQ6LTVweH1AbWVkaWEgb25seSBzY3JlZW4gYW5kIChtaW4tcmVzb2x1dGlvbjoxOTJkcGkpeyNsb2dve2JhY2tncm91bmQ6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIG5vLXJlcGVhdCAwJSAwJS8xMDAlIDEwMCU7LW1vei1ib3JkZXItaW1hZ2U6dXJsKC8vd3d3Lmdvb2dsZS5jb20vaW1hZ2VzL2JyYW5kaW5nL2dvb2dsZWxvZ28vMngvZ29vZ2xlbG9nb19jb2xvcl8xNTB4NTRkcC5wbmcpIDB9fUBtZWRpYSBvbmx5IHNjcmVlbiBhbmQgKC13ZWJraXQtbWluLWRldmljZS1waXhlbC1yYXRpbzoyKXsjbG9nb3tiYWNrZ3JvdW5kOnVybCgvL3d3dy5nb29nbGUuY29tL2ltYWdlcy9icmFuZGluZy9nb29nbGVsb2dvLzJ4L2dvb2dsZWxvZ29fY29sb3JfMTUweDU0ZHAucG5nKSBuby1yZXBlYXQ7LXdlYmtpdC1iYWNrZ3JvdW5kLXNpemU6MTAwJSAxMDAlfX0jbG9nb3tkaXNwbGF5OmlubGluZS1ibG9jaztoZWlnaHQ6NTRweDt3aWR0aDoxNTBweH0KICA8L3N0eWxlPgogIDxhIGhyZWY9Ly93d3cuZ29vZ2xlLmNvbS8+PHNwYW4gaWQ9bG9nbyBhcmlhLWxhYmVsPUdvb2dsZT48L3NwYW4+PC9hPgogIDxwPjxiPjQwNC48L2I+IDxpbnM+VGhhdOKAmXMgYW4gZXJyb3IuPC9pbnM+CiAgPHA+VGhlIHJlcXVlc3RlZCBVUkwgPGNvZGU+L3Byb3h5LWdvb2dsZS10ZXN0LXBvc3Q8L2NvZGU+IHdhcyBub3QgZm91bmQgb24gdGhpcyBzZXJ2ZXIuICA8aW5zPlRoYXTigJlzIGFsbCB3ZSBrbm93LjwvaW5zPgo=",
|
||||
"BodyEncoding": {
|
||||
"CodePage": 65001,
|
||||
"EncodingName": "Unicode (UTF-8)",
|
||||
"WebName": "utf-8"
|
||||
},
|
||||
"UseTransformer": false,
|
||||
"Headers": {
|
||||
"Date": "Wed, 27 Oct 2017 18:57:40 GMT",
|
||||
"Alt-Svc": "quic=\":443\"; ma=2592000; v=\"39,38,37,35\"",
|
||||
"Referrer-Policy": "no-referrer",
|
||||
"Connection": "close"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
{
|
||||
"Guid": "873d495f-940e-4b86-a1f4-4f0fc7be8b8b",
|
||||
"Priority": 4,
|
||||
"Request": {
|
||||
"Path": {},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"StatusCode": 200,
|
||||
"BodyDestination": "SameAsSource",
|
||||
"Body": "NO PATH OR URL",
|
||||
"UseTransformer": false,
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,22 @@
|
||||
{
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/bodyasfilexmltest",
|
||||
"IgnoreCase": false
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"StatusCode": 200,
|
||||
"Headers": {"Content-Type": "application/xml"},
|
||||
"BodyAsFile": "MyXmlResponse.xml",
|
||||
"UseTransformer": false
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,3 @@
|
||||
<xml>
|
||||
<hello>world</hello>
|
||||
</xml>
|
||||
@@ -0,0 +1,46 @@
|
||||
[
|
||||
{
|
||||
"Title": "1",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/mappings_static_1"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "result": "mappings static_1" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
"Title": "2",
|
||||
"Request": {
|
||||
"Path": {
|
||||
"Matchers": [
|
||||
{
|
||||
"Name": "WildcardMatcher",
|
||||
"Pattern": "/mappings_static_2"
|
||||
}
|
||||
]
|
||||
},
|
||||
"Methods": [
|
||||
"get"
|
||||
]
|
||||
},
|
||||
"Response": {
|
||||
"BodyAsJson": { "result": "mappings static_2" },
|
||||
"Headers": {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
}
|
||||
}
|
||||
]
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.0.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.1.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<!--<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="3.4.0" />-->
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.Console.NETCoreApp3WithCertificate
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string url = "https://localhost:8433/";
|
||||
|
||||
var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Urls = new[] { url },
|
||||
StartAdminInterface = true,
|
||||
Logger = new WireMockConsoleLogger(),
|
||||
CertificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
X509StoreName = "My",
|
||||
X509StoreLocation = "CurrentUser",
|
||||
X509StoreThumbprintOrSubjectName = "FE16586076A8B3F3E2F1466803A6C4C7CA35455B"
|
||||
|
||||
// X509CertificateFilePath = "example.pfx",
|
||||
// X509CertificatePassword = "wiremock"
|
||||
}
|
||||
|
||||
});
|
||||
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.StandAlone\WireMock.Net.StandAlone.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="example.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEsDCCApigAwIBAgIQJbH6hSGKdoFI0B7qCIOK7jANBgkqhkiG9w0BAQUFADAU
|
||||
MRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMjAxMDMwMjMwMDAwWhcNMzAxMTA2MjMw
|
||||
MDAwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4IC
|
||||
DwAwggIKAoICAQCl5fQSrRgT3Q6WoULR98Y+rrDWtTTgVpbLU04G0hLZ4yUeP7Wa
|
||||
yuVbvx7zX8XT4lA8Hu5T/GG91U077JcSSEjnPBFsh4hE7FkRoSYIEW6BFG7D7eUG
|
||||
dGHnDV8UkSRQ97LJPyjXuHVDJzNDJ9xQGMzOZ4n8vQ7SEKBw9hRG2ugkP5b2jVIN
|
||||
e1E549tq2jnIVpKCZ4+prf64ZLsaokX7VHe+b/CW3GoAqUUaUjdTpAQ7LpypJuFz
|
||||
415enOrKQe+UEBdqhGlgcC/O/Bw0uq4qVk+NNe5DEINVwoYs9XjNdzxuIkkAtcCt
|
||||
avTEzhHf8zWYLb5Nt2DIOcRGVELvRhsBX4um5f7dOGzMbXzBfUdjkP2O4hi6crhm
|
||||
Hba5bNkj4Zw2EHR9Xua3nadGCj22z0vpMKP2gXdFVnxFqQlaUWBLtwwN9p6tCQHl
|
||||
kU7wypvOHUsMa2Ojg5eZP4RpYFvZG3kkc9zTZCSakgw2n0ampBbvxPP11/AYIXtz
|
||||
HKu3CKcpjVQ+lE0DAU/Mm77QJ24TMbXmAydwCf1UCdFbDUZhdM9lspHvA0J9eiCv
|
||||
LOE94BrpVKuZ6TrAW0LZjAmBnkqYQAewhTW7GSgARE+QQcwfyu03Ck7id3Zt4FeQ
|
||||
sQDo0NNj7zQOy3Y1GK0ZYAVZv/GUeHMkxpClSWPoub/f5SJ4YzD5Il0cQQIDAQAB
|
||||
MA0GCSqGSIb3DQEBBQUAA4ICAQBd91xfUepnWcKwmupie2h1CAAQZEunyW78i++t
|
||||
evABfBu0TgV4s6Xe0umFv9V4r+O+rrF3ddSudbSOPBEb0Ooe+e3YGlNk1JrI1EEn
|
||||
fhb0YI8bMfBNpl85yNqxgByra7JF2mG4qbAnjrCs/PZkXo/34N29SY6dyZ7mffR3
|
||||
r/l01Rdm3ogRwGkiMUeKb3iGwLUy1T55svuI3Zc13N+NJT1s9NqpwWeK/jFK/WRN
|
||||
5Hi9W3DmlGCYAwFPCyBaQagxpGuGIpNsU0hKp86W5EvJpBpmCihfwlydH8ZbkHJ9
|
||||
jx2UDgTCaDzmaiKysiTP2HHDBsReL4tjakBksa9jkTfy5ajB53F3aUVs4jvTA46L
|
||||
w8wcAJlRPBz5siBrv4CH/0lBMyNeYzuqmDY3ulF4IMKNb5Kk9Ye4Pt0474z50A4v
|
||||
fSah+9iwI/mubaJ5tK522AtWtUoOIAswIwpDQyNeJPOggyzT2Y2OYZdGuFAoMYuq
|
||||
ZD58k4Yo+vky9K88l8NuzNJJvtgTKtT+/9qfMucxFmnvwbKEEULP3sw1FUKkPtM4
|
||||
f242FIV/XnOeloDmhGGeTB7aODB+gGCvgmOH92njjUEIv+SnYQkflQaRhhyNIACi
|
||||
ZvWlP/96H+X4fUG5kVNBHY021ZWmurUDqVxWUaswg63+DfsZcYtt6wgxiAN4ssXG
|
||||
wLnLPw==
|
||||
-----END CERTIFICATE-----
|
||||
@@ -12,6 +12,7 @@ using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WireMock.Net.ConsoleApplication
|
||||
{
|
||||
@@ -249,6 +250,13 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithProxy("http://www.google.com")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithHeader("ProxyThisHttps", "true")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithProxy("https://www.google.com")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/bodyasbytes.png")
|
||||
.UsingGet())
|
||||
@@ -521,9 +529,29 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
|
||||
server
|
||||
.Given(Request.Create().WithPath("/random200or505").UsingGet())
|
||||
.RespondWith(Response.Create().WithCallback(request => new ResponseMessage
|
||||
.RespondWith(Response.Create().WithCallback(request =>
|
||||
{
|
||||
StatusCode = new Random().Next(1, 100) == 1 ? 504 : 200
|
||||
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
||||
return new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData { BodyAsString = "random200or505:" + code, DetectedBodyType = Types.BodyType.String },
|
||||
StatusCode = code
|
||||
};
|
||||
}));
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/random200or505async").UsingGet())
|
||||
.RespondWith(Response.Create().WithCallback(async request =>
|
||||
{
|
||||
await Task.Delay(1);
|
||||
|
||||
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
||||
|
||||
return new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData { BodyAsString = "random200or505async:" + code, DetectedBodyType = Types.BodyType.String },
|
||||
StatusCode = code
|
||||
};
|
||||
}));
|
||||
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
@@ -13,16 +15,26 @@ namespace WireMock.Net.Console.Proxy.NETCoreApp
|
||||
Urls = new[] { "http://localhost:9091/", "https://localhost:9443/" },
|
||||
StartAdminInterface = true,
|
||||
ReadStaticMappings = false,
|
||||
ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
{
|
||||
Url = "https://www.google.com",
|
||||
//ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
|
||||
SaveMapping = true,
|
||||
SaveMappingToFile = false,
|
||||
ExcludedHeaders = new [] { "dnt", "Content-Length" }
|
||||
}
|
||||
//ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
//{
|
||||
// Url = "https://www.google.com",
|
||||
// //ClientX509Certificate2ThumbprintOrSubjectName = "www.yourclientcertname.com OR yourcertificatethumbprint (only if the service you're proxying to requires it)",
|
||||
// SaveMapping = true,
|
||||
// SaveMappingToFile = false,
|
||||
// ExcludedHeaders = new [] { "dnt", "Content-Length" }
|
||||
//}
|
||||
});
|
||||
|
||||
server
|
||||
.Given(Request.Create().UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithProxy(new ProxyAndRecordSettings
|
||||
{
|
||||
Url = "http://postman-echo.com/post",
|
||||
SaveMapping = true,
|
||||
SaveMappingToFile = true
|
||||
}));
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp1.1</TargetFramework>
|
||||
<TargetFramework>net5.0</TargetFramework>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ using System.Threading;
|
||||
using log4net;
|
||||
using log4net.Config;
|
||||
using log4net.Repository;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
@@ -23,11 +25,21 @@ namespace WireMock.Net.StandAlone.NETCoreApp
|
||||
{
|
||||
XmlConfigurator.Configure(LogRepository, new FileInfo("log4net.config"));
|
||||
|
||||
var settings = WireMockServerSettingsParser.ParseArguments(args, new WireMockLog4NetLogger());
|
||||
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()
|
||||
// .UsingAnyMethod())
|
||||
// .RespondWith(Response.Create()
|
||||
// .WithProxy("https://www.google.com"));
|
||||
|
||||
Console.WriteLine($"{DateTime.UtcNow} Press Ctrl+C to shut down");
|
||||
|
||||
Console.CancelKeyPress += (s, e) =>
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
"profiles": {
|
||||
"WireMock.Net.StandAlone.NETCoreApp": {
|
||||
"commandName": "Project",
|
||||
"commandLineArgs": "--Port 9091 --WireMockLogger WireMockConsoleLogger"
|
||||
"commandLineArgs": "--Urls https://localhost:10080 --WireMockLogger WireMockConsoleLogger"
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -2,7 +2,7 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFrameworks>netcoreapp2.1</TargetFrameworks>
|
||||
<TargetFrameworks>netcoreapp3.1</TargetFrameworks>
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
<StartupObject>WireMock.Net.StandAlone.NETCoreApp.Program</StartupObject>
|
||||
</PropertyGroup>
|
||||
|
||||
@@ -1 +0,0 @@
|
||||
dotnet run --framework netcoreapp1.1
|
||||
@@ -1 +0,0 @@
|
||||
dotnet run --framework netcoreapp2.0
|
||||
@@ -1 +0,0 @@
|
||||
dotnet run --framework netcoreapp2.1
|
||||
@@ -13,13 +13,15 @@ namespace WireMock.Net.StandAlone.Net452
|
||||
{
|
||||
XmlConfigurator.Configure(new FileInfo("log4net.config"));
|
||||
|
||||
var settings = WireMockServerSettingsParser.ParseArguments(args);
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
WireMockServer.Start(settings);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server");
|
||||
Console.ReadKey();
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
|
||||
{
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
WireMockServer.Start(settings);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,13 +9,15 @@ namespace WireMock.Net.StandAlone.Net461
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
var settings = WireMockServerSettingsParser.ParseArguments(args);
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
WireMockServer.Start(settings);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server");
|
||||
Console.ReadKey();
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings))
|
||||
{
|
||||
settings.Logger.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
WireMockServer.Start(settings);
|
||||
|
||||
Console.WriteLine("Press any key to stop the server");
|
||||
Console.ReadKey();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,22 +1,22 @@
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public class App
|
||||
{
|
||||
private readonly IWireMockService _service;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public App(IWireMockService service, ILogger logger)
|
||||
{
|
||||
_service = service;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
_logger.LogInformation("WireMock.Net App running");
|
||||
_service.Run();
|
||||
}
|
||||
}
|
||||
using Microsoft.Extensions.Logging;
|
||||
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public class App
|
||||
{
|
||||
private readonly IWireMockService _service;
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public App(IWireMockService service, ILogger logger)
|
||||
{
|
||||
_service = service;
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
_logger.LogInformation("WireMock.Net App running");
|
||||
_service.Run();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,7 @@
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public interface IWireMockService
|
||||
{
|
||||
void Run();
|
||||
}
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public interface IWireMockService
|
||||
{
|
||||
void Run();
|
||||
}
|
||||
}
|
||||
@@ -1,38 +1,38 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iis": {
|
||||
"applicationUrl": "http://localhost//wiremock",
|
||||
"sslPort": 0
|
||||
},
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:56513/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"WireMock.Net.WebApplication": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:56514/"
|
||||
},
|
||||
"IIS": {
|
||||
"commandName": "IIS",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "development"
|
||||
}
|
||||
}
|
||||
}
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iis": {
|
||||
"applicationUrl": "http://localhost//wiremock",
|
||||
"sslPort": 0
|
||||
},
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:56513/",
|
||||
"sslPort": 0
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"WireMock.Net.WebApplication": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:56514/"
|
||||
},
|
||||
"IIS": {
|
||||
"commandName": "IIS",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
{
|
||||
"version": "1.0",
|
||||
"defaultProvider": "cdnjs",
|
||||
"libraries": []
|
||||
{
|
||||
"version": "1.0",
|
||||
"defaultProvider": "cdnjs",
|
||||
"libraries": []
|
||||
}
|
||||
@@ -1,21 +1,21 @@
|
||||
# Running in IIS
|
||||
|
||||
Follow these links / steps:
|
||||
* https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS
|
||||
* https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/development-time-iis-support?view=aspnetcore-2.1
|
||||
* Create a `web.config` file
|
||||
|
||||
## IIS Sites
|
||||

|
||||
|
||||
## App Pool settings
|
||||

|
||||
|
||||
## Publish Profiles
|
||||
Two example publish profiles are created:
|
||||
* [IIS Localhost 1](./Properties/PublishProfiles/IIS%20Localhost%201.pubxml)
|
||||
* [IIS Localhost 2](./Properties/PublishProfiles/IIS%20Localhost%202.pubxml)
|
||||
|
||||
## Debugging
|
||||
Select the debug "IIS" if you want to debug in IIS.
|
||||

|
||||
# Running in IIS
|
||||
|
||||
Follow these links / steps:
|
||||
* https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS
|
||||
* https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/development-time-iis-support?view=aspnetcore-2.1
|
||||
* Create a `web.config` file
|
||||
|
||||
## IIS Sites
|
||||

|
||||
|
||||
## App Pool settings
|
||||

|
||||
|
||||
## Publish Profiles
|
||||
Two example publish profiles are created:
|
||||
* [IIS Localhost 1](./Properties/PublishProfiles/IIS%20Localhost%201.pubxml)
|
||||
* [IIS Localhost 2](./Properties/PublishProfiles/IIS%20Localhost%202.pubxml)
|
||||
|
||||
## Debugging
|
||||
Select the debug "IIS" if you want to debug in IIS.
|
||||

|
||||
|
Before Width: | Height: | Size: 7.9 KiB After Width: | Height: | Size: 7.9 KiB |
|
Before Width: | Height: | Size: 36 KiB After Width: | Height: | Size: 36 KiB |
|
Before Width: | Height: | Size: 14 KiB After Width: | Height: | Size: 14 KiB |
@@ -1,12 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModule" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
|
||||
</system.webServer>
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
28
examples/WireMock.Net.WebApplication.NETCore3/App.cs
Normal file
@@ -0,0 +1,28 @@
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public class App : IHostedService
|
||||
{
|
||||
private readonly IWireMockService _service;
|
||||
|
||||
public App(IWireMockService service)
|
||||
{
|
||||
_service = service;
|
||||
}
|
||||
|
||||
public Task StartAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_service.Start();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
|
||||
public Task StopAsync(CancellationToken cancellationToken)
|
||||
{
|
||||
_service.Stop();
|
||||
return Task.CompletedTask;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public interface IWireMockService
|
||||
{
|
||||
void Start();
|
||||
|
||||
void Stop();
|
||||
}
|
||||
}
|
||||
30
examples/WireMock.Net.WebApplication.NETCore3/Program.cs
Normal file
@@ -0,0 +1,30 @@
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public class Program
|
||||
{
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
CreateHostBuilder(args).Build().Run();
|
||||
}
|
||||
|
||||
private static IHostBuilder CreateHostBuilder(string[] args)
|
||||
=> Host.CreateDefaultBuilder(args)
|
||||
.ConfigureServices((host, services) => ConfigureServices(services, host.Configuration));
|
||||
|
||||
private static void ConfigureServices(IServiceCollection services, IConfiguration configuration)
|
||||
{
|
||||
services.AddLogging(logging => logging.AddConsole().AddDebug());
|
||||
|
||||
services.AddTransient<IWireMockService, WireMockService>();
|
||||
services.Configure<WireMockServerSettings>(configuration.GetSection("WireMockServerSettings"));
|
||||
|
||||
services.AddHostedService<App>();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,38 @@
|
||||
{
|
||||
"iisSettings": {
|
||||
"windowsAuthentication": false,
|
||||
"anonymousAuthentication": true,
|
||||
"iis": {
|
||||
"applicationUrl": "http://localhost//wiremock",
|
||||
"sslPort": 0
|
||||
},
|
||||
"iisExpress": {
|
||||
"applicationUrl": "http://localhost:56513/",
|
||||
"sslPort": 44304
|
||||
}
|
||||
},
|
||||
"profiles": {
|
||||
"IIS Express": {
|
||||
"commandName": "IISExpress",
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
}
|
||||
},
|
||||
"WireMock.Net.WebApplication": {
|
||||
"commandName": "Project",
|
||||
"launchBrowser": true,
|
||||
"launchUrl": "__admin/settings",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "Development"
|
||||
},
|
||||
"applicationUrl": "http://localhost:56514/"
|
||||
},
|
||||
"IIS": {
|
||||
"commandName": "IIS",
|
||||
"environmentVariables": {
|
||||
"ASPNETCORE_ENVIRONMENT": "development"
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,32 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk.Web">
|
||||
|
||||
<PropertyGroup>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<RuntimeIdentifiers>win10-x64</RuntimeIdentifiers>
|
||||
<StartupObject>WireMock.Net.WebApplication.Program</StartupObject>
|
||||
<AssemblyName>WireMock.Net.WebApplication</AssemblyName>
|
||||
<RootNamespace>WireMock.Net.WebApplication</RootNamespace>
|
||||
<UserSecretsId>efcf4a18-fd7c-4622-1111-336d65290599</UserSecretsId>
|
||||
<AspNetCoreHostingModel>OutOfProcess</AspNetCoreHostingModel>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<!--<DotNetCliToolReference Include="Microsoft.VisualStudio.Web.CodeGeneration.Tools" Version="2.0.4" />-->
|
||||
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Console" Version="3.1.8" />
|
||||
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Content Update="appsettings.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</Content>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.Options;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Admin.Requests;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.WebApplication
|
||||
{
|
||||
public class WireMockService : IWireMockService
|
||||
{
|
||||
private WireMockServer _server;
|
||||
private readonly ILogger _logger;
|
||||
private readonly WireMockServerSettings _settings;
|
||||
|
||||
private class Logger : IWireMockLogger
|
||||
{
|
||||
private readonly ILogger _logger;
|
||||
|
||||
public Logger(ILogger logger)
|
||||
{
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public void Debug(string formatString, params object[] args)
|
||||
{
|
||||
_logger.LogDebug(formatString, args);
|
||||
}
|
||||
|
||||
public void Info(string formatString, params object[] args)
|
||||
{
|
||||
_logger.LogInformation(formatString, args);
|
||||
}
|
||||
|
||||
public void Warn(string formatString, params object[] args)
|
||||
{
|
||||
_logger.LogWarning(formatString, args);
|
||||
}
|
||||
|
||||
public void Error(string formatString, params object[] args)
|
||||
{
|
||||
_logger.LogError(formatString, args);
|
||||
}
|
||||
|
||||
public void DebugRequestResponse(LogEntryModel logEntryModel, bool isAdminrequest)
|
||||
{
|
||||
string message = JsonConvert.SerializeObject(logEntryModel, Formatting.Indented);
|
||||
_logger.LogDebug("Admin[{0}] {1}", isAdminrequest, message);
|
||||
}
|
||||
|
||||
public void Error(string formatString, Exception exception)
|
||||
{
|
||||
_logger.LogError(formatString, exception.Message);
|
||||
}
|
||||
}
|
||||
|
||||
public WireMockService(ILogger<WireMockService> logger, IOptions<WireMockServerSettings> settings)
|
||||
{
|
||||
_logger = logger;
|
||||
_settings = settings.Value;
|
||||
|
||||
_settings.Logger = new Logger(logger);
|
||||
}
|
||||
|
||||
public void Start()
|
||||
{
|
||||
_logger.LogInformation("WireMock.Net server starting");
|
||||
|
||||
_server = WireMockServer.Start(_settings);
|
||||
|
||||
_logger.LogInformation($"WireMock.Net server settings {JsonConvert.SerializeObject(_settings)}");
|
||||
}
|
||||
|
||||
public void Stop()
|
||||
{
|
||||
_logger.LogInformation("WireMock.Net server stopping");
|
||||
_server?.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
{
|
||||
"Logging": {
|
||||
"IncludeScopes": false,
|
||||
"Debug": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug"
|
||||
}
|
||||
},
|
||||
"Console": {
|
||||
"LogLevel": {
|
||||
"Default": "Debug"
|
||||
}
|
||||
}
|
||||
},
|
||||
"WireMockServerSettings": {
|
||||
"AdminUsername": "a",
|
||||
"AdminPassword": "b",
|
||||
"StartAdminInterface": true
|
||||
}
|
||||
}
|
||||
21
examples/WireMock.Net.WebApplication.NETCore3/readme.md
Normal file
@@ -0,0 +1,21 @@
|
||||
# Running in IIS
|
||||
|
||||
Follow these links / steps:
|
||||
* https://weblog.west-wind.com/posts/2016/Jun/06/Publishing-and-Running-ASPNET-Core-Applications-with-IIS
|
||||
* https://docs.microsoft.com/en-us/aspnet/core/host-and-deploy/iis/development-time-iis-support?view=aspnetcore-2.1
|
||||
* Create a `web.config` file
|
||||
|
||||
## IIS Sites
|
||||

|
||||
|
||||
## App Pool settings
|
||||

|
||||
|
||||
## Publish Profiles
|
||||
Two example publish profiles are created:
|
||||
* [IIS Localhost 1](./Properties/PublishProfiles/IIS%20Localhost%201.pubxml)
|
||||
* [IIS Localhost 2](./Properties/PublishProfiles/IIS%20Localhost%202.pubxml)
|
||||
|
||||
## Debugging
|
||||
Select the debug "IIS" if you want to debug in IIS.
|
||||

|
||||
|
After Width: | Height: | Size: 7.9 KiB |
|
After Width: | Height: | Size: 36 KiB |
|
After Width: | Height: | Size: 14 KiB |
12
examples/WireMock.Net.WebApplication.NETCore3/web.config
Normal file
@@ -0,0 +1,12 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<!--
|
||||
Configure your application settings in appsettings.json. Learn more at http://go.microsoft.com/fwlink/?LinkId=786380
|
||||
-->
|
||||
<system.webServer>
|
||||
<handlers>
|
||||
<add name="aspNetCore" path="*" verb="*" modules="AspNetCoreModuleV2" resourceType="Unspecified" />
|
||||
</handlers>
|
||||
<aspNetCore processPath="%LAUNCHER_PATH%" arguments="%LAUNCHER_ARGS%" stdoutLogEnabled="false" stdoutLogFile=".\logs\stdout" forwardWindowsAuthToken="false" />
|
||||
</system.webServer>
|
||||
</configuration>
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WebPublishMethod>MSDeploy</WebPublishMethod>
|
||||
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<ProjectGuid>049539c1-7a66-4559-ad7a-b1c73b97cbb0</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
<_IsPortable>false</_IsPortable>
|
||||
<MSDeployServiceURL>localhost</MSDeployServiceURL>
|
||||
<DeployIisAppPath>Default Web Site/wiremock1</DeployIisAppPath>
|
||||
<RemoteSitePhysicalPath />
|
||||
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
|
||||
<MSDeployPublishMethod>InProc</MSDeployPublishMethod>
|
||||
<EnableMSDeployBackup>False</EnableMSDeployBackup>
|
||||
<UserName />
|
||||
<_SavePWD>False</_SavePWD>
|
||||
<PublishDatabaseSettings>
|
||||
<Objects xmlns="" />
|
||||
</PublishDatabaseSettings>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
@@ -1,31 +0,0 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<!--
|
||||
This file is used by the publish/package process of your Web project. You can customize the behavior of this process
|
||||
by editing this MSBuild file. In order to learn more about this please visit https://go.microsoft.com/fwlink/?LinkID=208121.
|
||||
-->
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<PropertyGroup>
|
||||
<WebPublishMethod>MSDeploy</WebPublishMethod>
|
||||
<LastUsedBuildConfiguration>Debug</LastUsedBuildConfiguration>
|
||||
<LastUsedPlatform>Any CPU</LastUsedPlatform>
|
||||
<SiteUrlToLaunchAfterPublish />
|
||||
<LaunchSiteAfterPublish>True</LaunchSiteAfterPublish>
|
||||
<ExcludeApp_Data>False</ExcludeApp_Data>
|
||||
<TargetFramework>netcoreapp2.0</TargetFramework>
|
||||
<RuntimeIdentifier>win10-x64</RuntimeIdentifier>
|
||||
<ProjectGuid>049539c1-7a66-4559-ad7a-b1c73b97cbb1</ProjectGuid>
|
||||
<SelfContained>true</SelfContained>
|
||||
<_IsPortable>false</_IsPortable>
|
||||
<MSDeployServiceURL>localhost</MSDeployServiceURL>
|
||||
<DeployIisAppPath>Default Web Site/wiremock2</DeployIisAppPath>
|
||||
<RemoteSitePhysicalPath />
|
||||
<SkipExtraFilesOnServer>True</SkipExtraFilesOnServer>
|
||||
<MSDeployPublishMethod>InProc</MSDeployPublishMethod>
|
||||
<EnableMSDeployBackup>False</EnableMSDeployBackup>
|
||||
<UserName />
|
||||
<_SavePWD>False</_SavePWD>
|
||||
<PublishDatabaseSettings>
|
||||
<Objects xmlns="" />
|
||||
</PublishDatabaseSettings>
|
||||
</PropertyGroup>
|
||||
</Project>
|
||||
7
nuget.config
Normal file
@@ -0,0 +1,7 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<configuration>
|
||||
<packageSources>
|
||||
<add key="nuget.org" value="https://www.nuget.org/api/v2/" />
|
||||
<add key="coverlet" value="https://f.feedz.io/marcorossignoli/coverletunofficial/nuget/index.json" />
|
||||
</packageSources>
|
||||
</configuration>
|
||||
@@ -51,7 +51,11 @@ namespace WireMock.Server
|
||||
event NotifyCollectionChangedEventHandler LogEntriesChanged;
|
||||
|
||||
/// <summary>
|
||||
/// Adds the catch all mapping.
|
||||
/// Adds a 'catch all mapping'
|
||||
///
|
||||
/// - matches all Paths and any Methods
|
||||
/// - priority is set to 1000
|
||||
/// - responds with a 404 "No matching mapping found"
|
||||
/// </summary>
|
||||
void AddCatchAllMapping();
|
||||
|
||||
@@ -83,13 +87,18 @@ namespace WireMock.Server
|
||||
//IRespondWithAProvider Given(IRequestMatcher requestMatcher, bool saveToFile = false);
|
||||
|
||||
/// <summary>
|
||||
/// Reads a static mapping file and adds or updates the mapping.
|
||||
/// 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.</param>
|
||||
/// <param name="path">The path to the static mapping file.</param>
|
||||
bool ReadStaticMappingAndAddOrUpdate([NotNull] string path);
|
||||
|
||||
/// <summary>
|
||||
/// Reads the static mappings from a folder.
|
||||
/// (This method is also used when WireMockServerSettings.ReadStaticMappings is set to true.
|
||||
///
|
||||
/// 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([CanBeNull] string folder = null);
|
||||
@@ -157,12 +166,16 @@ namespace WireMock.Server
|
||||
|
||||
/// <summary>
|
||||
/// Register the mappings (via <see cref="MappingModel"/>).
|
||||
///
|
||||
/// 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>
|
||||
/// <param name="mappings">The MappingModels</param>
|
||||
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);
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace WireMock.FluentAssertions
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> AtAbsoluteUrl(string absoluteUrl, string because = "",
|
||||
params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
@@ -36,13 +35,11 @@ namespace WireMock.FluentAssertions
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value,
|
||||
string because = "", params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs)
|
||||
=> WithHeader(expectedKey, new[] {value}, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues,
|
||||
string because = "", params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
var headersDictionary = _subject.LogEntries.SelectMany(x => x.RequestMessage.Headers)
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
@@ -72,5 +69,62 @@ namespace WireMock.FluentAssertions
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> AtUrl(string url, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
|
||||
url)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.Url == url))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.",
|
||||
_ => url, requests => requests.Select(request => request.Url));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but no calls were made.",
|
||||
proxyUrl)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.ProxyUrl == proxyUrl))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
|
||||
_ => proxyUrl, requests => requests.Select(request => request.ProxyUrl));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
|
||||
clientIP)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.ClientIP == clientIP))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
|
||||
_ => clientIP, requests => requests.Select(request => request.ClientIP));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -21,6 +21,7 @@
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -11,6 +11,7 @@
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
|
||||
@@ -21,6 +21,7 @@
|
||||
<AssemblyOriginatorKeyFile>../WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
<PackageLicenseExpression>MIT</PackageLicenseExpression>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
|
||||
|
||||
@@ -1,48 +1,74 @@
|
||||
using JetBrains.Annotations;
|
||||
using System.Linq;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Net.StandAlone
|
||||
{
|
||||
/// <summary>
|
||||
/// The StandAloneApp
|
||||
/// </summary>
|
||||
public static class StandAloneApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Start WireMock.Net standalone Server based on the IWireMockServerSettings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The IWireMockServerSettings</param>
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start([NotNull] IWireMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
var server = WireMockServer.Start(settings);
|
||||
|
||||
settings.Logger?.Info("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start WireMock.Net standalone Server based on the commandline arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The commandline arguments</param>
|
||||
/// <param name="logger">The logger</param>
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start([NotNull] string[] args, [CanBeNull] IWireMockLogger logger = null)
|
||||
{
|
||||
Check.NotNull(args, nameof(args));
|
||||
|
||||
var settings = WireMockServerSettingsParser.ParseArguments(args, logger);
|
||||
|
||||
settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
return Start(settings);
|
||||
}
|
||||
}
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Net.StandAlone
|
||||
{
|
||||
/// <summary>
|
||||
/// The StandAloneApp
|
||||
/// </summary>
|
||||
public static class StandAloneApp
|
||||
{
|
||||
/// <summary>
|
||||
/// Start WireMock.Net standalone Server based on the IWireMockServerSettings.
|
||||
/// </summary>
|
||||
/// <param name="settings">The IWireMockServerSettings</param>
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start([NotNull] IWireMockServerSettings settings)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
var server = WireMockServer.Start(settings);
|
||||
|
||||
settings.Logger?.Info("WireMock.Net server listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
return server;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Start WireMock.Net standalone Server based on the commandline arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The commandline arguments</param>
|
||||
/// <param name="logger">The logger</param>
|
||||
[PublicAPI]
|
||||
public static WireMockServer Start([NotNull] string[] args, [CanBeNull] IWireMockLogger logger = null)
|
||||
{
|
||||
Check.NotNull(args, nameof(args));
|
||||
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger))
|
||||
{
|
||||
settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
return Start(settings);
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Try to start WireMock.Net standalone Server based on the commandline arguments.
|
||||
/// </summary>
|
||||
/// <param name="args">The commandline arguments</param>
|
||||
/// <param name="logger">The logger</param>
|
||||
/// <param name="server">The WireMockServer</param>
|
||||
[PublicAPI]
|
||||
public static bool TryStart([NotNull] string[] args, out WireMockServer server, [CanBeNull] IWireMockLogger logger = null)
|
||||
{
|
||||
Check.NotNull(args, nameof(args));
|
||||
|
||||
if (WireMockServerSettingsParser.TryParseArguments(args, out var settings, logger))
|
||||
{
|
||||
settings.Logger?.Debug("WireMock.Net server arguments [{0}]", string.Join(", ", args.Select(a => $"'{a}'")));
|
||||
|
||||
server = Start(settings);
|
||||
return true;
|
||||
}
|
||||
|
||||
server = null;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3,7 +3,7 @@
|
||||
<Description>Lightweight StandAlone Http Mocking Server for .Net.</Description>
|
||||
<AssemblyTitle>WireMock.Net.StandAlone</AssemblyTitle>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1</TargetFrameworks>
|
||||
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1;netcoreapp3.1;net5.0</TargetFrameworks>
|
||||
<GenerateDocumentationFile>true</GenerateDocumentationFile>
|
||||
<AssemblyName>WireMock.Net.StandAlone</AssemblyName>
|
||||
<PackageId>WireMock.Net.StandAlone</PackageId>
|
||||
|
||||
@@ -1,19 +1,15 @@
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.HttpsCertificate;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Http
|
||||
{
|
||||
internal static class HttpClientHelper
|
||||
internal static class HttpClientBuilder
|
||||
{
|
||||
public static HttpClient CreateHttpClient(IProxyAndRecordSettings settings)
|
||||
public static HttpClient Build(IProxyAndRecordSettings settings)
|
||||
{
|
||||
#if NETSTANDARD || NETCOREAPP3_1
|
||||
#if NETSTANDARD || NETCOREAPP3_1 || NET5_0
|
||||
var handler = new HttpClientHandler
|
||||
{
|
||||
CheckCertificateRevocationList = false,
|
||||
@@ -27,21 +23,19 @@ namespace WireMock.Http
|
||||
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
};
|
||||
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
|
||||
#else
|
||||
var handler = new WebRequestHandler
|
||||
{
|
||||
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true,
|
||||
AutomaticDecompression = DecompressionMethods.GZip | DecompressionMethods.Deflate
|
||||
};
|
||||
ServicePointManager.SecurityProtocol |= SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11;
|
||||
#endif
|
||||
|
||||
if (!string.IsNullOrEmpty(settings.ClientX509Certificate2ThumbprintOrSubjectName))
|
||||
{
|
||||
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
||||
|
||||
var x509Certificate2 = ClientCertificateHelper.GetCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName);
|
||||
var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName);
|
||||
handler.ClientCertificates.Add(x509Certificate2);
|
||||
}
|
||||
|
||||
@@ -61,29 +55,12 @@ namespace WireMock.Http
|
||||
}
|
||||
}
|
||||
|
||||
var client = new HttpClient(handler);
|
||||
#if NET452 || NET46
|
||||
#if !NETSTANDARD1_3
|
||||
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls12 | SecurityProtocolType.Tls11 | SecurityProtocolType.Tls;
|
||||
ServicePointManager.ServerCertificateValidationCallback = (message, cert, chain, errors) => true;
|
||||
#endif
|
||||
return client;
|
||||
}
|
||||
|
||||
public static async Task<ResponseMessage> SendAsync([NotNull] HttpClient client, [NotNull] RequestMessage requestMessage, string url, bool deserializeJson, bool decompressGzipAndDeflate)
|
||||
{
|
||||
Check.NotNull(client, nameof(client));
|
||||
Check.NotNull(requestMessage, nameof(requestMessage));
|
||||
|
||||
var originalUri = new Uri(requestMessage.Url);
|
||||
var requiredUri = new Uri(url);
|
||||
|
||||
// Create HttpRequestMessage
|
||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, url);
|
||||
|
||||
// Call the URL
|
||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
// Create ResponseMessage
|
||||
return await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson, decompressGzipAndDeflate);
|
||||
return new HttpClient(handler);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,15 +59,29 @@ namespace WireMock.Http
|
||||
|
||||
foreach (var header in requestMessage.Headers.Where(h => !excludeHeaders.Contains(h.Key, StringComparer.OrdinalIgnoreCase)))
|
||||
{
|
||||
// Try to add to request headers. If failed - try to add to content headers
|
||||
if (httpRequestMessage.Headers.Contains(header.Key))
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Headers.Contains() with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (!httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value))
|
||||
// Skip if already added. We need to ToList() else calling httpRequestMessage.Content.Headers.Contains(...) with a header starting with a ":" throws an exception.
|
||||
if (httpRequestMessage.Content != null && httpRequestMessage.Content.Headers.ToList().Any(h => string.Equals(h.Key, header.Key, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
httpRequestMessage.Content.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
continue;
|
||||
}
|
||||
|
||||
// Try to add to request headers. If failed - try to add to content headers. If still fails, just ignore this header.
|
||||
try
|
||||
{
|
||||
if (!httpRequestMessage.Headers.TryAddWithoutValidation(header.Key, header.Value))
|
||||
{
|
||||
httpRequestMessage.Content?.Headers.TryAddWithoutValidation(header.Key, header.Value);
|
||||
}
|
||||
}
|
||||
catch
|
||||
{
|
||||
// Just continue
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
100
src/WireMock.Net/HttpsCertificate/CertificateLoader.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
{
|
||||
internal static class CertificateLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the WireMock.Net server
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(
|
||||
string storeName,
|
||||
string storeLocation,
|
||||
string thumbprintOrSubjectName,
|
||||
string filePath,
|
||||
string password,
|
||||
string host)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
|
||||
{
|
||||
var thumbprintOrSubjectNameOrHost = thumbprintOrSubjectName ?? host;
|
||||
|
||||
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), storeName), (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation));
|
||||
try
|
||||
{
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException($"No Certificate found with in store '{storeName}', location '{storeLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(password))
|
||||
{
|
||||
return new X509Certificate2(filePath, password);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath and X509CertificatePassword are mandatory.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for Proxy
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
{
|
||||
internal static class ClientCertificateHelper
|
||||
{
|
||||
public static X509Certificate2 GetCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to subject name
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -71,7 +71,7 @@ namespace WireMock
|
||||
/// The WireMockServerSettings.
|
||||
/// </summary>
|
||||
IWireMockServerSettings Settings { get; }
|
||||
|
||||
|
||||
/// <summary>
|
||||
/// Is State started ?
|
||||
/// </summary>
|
||||
|
||||
@@ -68,9 +68,18 @@ namespace WireMock
|
||||
/// <param name="executionConditionState">State in which the current mapping can occur. [Optional]</param>
|
||||
/// <param name="nextState">The next state which will occur after the current mapping execution. [Optional]</param>
|
||||
/// <param name="stateTimes">Only when the current state is executed this number, the next state which will occur. [Optional]</param>
|
||||
public Mapping(Guid guid, [CanBeNull] string title, [CanBeNull] string path,
|
||||
[NotNull] IWireMockServerSettings settings, [NotNull] IRequestMatcher requestMatcher, [NotNull] IResponseProvider provider,
|
||||
int priority, [CanBeNull] string scenario, [CanBeNull] string executionConditionState, [CanBeNull] string nextState, [CanBeNull] int? stateTimes)
|
||||
public Mapping(
|
||||
Guid guid,
|
||||
[CanBeNull] string title,
|
||||
[CanBeNull] string path,
|
||||
[NotNull] IWireMockServerSettings settings,
|
||||
[NotNull] IRequestMatcher requestMatcher,
|
||||
[NotNull] IResponseProvider provider,
|
||||
int priority,
|
||||
[CanBeNull] string scenario,
|
||||
[CanBeNull] string executionConditionState,
|
||||
[CanBeNull] string nextState,
|
||||
[CanBeNull] int? stateTimes)
|
||||
{
|
||||
Guid = guid;
|
||||
Title = title;
|
||||
@@ -82,7 +91,7 @@ namespace WireMock
|
||||
Scenario = scenario;
|
||||
ExecutionConditionState = executionConditionState;
|
||||
NextState = nextState;
|
||||
StateTimes = stateTimes;
|
||||
StateTimes = stateTimes;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IMapping.ProvideResponseAsync" />
|
||||
|
||||
@@ -12,6 +12,7 @@ namespace WireMock.Matchers
|
||||
/// </summary>
|
||||
/// <inheritdoc cref="IObjectMatcher"/>
|
||||
/// <inheritdoc cref="IStringMatcher"/>
|
||||
[Obsolete("This class will be moved to a separate NuGet package 'WireMock.Net.Matchers.CSharpCode'")]
|
||||
internal class CSharpCodeMatcher : IObjectMatcher, IStringMatcher
|
||||
{
|
||||
private const string TemplateForIsMatchWithString = "{0} public class CodeHelper {{ public bool IsMatch(string it) {{ {1} }} }}";
|
||||
@@ -151,7 +152,7 @@ namespace WireMock.Matchers
|
||||
throw new WireMockException("CSharpCodeMatcher: Problem calling method 'IsMatch' in WireMock.CodeHelper", ex);
|
||||
}
|
||||
|
||||
#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1)
|
||||
#elif (NETSTANDARD2_0 || NETSTANDARD2_1 || NETCOREAPP3_1 || NET5_0)
|
||||
dynamic script;
|
||||
try
|
||||
{
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Collections;
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json;
|
||||
@@ -17,7 +18,7 @@ namespace WireMock.Matchers
|
||||
public object Value { get; }
|
||||
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public string Name => "JsonMatcher";
|
||||
public virtual string Name => "JsonMatcher";
|
||||
|
||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||
public MatchBehaviour MatchBehaviour { get; }
|
||||
@@ -29,6 +30,7 @@ namespace WireMock.Matchers
|
||||
public bool ThrowException { get; }
|
||||
|
||||
private readonly JToken _valueAsJToken;
|
||||
private readonly Func<JToken, JToken> _jTokenConverter;
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonMatcher"/> class.
|
||||
@@ -67,6 +69,9 @@ namespace WireMock.Matchers
|
||||
|
||||
Value = value;
|
||||
_valueAsJToken = ConvertValueToJToken(value);
|
||||
_jTokenConverter = ignoreCase
|
||||
? (Func<JToken, JToken>)Rename
|
||||
: jToken => jToken;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IObjectMatcher.IsMatch"/>
|
||||
@@ -81,7 +86,9 @@ namespace WireMock.Matchers
|
||||
{
|
||||
var inputAsJToken = ConvertValueToJToken(input);
|
||||
|
||||
match = DeepEquals(_valueAsJToken, inputAsJToken);
|
||||
match = IsMatch(
|
||||
_jTokenConverter(_valueAsJToken),
|
||||
_jTokenConverter(inputAsJToken));
|
||||
}
|
||||
catch (JsonException)
|
||||
{
|
||||
@@ -95,6 +102,17 @@ namespace WireMock.Matchers
|
||||
return MatchBehaviourHelper.Convert(MatchBehaviour, MatchScores.ToScore(match));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Compares the input against the matcher value
|
||||
/// </summary>
|
||||
/// <param name="value">Matcher value</param>
|
||||
/// <param name="input">Input value</param>
|
||||
/// <returns></returns>
|
||||
protected virtual bool IsMatch(JToken value, JToken input)
|
||||
{
|
||||
return JToken.DeepEquals(value, input);
|
||||
}
|
||||
|
||||
private static JToken ConvertValueToJToken(object value)
|
||||
{
|
||||
// Check if JToken, string, IEnumerable or object
|
||||
@@ -114,19 +132,6 @@ namespace WireMock.Matchers
|
||||
}
|
||||
}
|
||||
|
||||
private bool DeepEquals(JToken value, JToken input)
|
||||
{
|
||||
if (!IgnoreCase)
|
||||
{
|
||||
return JToken.DeepEquals(value, input);
|
||||
}
|
||||
|
||||
JToken renamedValue = Rename(value);
|
||||
JToken renamedInput = Rename(input);
|
||||
|
||||
return JToken.DeepEquals(renamedValue, renamedInput);
|
||||
}
|
||||
|
||||
private static string ToUpper(string input)
|
||||
{
|
||||
return input?.ToUpperInvariant();
|
||||
|
||||
87
src/WireMock.Net/Matchers/JsonPartialMatcher.cs
Normal file
@@ -0,0 +1,87 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using JetBrains.Annotations;
|
||||
using Newtonsoft.Json.Linq;
|
||||
|
||||
namespace WireMock.Matchers
|
||||
{
|
||||
/// <summary>
|
||||
/// JsonPartialMatcher
|
||||
/// </summary>
|
||||
public class JsonPartialMatcher : JsonMatcher
|
||||
{
|
||||
/// <inheritdoc cref="IMatcher.Name"/>
|
||||
public override string Name => "JsonPartialMatcher";
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The string value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
public JsonPartialMatcher([NotNull] string value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="value">The object value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
public JsonPartialMatcher([NotNull] object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(value, ignoreCase, throwException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Initializes a new instance of the <see cref="JsonPartialMatcher"/> class.
|
||||
/// </summary>
|
||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||
/// <param name="value">The value to check for equality.</param>
|
||||
/// <param name="ignoreCase">Ignore the case from the PropertyName and PropertyValue (string only).</param>
|
||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||
public JsonPartialMatcher(MatchBehaviour matchBehaviour, [NotNull] object value, bool ignoreCase = false, bool throwException = false)
|
||||
: base(matchBehaviour, value, ignoreCase, throwException)
|
||||
{
|
||||
}
|
||||
|
||||
/// <inheritdoc />
|
||||
protected override bool IsMatch(JToken value, JToken input)
|
||||
{
|
||||
if (value == null || value == input)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (input == null || value.Type != input.Type)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (value.Type)
|
||||
{
|
||||
case JTokenType.Object:
|
||||
var nestedValues = value.ToObject<Dictionary<string, JToken>>();
|
||||
return nestedValues?.Any() != true ||
|
||||
nestedValues.All(pair => IsMatch(pair.Value, input.SelectToken(pair.Key)));
|
||||
|
||||
case JTokenType.Array:
|
||||
var valuesArray = value.ToObject<JToken[]>();
|
||||
var tokenArray = input.ToObject<JToken[]>();
|
||||
|
||||
if (valuesArray?.Any() != true)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
return tokenArray?.Any() == true &&
|
||||
valuesArray.All(subFilter => tokenArray.Any(subToken => IsMatch(subFilter, subToken)));
|
||||
|
||||
default:
|
||||
return value.ToString() == input.ToString();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,8 +1,10 @@
|
||||
#if USE_ASPNETCORE && !NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.HttpsCertificate;
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
@@ -16,23 +18,56 @@ namespace WireMock.Owin
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions kestrelOptions, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
{
|
||||
foreach (var detail in urlDetails)
|
||||
foreach (var urlDetail in urlDetails)
|
||||
{
|
||||
if (detail.Url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
if (urlDetail.IsHttps)
|
||||
{
|
||||
options.Listen(System.Net.IPAddress.Any, detail.Port, listenOptions =>
|
||||
kestrelOptions.Listen(System.Net.IPAddress.Any, urlDetail.Port, listenOptions =>
|
||||
{
|
||||
listenOptions.UseHttps();
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
listenOptions.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
listenOptions.UseHttps();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Listen(System.Net.IPAddress.Any, detail.Port);
|
||||
kestrelOptions.Listen(System.Net.IPAddress.Any, urlDetail.Port);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class IWebHostBuilderExtensions
|
||||
{
|
||||
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder)
|
||||
{
|
||||
return builder.ConfigureAppConfiguration(config =>
|
||||
{
|
||||
config.AddEnvironmentVariables();
|
||||
});
|
||||
}
|
||||
|
||||
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
|
||||
{
|
||||
return builder.ConfigureServices((context, services) =>
|
||||
{
|
||||
services.Configure<KestrelServerOptions>(context.Configuration.GetSection("Kestrel"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -1,9 +1,9 @@
|
||||
#if USE_ASPNETCORE && NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.HttpsCertificate;
|
||||
|
||||
namespace WireMock.Owin
|
||||
@@ -17,14 +17,47 @@ namespace WireMock.Owin
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
{
|
||||
var urls = urlDetails.Select(u => u.Url);
|
||||
if (urls.Any(u => u.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
|
||||
foreach (var urlDetail in urlDetails)
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
if (urlDetail.IsHttps)
|
||||
{
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
options.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
internal static class IWebHostBuilderExtensions
|
||||
{
|
||||
internal static IWebHostBuilder ConfigureAppConfigurationUsingEnvironmentVariables(this IWebHostBuilder builder) => builder;
|
||||
|
||||
internal static IWebHostBuilder ConfigureKestrelServerOptions(this IWebHostBuilder builder)
|
||||
{
|
||||
var configuration = new ConfigurationBuilder()
|
||||
.AddEnvironmentVariables()
|
||||
.Build();
|
||||
|
||||
return builder.ConfigureServices(services =>
|
||||
{
|
||||
services.Configure<KestrelServerOptions>(configuration.GetSection("Kestrel"));
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
#endif
|
||||
@@ -18,7 +18,7 @@ namespace WireMock.Owin
|
||||
internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
||||
{
|
||||
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
|
||||
private readonly IWireMockLogger _logger;
|
||||
private readonly HostUrlOptions _urlOptions;
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace WireMock.Owin
|
||||
|
||||
public Exception RunningException => _runningException;
|
||||
|
||||
public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions options, [NotNull] HostUrlOptions urlOptions)
|
||||
public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions wireMockMiddlewareOptions, [NotNull] HostUrlOptions urlOptions)
|
||||
{
|
||||
Check.NotNull(options, nameof(options));
|
||||
Check.NotNull(wireMockMiddlewareOptions, nameof(wireMockMiddlewareOptions));
|
||||
Check.NotNull(urlOptions, nameof(urlOptions));
|
||||
|
||||
_logger = options.Logger ?? new WireMockConsoleLogger();
|
||||
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
|
||||
|
||||
_options = options;
|
||||
_wireMockMiddlewareOptions = wireMockMiddlewareOptions;
|
||||
_urlOptions = urlOptions;
|
||||
}
|
||||
|
||||
@@ -58,9 +58,11 @@ namespace WireMock.Owin
|
||||
}
|
||||
|
||||
_host = builder
|
||||
.UseSetting("suppressStatusMessages", "True") // https://andrewlock.net/suppressing-the-startup-and-shutdown-messages-in-asp-net-core/
|
||||
.ConfigureAppConfigurationUsingEnvironmentVariables()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(_options);
|
||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||
@@ -69,18 +71,19 @@ namespace WireMock.Owin
|
||||
{
|
||||
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
|
||||
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
|
||||
appBuilder.UseMiddleware<WireMockMiddleware>();
|
||||
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
_wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
})
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
SetKestrelOptionsLimits(options);
|
||||
|
||||
SetHttpsAndUrls(options, _urlOptions.GetDetails());
|
||||
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
|
||||
})
|
||||
.ConfigureKestrelServerOptions()
|
||||
|
||||
#if NETSTANDARD1_3
|
||||
.UseUrls(_urlOptions.GetDetails().Select(u => u.Url).ToArray())
|
||||
@@ -105,7 +108,7 @@ namespace WireMock.Owin
|
||||
{
|
||||
Urls.Add(address.Replace("0.0.0.0", "localhost"));
|
||||
|
||||
PortUtils.TryExtract(address, out string protocol, out string host, out int port);
|
||||
PortUtils.TryExtract(address, out bool isHttps, out string protocol, out string host, out int port);
|
||||
Ports.Add(port);
|
||||
}
|
||||
|
||||
@@ -118,8 +121,12 @@ namespace WireMock.Owin
|
||||
_logger.Info("WireMock.Net server using netstandard2.0");
|
||||
#elif NETSTANDARD2_1
|
||||
_logger.Info("WireMock.Net server using netstandard2.1");
|
||||
#elif NETCOREAPP3_1
|
||||
_logger.Info("WireMock.Net server using .NET Core 3.1");
|
||||
#elif NET5_0
|
||||
_logger.Info("WireMock.Net server using .NET 5.0");
|
||||
#elif NET46
|
||||
_logger.Info("WireMock.Net server using .net 4.6.1 or higher");
|
||||
_logger.Info("WireMock.Net server using .NET Framework 4.6.1 or higher");
|
||||
#endif
|
||||
|
||||
#if NETSTANDARD1_3
|
||||
|
||||
15
src/WireMock.Net/Owin/HostUrlDetails.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
internal class HostUrlDetails
|
||||
{
|
||||
public bool IsHttps { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public string Protocol { get; set; }
|
||||
|
||||
public string Host { get; set; }
|
||||
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,29 @@ namespace WireMock.Owin
|
||||
{
|
||||
internal class HostUrlOptions
|
||||
{
|
||||
private const string LOCALHOST = "localhost";
|
||||
|
||||
public ICollection<string> Urls { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
public ICollection<(string Url, int Port)> GetDetails()
|
||||
public ICollection<HostUrlDetails> GetDetails()
|
||||
{
|
||||
var list = new List<(string Url, int Port)>();
|
||||
var list = new List<HostUrlDetails>();
|
||||
if (Urls == null)
|
||||
{
|
||||
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
|
||||
list.Add(($"{(UseSSL ? "https" : "http")}://localhost:{port}", port));
|
||||
string protocol = UseSSL ? "https" : "http";
|
||||
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string url in Urls)
|
||||
{
|
||||
PortUtils.TryExtract(url, out string protocol, out string host, out int port);
|
||||
list.Add((url, port));
|
||||
PortUtils.TryExtract(url, out bool isHttps, out string protocol, out string host, out int port);
|
||||
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,17 @@ namespace WireMock.Owin
|
||||
bool? DisableRequestBodyDecompressing { get; set; }
|
||||
|
||||
bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
string X509StoreName { get; set; }
|
||||
|
||||
string X509StoreLocation { get; set; }
|
||||
|
||||
string X509ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
string X509CertificateFilePath { get; set; }
|
||||
|
||||
string X509CertificatePassword { get; set; }
|
||||
|
||||
bool CustomCertificateDefined { get; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
@@ -79,16 +80,21 @@ namespace WireMock.Owin.Mappers
|
||||
break;
|
||||
}
|
||||
|
||||
switch (responseMessage.StatusCode)
|
||||
var statusCodeType = responseMessage.StatusCode?.GetType();
|
||||
|
||||
switch (statusCodeType)
|
||||
{
|
||||
case int statusCodeAsInteger:
|
||||
response.StatusCode = MapStatusCode(statusCodeAsInteger);
|
||||
case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
|
||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode);
|
||||
break;
|
||||
|
||||
case Type typeAsString when typeAsString == typeof(string):
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(responseMessage.StatusCode as string, out int result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
break;
|
||||
|
||||
case string statusCodeAsString:
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(statusCodeAsString, out int result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -8,6 +8,7 @@ using WireMock.Owin.Mappers;
|
||||
using WireMock.Serialization;
|
||||
using WireMock.Types;
|
||||
using WireMock.Validation;
|
||||
using WireMock.ResponseBuilders;
|
||||
#if !USE_ASPNETCORE
|
||||
using Microsoft.Owin;
|
||||
using IContext = Microsoft.Owin.IOwinContext;
|
||||
@@ -129,6 +130,22 @@ namespace WireMock.Owin
|
||||
|
||||
response = await targetMapping.ProvideResponseAsync(request);
|
||||
|
||||
var responseBuilder = targetMapping.Provider as Response;
|
||||
|
||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMapping == true || targetMapping?.Settings?.ProxyAndRecordSettings?.SaveMapping == true)
|
||||
{
|
||||
_options.Mappings.TryAdd(targetMapping.Guid, targetMapping);
|
||||
}
|
||||
|
||||
if (responseBuilder?.ProxyAndRecordSettings?.SaveMappingToFile == true || targetMapping?.Settings?.ProxyAndRecordSettings?.SaveMappingToFile == true)
|
||||
{
|
||||
var matcherMapper = new MatcherMapper(targetMapping.Settings);
|
||||
var mappingConverter = new MappingConverter(matcherMapper);
|
||||
var mappingToFileSaver = new MappingToFileSaver(targetMapping.Settings, mappingConverter);
|
||||
|
||||
mappingToFileSaver.SaveMappingToFile(targetMapping);
|
||||
}
|
||||
|
||||
if (targetMapping.Scenario != null)
|
||||
{
|
||||
UpdateScenarioState(targetMapping);
|
||||
|
||||
@@ -53,5 +53,25 @@ namespace WireMock.Owin
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.HandleRequestsSynchronously"/>
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreName"/>
|
||||
public string X509StoreName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreLocation"/>
|
||||
public string X509StoreLocation { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509ThumbprintOrSubjectName"/>
|
||||
public string X509ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificateFilePath"/>
|
||||
public string X509CertificateFilePath { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificatePassword"/>
|
||||
public string X509CertificatePassword { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.CustomCertificateDefined"/>
|
||||
public bool CustomCertificateDefined =>
|
||||
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
|
||||
!string.IsNullOrEmpty(X509CertificateFilePath) && !string.IsNullOrEmpty(X509CertificatePassword);
|
||||
}
|
||||
}
|
||||
111
src/WireMock.Net/Proxy/ProxyHelper.cs
Normal file
@@ -0,0 +1,111 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using HandlebarsDotNet.Helpers.Validation;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Http;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
|
||||
namespace WireMock.Proxy
|
||||
{
|
||||
internal class ProxyHelper
|
||||
{
|
||||
private readonly IWireMockServerSettings _settings;
|
||||
|
||||
public ProxyHelper([NotNull] IWireMockServerSettings settings)
|
||||
{
|
||||
Guard.NotNull(settings, nameof(settings));
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public async Task<(ResponseMessage ResponseMessage, IMapping Mapping)> SendAsync(
|
||||
[NotNull] IProxyAndRecordSettings proxyAndRecordSettings,
|
||||
[NotNull] HttpClient client,
|
||||
[NotNull] RequestMessage requestMessage,
|
||||
[NotNull] string url)
|
||||
{
|
||||
Guard.NotNull(client, nameof(client));
|
||||
Guard.NotNull(requestMessage, nameof(requestMessage));
|
||||
Guard.NotNull(url, nameof(url));
|
||||
|
||||
var originalUri = new Uri(requestMessage.Url);
|
||||
var requiredUri = new Uri(url);
|
||||
|
||||
// Create HttpRequestMessage
|
||||
var httpRequestMessage = HttpRequestMessageHelper.Create(requestMessage, url);
|
||||
|
||||
// Call the URL
|
||||
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
|
||||
|
||||
// Create ResponseMessage
|
||||
bool deserializeJson = !_settings.DisableJsonBodyParsing.GetValueOrDefault(false);
|
||||
bool decompressGzipAndDeflate = !_settings.DisableRequestBodyDecompressing.GetValueOrDefault(false);
|
||||
|
||||
var responseMessage = await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson, decompressGzipAndDeflate);
|
||||
|
||||
IMapping mapping = null;
|
||||
if (HttpStatusRangeParser.IsMatch(proxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
|
||||
(proxyAndRecordSettings.SaveMapping || proxyAndRecordSettings.SaveMappingToFile))
|
||||
{
|
||||
mapping = ToMapping(proxyAndRecordSettings, requestMessage, responseMessage);
|
||||
}
|
||||
|
||||
return (responseMessage, mapping);
|
||||
}
|
||||
|
||||
private IMapping ToMapping(IProxyAndRecordSettings proxyAndRecordSettings, RequestMessage requestMessage, ResponseMessage responseMessage)
|
||||
{
|
||||
string[] excludedHeaders = proxyAndRecordSettings.ExcludedHeaders ?? new string[] { };
|
||||
string[] excludedCookies = proxyAndRecordSettings.ExcludedCookies ?? new string[] { };
|
||||
|
||||
var request = Request.Create();
|
||||
request.WithPath(requestMessage.Path);
|
||||
request.UsingMethod(requestMessage.Method);
|
||||
|
||||
requestMessage.Query.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
|
||||
requestMessage.Cookies.Loop((key, value) =>
|
||||
{
|
||||
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
request.WithCookie(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
var allExcludedHeaders = new List<string>(excludedHeaders) { "Cookie" };
|
||||
requestMessage.Headers.Loop((key, value) =>
|
||||
{
|
||||
if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
request.WithHeader(key, value.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Json:
|
||||
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson, true, throwExceptionWhenMatcherFails));
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, throwExceptionWhenMatcherFails, requestMessage.BodyData.BodyAsString));
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
|
||||
break;
|
||||
}
|
||||
|
||||
var response = Response.Create(responseMessage);
|
||||
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,27 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.ResponseProviders;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
|
||||
}
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.ResponseProviders;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
|
||||
|
||||
/// <summary>
|
||||
/// The async callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, Task<ResponseMessage>> callbackHandler);
|
||||
}
|
||||
}
|
||||
60
src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
public partial class Response
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response async.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, ResponseMessage})"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, Task{ResponseMessage}})"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
CallbackAsync = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -9,15 +9,10 @@ namespace WireMock.ResponseBuilders
|
||||
{
|
||||
private HttpClient _httpClientForProxy;
|
||||
|
||||
/// <summary>
|
||||
/// The Proxy URL to use.
|
||||
/// </summary>
|
||||
public string ProxyUrl { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// The WebProxy settings.
|
||||
/// </summary>
|
||||
public IWebProxySettings WebProxySettings { get; private set; }
|
||||
public IProxyAndRecordSettings ProxyAndRecordSettings { get; private set; }
|
||||
|
||||
/// <inheritdoc cref="IProxyResponseBuilder.WithProxy(string, string)"/>
|
||||
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2ThumbprintOrSubjectName = null)
|
||||
@@ -38,10 +33,9 @@ namespace WireMock.ResponseBuilders
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
ProxyUrl = settings.Url;
|
||||
WebProxySettings = settings.WebProxySettings;
|
||||
ProxyAndRecordSettings = settings;
|
||||
|
||||
_httpClientForProxy = HttpClientHelper.CreateHttpClient(settings);
|
||||
_httpClientForProxy = HttpClientBuilder.Build(settings);
|
||||
return this;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -7,7 +7,7 @@ using System.Net;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Http;
|
||||
using WireMock.Proxy;
|
||||
using WireMock.ResponseProviders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Transformers;
|
||||
@@ -42,16 +42,6 @@ namespace WireMock.ResponseBuilders
|
||||
/// </summary>
|
||||
public ResponseMessage ResponseMessage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance.
|
||||
/// </summary>
|
||||
@@ -311,25 +301,6 @@ namespace WireMock.ResponseBuilders
|
||||
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IWireMockServerSettings)"/>
|
||||
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
|
||||
{
|
||||
@@ -341,7 +312,7 @@ namespace WireMock.ResponseBuilders
|
||||
await Task.Delay(Delay.Value);
|
||||
}
|
||||
|
||||
if (ProxyUrl != null && _httpClientForProxy != null)
|
||||
if (ProxyAndRecordSettings != null && _httpClientForProxy != null)
|
||||
{
|
||||
string RemoveFirstOccurrence(string source, string find)
|
||||
{
|
||||
@@ -352,26 +323,36 @@ namespace WireMock.ResponseBuilders
|
||||
var requestUri = new Uri(requestMessage.Url);
|
||||
|
||||
// Build the proxy url and skip duplicates
|
||||
string extra = RemoveFirstOccurrence(requestUri.LocalPath.TrimEnd('/'), new Uri(ProxyUrl).LocalPath.TrimEnd('/'));
|
||||
requestMessage.ProxyUrl = ProxyUrl + extra + requestUri.Query;
|
||||
string extra = RemoveFirstOccurrence(requestUri.LocalPath.TrimEnd('/'), new Uri(ProxyAndRecordSettings.Url).LocalPath.TrimEnd('/'));
|
||||
requestMessage.ProxyUrl = ProxyAndRecordSettings.Url + extra + requestUri.Query;
|
||||
|
||||
return await HttpClientHelper.SendAsync(
|
||||
var proxyHelper = new ProxyHelper(settings);
|
||||
|
||||
var (proxyResponseMessage, mapping) = await proxyHelper.SendAsync(
|
||||
ProxyAndRecordSettings,
|
||||
_httpClientForProxy,
|
||||
requestMessage,
|
||||
requestMessage.ProxyUrl,
|
||||
!settings.DisableJsonBodyParsing.GetValueOrDefault(false),
|
||||
!settings.DisableRequestBodyDecompressing.GetValueOrDefault(false)
|
||||
requestMessage.ProxyUrl
|
||||
);
|
||||
|
||||
return proxyResponseMessage;
|
||||
}
|
||||
|
||||
ResponseMessage responseMessage;
|
||||
if (Callback == null)
|
||||
if (Callback == null && CallbackAsync == null)
|
||||
{
|
||||
responseMessage = ResponseMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
if (Callback != null)
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = await CallbackAsync(requestMessage);
|
||||
}
|
||||
|
||||
if (!WithCallbackUsed)
|
||||
{
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
// This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
|
||||
// For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
|
||||
using JetBrains.Annotations;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.ResponseProviders
|
||||
|
||||
19
src/WireMock.Net/Serialization/JsonSerializationConstants.cs
Normal file
@@ -0,0 +1,19 @@
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
internal static class JsonSerializationConstants
|
||||
{
|
||||
public static readonly JsonSerializerSettings JsonSerializerSettingsDefault = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
public static readonly JsonSerializerSettings JsonSerializerSettingsIncludeNullValues = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Include
|
||||
};
|
||||
}
|
||||
}
|
||||
@@ -101,7 +101,7 @@ namespace WireMock.Serialization
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(response.ProxyUrl))
|
||||
if (response.ProxyAndRecordSettings != null)
|
||||
{
|
||||
mappingModel.Response.StatusCode = null;
|
||||
mappingModel.Response.Headers = null;
|
||||
@@ -115,9 +115,9 @@ namespace WireMock.Serialization
|
||||
mappingModel.Response.UseTransformer = null;
|
||||
mappingModel.Response.UseTransformerForBodyAsFile = null;
|
||||
mappingModel.Response.BodyEncoding = null;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyUrl;
|
||||
mappingModel.Response.ProxyUrl = response.ProxyAndRecordSettings.Url;
|
||||
mappingModel.Response.Fault = null;
|
||||
mappingModel.Response.WebProxy = MapWebProxy(response.WebProxySettings);
|
||||
mappingModel.Response.WebProxy = MapWebProxy(response.ProxyAndRecordSettings.WebProxySettings);
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
49
src/WireMock.Net/Serialization/MappingToFileSaver.cs
Normal file
@@ -0,0 +1,49 @@
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.Serialization
|
||||
{
|
||||
internal class MappingToFileSaver
|
||||
{
|
||||
private readonly IWireMockServerSettings _settings;
|
||||
private readonly MappingConverter _mappingConverter;
|
||||
|
||||
public MappingToFileSaver(IWireMockServerSettings settings, MappingConverter mappingConverter)
|
||||
{
|
||||
Check.NotNull(settings, nameof(settings));
|
||||
|
||||
_settings = settings;
|
||||
_mappingConverter = mappingConverter;
|
||||
}
|
||||
|
||||
public void SaveMappingToFile(IMapping mapping, string folder = null)
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
_settings.FileSystemHandler.CreateFolder(folder);
|
||||
}
|
||||
|
||||
var model = _mappingConverter.ToMappingModel(mapping);
|
||||
string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
|
||||
|
||||
string path = Path.Combine(folder, filename);
|
||||
|
||||
_settings.Logger.Info("Saving Mapping file {0}", filename);
|
||||
|
||||
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, JsonSerializationConstants.JsonSerializerSettingsDefault));
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string name, char replaceChar = '_')
|
||||
{
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -36,7 +36,7 @@ namespace WireMock.Serialization
|
||||
string matcherName = parts[0];
|
||||
string matcherType = parts.Length > 1 ? parts[1] : null;
|
||||
|
||||
string[] stringPatterns = matcher.Patterns != null ? matcher.Patterns.OfType<string>().ToArray() : new[] { matcher.Pattern as string };
|
||||
string[] stringPatterns = (matcher.Patterns != null ? matcher.Patterns : new[] { matcher.Pattern }).OfType<string>().ToArray();
|
||||
MatchBehaviour matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||
bool ignoreCase = matcher.IgnoreCase == true;
|
||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||
@@ -64,7 +64,12 @@ namespace WireMock.Serialization
|
||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonMatcher":
|
||||
return new JsonMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
object value = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonMatcher(matchBehaviour, value, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonPartialMatcher":
|
||||
object matcherValue = matcher.Pattern ?? matcher.Patterns;
|
||||
return new JsonPartialMatcher(matchBehaviour, matcherValue, ignoreCase, throwExceptionWhenMatcherFails);
|
||||
|
||||
case "JsonPathMatcher":
|
||||
return new JsonPathMatcher(matchBehaviour, throwExceptionWhenMatcherFails, stringPatterns);
|
||||
|
||||
@@ -16,6 +16,7 @@ using WireMock.Http;
|
||||
using WireMock.Logging;
|
||||
using WireMock.Matchers;
|
||||
using WireMock.Matchers.Request;
|
||||
using WireMock.Proxy;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.ResponseProviders;
|
||||
@@ -47,18 +48,6 @@ namespace WireMock.Server
|
||||
private readonly RegexMatcher _adminMappingsGuidPathMatcher = new RegexMatcher(@"^\/__admin\/mappings\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||
private readonly RegexMatcher _adminRequestsGuidPathMatcher = new RegexMatcher(@"^\/__admin\/requests\/([0-9A-Fa-f]{8}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{4}[-][0-9A-Fa-f]{12})$");
|
||||
|
||||
private readonly JsonSerializerSettings _jsonSerializerSettings = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Ignore
|
||||
};
|
||||
|
||||
private readonly JsonSerializerSettings _settingsIncludeNullValues = new JsonSerializerSettings
|
||||
{
|
||||
Formatting = Formatting.Indented,
|
||||
NullValueHandling = NullValueHandling.Include
|
||||
};
|
||||
|
||||
#region InitAdmin
|
||||
private void InitAdmin()
|
||||
{
|
||||
@@ -119,7 +108,7 @@ namespace WireMock.Server
|
||||
{
|
||||
foreach (var mapping in Mappings.Where(m => !m.IsAdminInterface))
|
||||
{
|
||||
SaveMappingToFile(mapping, folder);
|
||||
_mappingToFileSaver.SaveMappingToFile(mapping, folder);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -246,7 +235,7 @@ namespace WireMock.Server
|
||||
|
||||
private void InitProxyAndRecord(IWireMockServerSettings settings)
|
||||
{
|
||||
_httpClientForProxy = HttpClientHelper.CreateHttpClient(settings.ProxyAndRecordSettings);
|
||||
_httpClientForProxy = HttpClientBuilder.Build(settings.ProxyAndRecordSettings);
|
||||
|
||||
var respondProvider = Given(Request.Create().WithPath("/*").UsingAnyMethod());
|
||||
if (settings.StartAdminInterface == true)
|
||||
@@ -263,82 +252,27 @@ namespace WireMock.Server
|
||||
var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url);
|
||||
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
|
||||
|
||||
var responseMessage = await HttpClientHelper.SendAsync(
|
||||
var proxyHelper = new ProxyHelper(settings);
|
||||
|
||||
var (responseMessage, mapping) = await proxyHelper.SendAsync(
|
||||
_settings.ProxyAndRecordSettings,
|
||||
_httpClientForProxy,
|
||||
requestMessage,
|
||||
proxyUriWithRequestPathAndQuery.AbsoluteUri,
|
||||
!settings.DisableJsonBodyParsing.GetValueOrDefault(false),
|
||||
!settings.DisableRequestBodyDecompressing.GetValueOrDefault(false)
|
||||
proxyUriWithRequestPathAndQuery.AbsoluteUri
|
||||
);
|
||||
|
||||
if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
|
||||
(settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile))
|
||||
if (settings.ProxyAndRecordSettings.SaveMapping)
|
||||
{
|
||||
var mapping = ToMapping(
|
||||
requestMessage,
|
||||
responseMessage,
|
||||
settings.ProxyAndRecordSettings.ExcludedHeaders ?? new string[] { },
|
||||
settings.ProxyAndRecordSettings.ExcludedCookies ?? new string[] { }
|
||||
);
|
||||
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||
}
|
||||
|
||||
if (settings.ProxyAndRecordSettings.SaveMapping)
|
||||
{
|
||||
_options.Mappings.TryAdd(mapping.Guid, mapping);
|
||||
}
|
||||
|
||||
if (settings.ProxyAndRecordSettings.SaveMappingToFile)
|
||||
{
|
||||
SaveMappingToFile(mapping);
|
||||
}
|
||||
if (settings.ProxyAndRecordSettings.SaveMappingToFile)
|
||||
{
|
||||
_mappingToFileSaver.SaveMappingToFile(mapping);
|
||||
}
|
||||
|
||||
return responseMessage;
|
||||
}
|
||||
|
||||
private IMapping ToMapping(RequestMessage requestMessage, ResponseMessage responseMessage, string[] excludedHeaders, string[] excludedCookies)
|
||||
{
|
||||
var request = Request.Create();
|
||||
request.WithPath(requestMessage.Path);
|
||||
request.UsingMethod(requestMessage.Method);
|
||||
|
||||
requestMessage.Query.Loop((key, value) => request.WithParam(key, false, value.ToArray()));
|
||||
requestMessage.Cookies.Loop((key, value) =>
|
||||
{
|
||||
if (!excludedCookies.Contains(key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
request.WithCookie(key, value);
|
||||
}
|
||||
});
|
||||
|
||||
var allExcludedHeaders = new List<string>(excludedHeaders) { "Cookie" };
|
||||
requestMessage.Headers.Loop((key, value) =>
|
||||
{
|
||||
if (!allExcludedHeaders.Contains(key, StringComparer.OrdinalIgnoreCase))
|
||||
{
|
||||
request.WithHeader(key, value.ToArray());
|
||||
}
|
||||
});
|
||||
|
||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||
switch (requestMessage.BodyData?.DetectedBodyType)
|
||||
{
|
||||
case BodyType.Json:
|
||||
request.WithBody(new JsonMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsJson, true, throwExceptionWhenMatcherFails));
|
||||
break;
|
||||
|
||||
case BodyType.String:
|
||||
request.WithBody(new ExactMatcher(MatchBehaviour.AcceptOnMatch, throwExceptionWhenMatcherFails, requestMessage.BodyData.BodyAsString));
|
||||
break;
|
||||
|
||||
case BodyType.Bytes:
|
||||
request.WithBody(new ExactObjectMatcher(MatchBehaviour.AcceptOnMatch, requestMessage.BodyData.BodyAsBytes, throwExceptionWhenMatcherFails));
|
||||
break;
|
||||
}
|
||||
|
||||
var response = Response.Create(responseMessage);
|
||||
|
||||
return new Mapping(Guid.NewGuid(), string.Empty, null, _settings, request, response, 0, null, null, null, null);
|
||||
}
|
||||
#endregion
|
||||
|
||||
#region Settings
|
||||
@@ -446,33 +380,6 @@ namespace WireMock.Server
|
||||
return ResponseMessageBuilder.Create("Mappings saved to disk");
|
||||
}
|
||||
|
||||
private void SaveMappingToFile(IMapping mapping, string folder = null)
|
||||
{
|
||||
if (folder == null)
|
||||
{
|
||||
folder = _settings.FileSystemHandler.GetMappingFolder();
|
||||
}
|
||||
|
||||
if (!_settings.FileSystemHandler.FolderExists(folder))
|
||||
{
|
||||
_settings.FileSystemHandler.CreateFolder(folder);
|
||||
}
|
||||
|
||||
var model = _mappingConverter.ToMappingModel(mapping);
|
||||
string filename = (!string.IsNullOrEmpty(mapping.Title) ? SanitizeFileName(mapping.Title) : mapping.Guid.ToString()) + ".json";
|
||||
|
||||
string path = Path.Combine(folder, filename);
|
||||
|
||||
_settings.Logger.Info("Saving Mapping file {0}", filename);
|
||||
|
||||
_settings.FileSystemHandler.WriteMappingFile(path, JsonConvert.SerializeObject(model, _jsonSerializerSettings));
|
||||
}
|
||||
|
||||
private static string SanitizeFileName(string name, char replaceChar = '_')
|
||||
{
|
||||
return Path.GetInvalidFileNameChars().Aggregate(name, (current, c) => current.Replace(c, replaceChar));
|
||||
}
|
||||
|
||||
private IEnumerable<MappingModel> ToMappingModels()
|
||||
{
|
||||
return Mappings.Where(m => !m.IsAdminInterface).Select(_mappingConverter.ToMappingModel);
|
||||
@@ -945,7 +852,7 @@ namespace WireMock.Server
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? _settingsIncludeNullValues : _jsonSerializerSettings)
|
||||
BodyAsString = JsonConvert.SerializeObject(result, keepNullValues ? JsonSerializationConstants.JsonSerializerSettingsIncludeNullValues : JsonSerializationConstants.JsonSerializerSettingsDefault)
|
||||
},
|
||||
StatusCode = (int)HttpStatusCode.OK,
|
||||
Headers = new Dictionary<string, WireMockList<string>> { { HttpKnownHeaderNames.ContentType, new WireMockList<string>(ContentTypeJson) } }
|
||||
|
||||
@@ -35,6 +35,7 @@ namespace WireMock.Server
|
||||
private readonly IWireMockMiddlewareOptions _options = new WireMockMiddlewareOptions();
|
||||
private readonly MappingConverter _mappingConverter;
|
||||
private readonly MatcherMapper _matcherMapper;
|
||||
private readonly MappingToFileSaver _mappingToFileSaver;
|
||||
|
||||
/// <inheritdoc cref="IWireMockServer.IsStarted" />
|
||||
[PublicAPI]
|
||||
@@ -80,10 +81,7 @@ namespace WireMock.Server
|
||||
/// <param name="disposing"><c>true</c> to release both managed and unmanaged resources; <c>false</c> to release only unmanaged resources.</param>
|
||||
protected virtual void Dispose(bool disposing)
|
||||
{
|
||||
if (_httpServer != null)
|
||||
{
|
||||
_httpServer.StopAsync();
|
||||
}
|
||||
_httpServer?.StopAsync();
|
||||
}
|
||||
#endregion
|
||||
|
||||
@@ -230,8 +228,18 @@ namespace WireMock.Server
|
||||
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
|
||||
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
|
||||
if (settings.CustomCertificateDefined)
|
||||
{
|
||||
_options.X509StoreName = settings.CertificateSettings.X509StoreName;
|
||||
_options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
|
||||
_options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
|
||||
_options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
|
||||
_options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
|
||||
}
|
||||
|
||||
_matcherMapper = new MatcherMapper(_settings);
|
||||
_mappingConverter = new MappingConverter(_matcherMapper);
|
||||
_mappingToFileSaver = new MappingToFileSaver(_settings, _mappingConverter);
|
||||
|
||||
#if USE_ASPNETCORE
|
||||
_httpServer = new AspNetCoreSelfHost(_options, urlOptions);
|
||||
@@ -485,7 +493,7 @@ namespace WireMock.Server
|
||||
|
||||
if (saveToFile)
|
||||
{
|
||||
SaveMappingToFile(mapping);
|
||||
_mappingToFileSaver.SaveMappingToFile(mapping);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||