Compare commits

..

18 Commits

Author SHA1 Message Date
Stef Heyenrath
7033d85e3a 1.2.10 2020-05-17 20:01:30 +02:00
Stef Heyenrath
7d873611ee Limits (#457) 2020-05-17 19:55:36 +02:00
Stef Heyenrath
f26bf62a13 Include Handlebars.Net.Helpers project (#456)
* wip

* h 100

* rename

* csproj
2020-05-17 19:55:06 +02:00
Stef Heyenrath
6938b6f73c 1.2.9.0 2020-05-14 06:25:36 +00:00
Stef Heyenrath
5b2cd061a6 Fix method ResetMappingsAsync in the RestEase-AdminApi (#465) 2020-05-14 08:00:44 +02:00
Stef Heyenrath
80993c7740 1.2.8.0 2020-05-04 17:36:28 +02:00
Sean Fausett
d4d0f8becd Fix SourceLink support (#463) 2020-05-04 17:33:41 +02:00
Stef Heyenrath
cd613d1c76 1.2.7.0 2020-04-30 17:52:48 +02:00
Stef Heyenrath
5f4c688e49 fix (#461) 2020-04-29 18:01:54 +02:00
Stef Heyenrath
e7949a47d9 1.2.6.0 2020-04-29 07:05:21 +00:00
Stef Heyenrath
a6cf7a48dc When using ResponseMessageTransformer : keep BodyEncoding (#460) 2020-04-29 08:40:49 +02:00
Stef Heyenrath
bf5afef7a1 1.2.5.0 2020-04-17 10:22:40 +00:00
Stef Heyenrath
a8934ec7f9 fix net452 (#454) 2020-04-17 12:18:45 +02:00
Stef Heyenrath
d2ac56e49a 1.2.4.0 2020-04-10 22:54:19 +02:00
Stef Heyenrath
e8a4d52797 Add ValidatedNotNullAttribute (for SonarQube) (#452)
* ValidatedNotNull

* usings
2020-04-10 22:51:34 +02:00
Stef Heyenrath
dac73b6fe0 codecov\1.10.0 (#451) 2020-04-10 20:28:07 +02:00
Stef Heyenrath
e91be0a4d1 Add support for GZip and Deflate (#439)
* gzip - wip

* wip

* tests

* fix gzip and deflate

* CheckIfShouldKillVBCSCompiler

* DisableRequestBodyDecompressing
2020-04-10 19:05:09 +02:00
Stef Heyenrath
a9974a4874 Add readme.md + license from mock4net (#444)
* add readme.md + license from mock4net

* common

* add license info
2020-04-05 18:42:22 +02:00
68 changed files with 2333 additions and 1835 deletions

11
.vscode/launch.json vendored
View File

@@ -1,17 +1,6 @@
{ {
"version": "0.2.0", "version": "0.2.0",
"configurations": [ "configurations": [
{
"name": ".NET Core Launch (WireMock.Net.StandAlone.NETCoreApp)",
"type": "coreclr",
"request": "launch",
"preLaunchTask": "build_WireMock.Net.StandAlone.NETCoreApp",
"program": "${workspaceRoot}/examples/WireMock.Net.StandAlone.NETCoreApp/bin/Debug/netcoreapp2.0/WireMock.Net.StandAlone.NETCoreApp.dll",
"args": [],
"cwd": "${workspaceRoot}",
"stopAtEntry": false,
"console": "internalConsole"
},
{ {
"name": ".NET Core Attach", "name": ".NET Core Attach",
"type": "coreclr", "type": "coreclr",

View File

@@ -1,3 +1,34 @@
# 1.2.10.0 (17 May 2020)
- [#456](https://github.com/WireMock-Net/WireMock.Net/pull/456) - Include Handlebars.Net.Helpers project [feature] contributed by [StefH](https://github.com/StefH)
- [#457](https://github.com/WireMock-Net/WireMock.Net/pull/457) - Kestrel Options Limits [bug] contributed by [StefH](https://github.com/StefH)
- [#455](https://github.com/WireMock-Net/WireMock.Net/issues/455) - There is no option to increase body size while proxying [bug]
# 1.2.9.0 (14 May 2020)
- [#465](https://github.com/WireMock-Net/WireMock.Net/pull/465) - Fix method ResetMappingsAsync in the RestEase-AdminApi [bug] contributed by [StefH](https://github.com/StefH)
- [#464](https://github.com/WireMock-Net/WireMock.Net/issues/464) - RestClient Admin API Metadata Base Path Duplication [bug]
# 1.2.8.0 (04 May 2020)
- [#463](https://github.com/WireMock-Net/WireMock.Net/pull/463) - GH161: Fix SourceLink support [bug] contributed by [gitfool](https://github.com/gitfool)
# 1.2.7.0 (30 April 2020)
- [#461](https://github.com/WireMock-Net/WireMock.Net/pull/461) - Support Path in ProxyUrl contributed by [StefH](https://github.com/StefH)
- [#459](https://github.com/WireMock-Net/WireMock.Net/issues/459) - When respond with proxy requestMessage.Url is used, not AbsoluteUrl [bug]
# 1.2.6.0 (29 April 2020)
- [#460](https://github.com/WireMock-Net/WireMock.Net/pull/460) - When using ResponseMessageTransformer : keep BodyEncoding [bug] contributed by [StefH](https://github.com/StefH)
- [#458](https://github.com/WireMock-Net/WireMock.Net/issues/458) - Response BodyAsString loses BodyData.Encoding when UseTransformer = true [bug]
# 1.2.5.0 (17 April 2020)
- [#454](https://github.com/WireMock-Net/WireMock.Net/pull/454) - Fix port = 0 for net452 [bug] contributed by [StefH](https://github.com/StefH)
- [#453](https://github.com/WireMock-Net/WireMock.Net/issues/453) - MockServer not starting [bug]
# 1.2.4.0 (10 April 2020)
- [#439](https://github.com/WireMock-Net/WireMock.Net/pull/439) - Add support for GZip and Deflate [feature] contributed by [StefH](https://github.com/StefH)
- [#444](https://github.com/WireMock-Net/WireMock.Net/pull/444) - Add readme.md + license from mock4net [feature] contributed by [StefH](https://github.com/StefH)
- [#451](https://github.com/WireMock-Net/WireMock.Net/pull/451) - Update NuGet dependencies (e.g. coverage related) to fix CI-build [feature] contributed by [StefH](https://github.com/StefH)
- [#452](https://github.com/WireMock-Net/WireMock.Net/pull/452) - Add ValidatedNotNullAttribute (for SonarQube) [refactor] contributed by [StefH](https://github.com/StefH)
- [#426](https://github.com/WireMock-Net/WireMock.Net/issues/426) - Add support for compressed requests, such as GZIP or DEFLATE [feature]
# 1.2.3.0 (01 April 2020) # 1.2.3.0 (01 April 2020)
- [#449](https://github.com/WireMock-Net/WireMock.Net/pull/449) - Netstandard21 [feature] contributed by [StefH](https://github.com/StefH) - [#449](https://github.com/WireMock-Net/WireMock.Net/pull/449) - Netstandard21 [feature] contributed by [StefH](https://github.com/StefH)
- [#447](https://github.com/WireMock-Net/WireMock.Net/issues/447) - Add support for .NET Standard 2.1 / .NET Core 3.1 [feature] - [#447](https://github.com/WireMock-Net/WireMock.Net/issues/447) - Add support for .NET Standard 2.1 / .NET Core 3.1 [feature]

View File

@@ -4,7 +4,14 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup> <PropertyGroup>
<VersionPrefix>1.2.3</VersionPrefix> <VersionPrefix>1.2.10</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>
<PackageLicenseExpression>Apache-2.0</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
</PropertyGroup> </PropertyGroup>
<Choose> <Choose>

View File

@@ -1,3 +1,3 @@
https://github.com/StefH/GitHubReleaseNotes https://github.com/StefH/GitHubReleaseNotes
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.2.3.0 GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.2.10.0

View File

@@ -9,6 +9,7 @@
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WWW/@EntryIndexedValue">WWW</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=WWW/@EntryIndexedValue">WWW</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XMS/@EntryIndexedValue">XMS</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XMS/@EntryIndexedValue">XMS</s:String>
<s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XUA/@EntryIndexedValue">XUA</s:String> <s:String x:Key="/Default/CodeStyle/Naming/CSharpNaming/Abbreviations/=XUA/@EntryIndexedValue">XUA</s:String>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Flurl/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=funcs/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=funcs/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Heyenrath/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Heyenrath/@EntryIndexedValue">True</s:Boolean>
<s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean> <s:Boolean x:Key="/Default/UserDictionary/Words/=Jmes/@EntryIndexedValue">True</s:Boolean>

View File

@@ -46,7 +46,7 @@ steps:
# Upload coverage to codecov.io # Upload coverage to codecov.io
- script: | - script: |
%USERPROFILE%\.nuget\packages\codecov\1.1.0\tools\codecov.exe -f "./test/WireMock.Net.Tests/coverage.opencover.xml" -t $(CODECOV_TOKEN) %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 displayName: Upload coverage to codecov.io
# https://github.com/microsoft/azure-pipelines-tasks/issues/12212 # https://github.com/microsoft/azure-pipelines-tasks/issues/12212

View File

@@ -28,7 +28,7 @@
<ItemGroup> <ItemGroup>
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" /> <ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
<PackageReference Include="Handlebars.Net" Version="1.9.5" /> <PackageReference Include="Handlebars.Net.Helpers" Version="0.0.3" />
<PackageReference Include="log4net" Version="2.0.8" /> <PackageReference Include="log4net" Version="2.0.8" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<!--<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="3.4.0" />--> <!--<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="3.4.0" />-->

View File

@@ -36,6 +36,9 @@ namespace WireMock.Net.ConsoleApplication
{ {
public static void Run() public static void Run()
{ {
var s = WireMockServer.Start();
s.Stop();
string url1 = "http://localhost:9091/"; string url1 = "http://localhost:9091/";
string url2 = "http://localhost:9092/"; string url2 = "http://localhost:9092/";
string url3 = "https://localhost:9443/"; string url3 = "https://localhost:9443/";
@@ -94,7 +97,7 @@ namespace WireMock.Net.ConsoleApplication
.WithHeader("postmanecho", "post") .WithHeader("postmanecho", "post")
) )
.RespondWith(Response.Create() .RespondWith(Response.Create()
.WithProxy(new ProxyAndRecordSettings { Url = "http://postman-echo.com/post" }) .WithProxy(new ProxyAndRecordSettings { Url = "http://postman-echo.com" })
); );
server server

177
mock4net/LICENSE.txt Normal file
View File

@@ -0,0 +1,177 @@
Apache License
Version 2.0, January 2004
http://www.apache.org/licenses/
TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
1. Definitions.
"License" shall mean the terms and conditions for use, reproduction,
and distribution as defined by Sections 1 through 9 of this document.
"Licensor" shall mean the copyright owner or entity authorized by
the copyright owner that is granting the License.
"Legal Entity" shall mean the union of the acting entity and all
other entities that control, are controlled by, or are under common
control with that entity. For the purposes of this definition,
"control" means (i) the power, direct or indirect, to cause the
direction or management of such entity, whether by contract or
otherwise, or (ii) ownership of fifty percent (50%) or more of the
outstanding shares, or (iii) beneficial ownership of such entity.
"You" (or "Your") shall mean an individual or Legal Entity
exercising permissions granted by this License.
"Source" form shall mean the preferred form for making modifications,
including but not limited to software source code, documentation
source, and configuration files.
"Object" form shall mean any form resulting from mechanical
transformation or translation of a Source form, including but
not limited to compiled object code, generated documentation,
and conversions to other media types.
"Work" shall mean the work of authorship, whether in Source or
Object form, made available under the License, as indicated by a
copyright notice that is included in or attached to the work
(an example is provided in the Appendix below).
"Derivative Works" shall mean any work, whether in Source or Object
form, that is based on (or derived from) the Work and for which the
editorial revisions, annotations, elaborations, or other modifications
represent, as a whole, an original work of authorship. For the purposes
of this License, Derivative Works shall not include works that remain
separable from, or merely link (or bind by name) to the interfaces of,
the Work and Derivative Works thereof.
"Contribution" shall mean any work of authorship, including
the original version of the Work and any modifications or additions
to that Work or Derivative Works thereof, that is intentionally
submitted to Licensor for inclusion in the Work by the copyright owner
or by an individual or Legal Entity authorized to submit on behalf of
the copyright owner. For the purposes of this definition, "submitted"
means any form of electronic, verbal, or written communication sent
to the Licensor or its representatives, including but not limited to
communication on electronic mailing lists, source code control systems,
and issue tracking systems that are managed by, or on behalf of, the
Licensor for the purpose of discussing and improving the Work, but
excluding communication that is conspicuously marked or otherwise
designated in writing by the copyright owner as "Not a Contribution."
"Contributor" shall mean Licensor and any individual or Legal Entity
on behalf of whom a Contribution has been received by Licensor and
subsequently incorporated within the Work.
2. Grant of Copyright License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
copyright license to reproduce, prepare Derivative Works of,
publicly display, publicly perform, sublicense, and distribute the
Work and such Derivative Works in Source or Object form.
3. Grant of Patent License. Subject to the terms and conditions of
this License, each Contributor hereby grants to You a perpetual,
worldwide, non-exclusive, no-charge, royalty-free, irrevocable
(except as stated in this section) patent license to make, have made,
use, offer to sell, sell, import, and otherwise transfer the Work,
where such license applies only to those patent claims licensable
by such Contributor that are necessarily infringed by their
Contribution(s) alone or by combination of their Contribution(s)
with the Work to which such Contribution(s) was submitted. If You
institute patent litigation against any entity (including a
cross-claim or counterclaim in a lawsuit) alleging that the Work
or a Contribution incorporated within the Work constitutes direct
or contributory patent infringement, then any patent licenses
granted to You under this License for that Work shall terminate
as of the date such litigation is filed.
4. Redistribution. You may reproduce and distribute copies of the
Work or Derivative Works thereof in any medium, with or without
modifications, and in Source or Object form, provided that You
meet the following conditions:
(a) You must give any other recipients of the Work or
Derivative Works a copy of this License; and
(b) You must cause any modified files to carry prominent notices
stating that You changed the files; and
(c) You must retain, in the Source form of any Derivative Works
that You distribute, all copyright, patent, trademark, and
attribution notices from the Source form of the Work,
excluding those notices that do not pertain to any part of
the Derivative Works; and
(d) If the Work includes a "NOTICE" text file as part of its
distribution, then any Derivative Works that You distribute must
include a readable copy of the attribution notices contained
within such NOTICE file, excluding those notices that do not
pertain to any part of the Derivative Works, in at least one
of the following places: within a NOTICE text file distributed
as part of the Derivative Works; within the Source form or
documentation, if provided along with the Derivative Works; or,
within a display generated by the Derivative Works, if and
wherever such third-party notices normally appear. The contents
of the NOTICE file are for informational purposes only and
do not modify the License. You may add Your own attribution
notices within Derivative Works that You distribute, alongside
or as an addendum to the NOTICE text from the Work, provided
that such additional attribution notices cannot be construed
as modifying the License.
You may add Your own copyright statement to Your modifications and
may provide additional or different license terms and conditions
for use, reproduction, or distribution of Your modifications, or
for any such Derivative Works as a whole, provided Your use,
reproduction, and distribution of the Work otherwise complies with
the conditions stated in this License.
5. Submission of Contributions. Unless You explicitly state otherwise,
any Contribution intentionally submitted for inclusion in the Work
by You to the Licensor shall be under the terms and conditions of
this License, without any additional terms or conditions.
Notwithstanding the above, nothing herein shall supersede or modify
the terms of any separate license agreement you may have executed
with Licensor regarding such Contributions.
6. Trademarks. This License does not grant permission to use the trade
names, trademarks, service marks, or product names of the Licensor,
except as required for reasonable and customary use in describing the
origin of the Work and reproducing the content of the NOTICE file.
7. Disclaimer of Warranty. Unless required by applicable law or
agreed to in writing, Licensor provides the Work (and each
Contributor provides its Contributions) on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
implied, including, without limitation, any warranties or conditions
of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
PARTICULAR PURPOSE. You are solely responsible for determining the
appropriateness of using or redistributing the Work and assume any
risks associated with Your exercise of permissions under this License.
8. Limitation of Liability. In no event and under no legal theory,
whether in tort (including negligence), contract, or otherwise,
unless required by applicable law (such as deliberate and grossly
negligent acts) or agreed to in writing, shall any Contributor be
liable to You for damages, including any direct, indirect, special,
incidental, or consequential damages of any character arising as a
result of this License or out of the use or inability to use the
Work (including but not limited to damages for loss of goodwill,
work stoppage, computer failure or malfunction, or any and all
other commercial damages or losses), even if such Contributor
has been advised of the possibility of such damages.
9. Accepting Warranty or Additional Liability. While redistributing
the Work or Derivative Works thereof, You may choose to offer,
and charge a fee for, acceptance of support, warranty, indemnity,
or other liability obligations and/or rights consistent with this
License. However, in accepting such obligations, You may act only
on Your own behalf and on Your sole responsibility, not on behalf
of any other Contributor, and only if You agree to indemnify,
defend, and hold each Contributor harmless for any liability
incurred by, or claims asserted against, such Contributor by reason
of your accepting any such warranty or additional liability.
END OF TERMS AND CONDITIONS

3
mock4net/readme.md Normal file
View File

@@ -0,0 +1,3 @@
WireMock.Net is based on the source-code from https://github.com/alexvictoor/mock4net
The license in this folder is copied from https://github.com/alexvictoor/mock4net/blob/master/LICENSE.txt

View File

@@ -40,6 +40,11 @@ namespace WireMock.Admin.Requests
/// </summary> /// </summary>
public string AbsoluteUrl { get; set; } public string AbsoluteUrl { get; set; }
/// <summary>
/// The ProxyUrl (if a proxy is used).
/// </summary>
public string ProxyUrl { get; set; }
/// <summary> /// <summary>
/// The query. /// The query.
/// </summary> /// </summary>

View File

@@ -9,20 +9,11 @@
<AssemblyName>WireMock.Net.Abstractions</AssemblyName> <AssemblyName>WireMock.Net.Abstractions</AssemblyName>
<PackageId>WireMock.Net.Abstractions</PackageId> <PackageId>WireMock.Net.Abstractions</PackageId>
<PackageTags>wiremock;interfaces;models;classes;enumerations;types</PackageTags> <PackageTags>wiremock;interfaces;models;classes;enumerations;types</PackageTags>
<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>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<RootNamespace>WireMock</RootNamespace> <RootNamespace>WireMock</RootNamespace>
<!--<DebugType>full</DebugType>
<IncludeSource>True</IncludeSource>
<IncludeSymbols>True</IncludeSymbols>-->
<ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid> <ProjectGuid>{B6269AAC-170A-4346-8B9A-579DED3D9A94}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
@@ -33,14 +24,13 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PathMap>$(MSBuildProjectDirectory)=/</PathMap> <!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<!--<GeneratePackageOnBuild>true</GeneratePackageOnBuild>--> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3"> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3" PrivateAssets="All" />
<PrivateAssets>all</PrivateAssets> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</PackageReference>
</ItemGroup> </ItemGroup>
</Project> </Project>

View File

@@ -86,7 +86,7 @@ namespace WireMock.Client
/// Delete (reset) all mappings. /// Delete (reset) all mappings.
/// </summary> /// </summary>
/// <param name="reloadStaticMappings">A value indicating whether to reload the static mappings after the reset.</param> /// <param name="reloadStaticMappings">A value indicating whether to reload the static mappings after the reset.</param>
[Post("__admin/mappings/reset")] [Post("mappings/reset")]
Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false); Task<StatusModel> ResetMappingsAsync(bool? reloadStaticMappings = false);
/// <summary> /// <summary>

View File

@@ -9,20 +9,11 @@
<AssemblyName>WireMock.Net.RestClient</AssemblyName> <AssemblyName>WireMock.Net.RestClient</AssemblyName>
<PackageId>WireMock.Net.RestClient</PackageId> <PackageId>WireMock.Net.RestClient</PackageId>
<PackageTags>wiremock;rest;client;restclient;restease;rest;json</PackageTags> <PackageTags>wiremock;rest;client;restclient;restease;rest;json</PackageTags>
<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>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<RootNamespace>WireMock.Client</RootNamespace> <RootNamespace>WireMock.Client</RootNamespace>
<!--<DebugType>full</DebugType>
<IncludeSource>True</IncludeSource>
<IncludeSymbols>True</IncludeSymbols>-->
<ProjectGuid>{B6269AAC-170A-43D6-8B9A-579DED3D9A96}</ProjectGuid> <ProjectGuid>{B6269AAC-170A-43D6-8B9A-579DED3D9A96}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>../WireMock.Net/WireMock.Net.ruleset</CodeAnalysisRuleSet>
@@ -33,11 +24,12 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PathMap>$(MSBuildProjectDirectory)=/</PathMap> <!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<PackageReference Include="RestEase" Version="1.4.10" /> <PackageReference Include="RestEase" Version="1.4.10" />
</ItemGroup> </ItemGroup>

View File

@@ -8,20 +8,11 @@
<AssemblyName>WireMock.Net.StandAlone</AssemblyName> <AssemblyName>WireMock.Net.StandAlone</AssemblyName>
<PackageId>WireMock.Net.StandAlone</PackageId> <PackageId>WireMock.Net.StandAlone</PackageId>
<PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags> <PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags>
<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>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<RootNamespace>WireMock.Net.StandAlone</RootNamespace> <RootNamespace>WireMock.Net.StandAlone</RootNamespace>
<!--<DebugType>full</DebugType>
<IncludeSource>True</IncludeSource>
<IncludeSymbols>True</IncludeSymbols>-->
<ProjectGuid>{B6269AAC-170A-43D5-8B9A-579DED3D9A95}</ProjectGuid> <ProjectGuid>{B6269AAC-170A-43D5-8B9A-579DED3D9A95}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<EmbedUntrackedSources>true</EmbedUntrackedSources>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
<CodeAnalysisRuleSet>WireMock.Net.StandAlone.ruleset</CodeAnalysisRuleSet> <CodeAnalysisRuleSet>WireMock.Net.StandAlone.ruleset</CodeAnalysisRuleSet>
@@ -32,7 +23,7 @@
</PropertyGroup> </PropertyGroup>
<PropertyGroup Condition=" '$(Configuration)' == 'Release' "> <PropertyGroup Condition=" '$(Configuration)' == 'Release' ">
<PathMap>$(MSBuildProjectDirectory)=/</PathMap> <!--<PathMap>$(MSBuildProjectDirectory)=/</PathMap>-->
<GeneratePackageOnBuild>true</GeneratePackageOnBuild> <GeneratePackageOnBuild>true</GeneratePackageOnBuild>
</PropertyGroup> </PropertyGroup>
@@ -45,9 +36,8 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2018.2.1"> <PackageReference Include="JetBrains.Annotations" Version="2018.2.1" PrivateAssets="All" />
<PrivateAssets>All</PrivateAssets> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
</PackageReference>
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320"> <PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>

View File

@@ -68,7 +68,7 @@ namespace WireMock.Http
return client; return client;
} }
public static async Task<ResponseMessage> SendAsync([NotNull] HttpClient client, [NotNull] RequestMessage requestMessage, string url, bool deserializeJson) 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(client, nameof(client));
Check.NotNull(requestMessage, nameof(requestMessage)); Check.NotNull(requestMessage, nameof(requestMessage));
@@ -83,7 +83,7 @@ namespace WireMock.Http
var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead); var httpResponseMessage = await client.SendAsync(httpRequestMessage, HttpCompletionOption.ResponseContentRead);
// Create ResponseMessage // Create ResponseMessage
return await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson); return await HttpResponseMessageHelper.CreateAsync(httpResponseMessage, requiredUri, originalUri, deserializeJson, decompressGzipAndDeflate);
} }
} }
} }

View File

@@ -9,7 +9,7 @@ namespace WireMock.Http
{ {
internal static class HttpResponseMessageHelper internal static class HttpResponseMessageHelper
{ {
public static async Task<ResponseMessage> CreateAsync(HttpResponseMessage httpResponseMessage, Uri requiredUri, Uri originalUri, bool deserializeJson) public static async Task<ResponseMessage> CreateAsync(HttpResponseMessage httpResponseMessage, Uri requiredUri, Uri originalUri, bool deserializeJson, bool decompressGzipAndDeflate)
{ {
var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode }; var responseMessage = new ResponseMessage { StatusCode = (int)httpResponseMessage.StatusCode };
@@ -24,7 +24,21 @@ namespace WireMock.Http
contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value; contentTypeHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentType, StringComparison.OrdinalIgnoreCase)).Value;
} }
responseMessage.BodyData = await BodyParser.Parse(stream, contentTypeHeader?.FirstOrDefault(), deserializeJson); IEnumerable<string> contentEncodingHeader = null;
if (headers.Any(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)))
{
contentEncodingHeader = headers.First(header => string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase)).Value;
}
var bodyParserSettings = new BodyParserSettings
{
Stream = stream,
ContentType = contentTypeHeader?.FirstOrDefault(),
DeserializeJson = deserializeJson,
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
DecompressGZipAndDeflate = decompressGzipAndDeflate
};
responseMessage.BodyData = await BodyParser.Parse(bodyParserSettings);
} }
foreach (var header in headers) foreach (var header in headers)

View File

@@ -0,0 +1,2 @@
Some source files in this folder are 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.

View File

@@ -0,0 +1,40 @@
#if USE_ASPNETCORE && !NETSTANDARD1_3
using System;
using System.Collections.Generic;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel.Core;
namespace WireMock.Owin
{
internal partial class AspNetCoreSelfHost
{
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
options.Limits.KeepAliveTimeout = TimeSpan.MaxValue;
options.Limits.MaxRequestBodySize = null; // https://stackoverflow.com/questions/46738364/increase-upload-request-length-limit-in-kestrel
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
options.Limits.RequestHeadersTimeout = TimeSpan.MaxValue;
}
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
{
foreach (var detail in urlDetails)
{
if (detail.Url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
options.Listen(System.Net.IPAddress.Any, detail.Port, listenOptions =>
{
listenOptions.UseHttps();
});
}
else
{
options.Listen(System.Net.IPAddress.Any, detail.Port);
}
}
}
}
}
#endif

View File

@@ -0,0 +1,32 @@
#if USE_ASPNETCORE && NETSTANDARD1_3
using System;
using System.Collections.Generic;
using System.Linq;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Server.Kestrel;
using WireMock.HttpsCertificate;
namespace WireMock.Owin
{
internal partial class AspNetCoreSelfHost
{
private static void SetKestrelOptionsLimits(KestrelServerOptions options)
{
options.Limits.KeepAliveTimeout = TimeSpan.MaxValue;
options.Limits.MaxRequestBufferSize = null;
options.Limits.MaxRequestHeaderCount = 100;
options.Limits.MaxResponseBufferSize = null;
options.Limits.RequestHeadersTimeout = TimeSpan.MaxValue;
}
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
{
var urls = urlDetails.Select(u => u.Url);
if (urls.Any(u => u.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
{
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
}
}
}
}
#endif

View File

@@ -8,7 +8,6 @@ using JetBrains.Annotations;
using Microsoft.AspNetCore.Builder; using Microsoft.AspNetCore.Builder;
using Microsoft.AspNetCore.Hosting; using Microsoft.AspNetCore.Hosting;
using Microsoft.Extensions.DependencyInjection; using Microsoft.Extensions.DependencyInjection;
using WireMock.HttpsCertificate;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Owin.Mappers; using WireMock.Owin.Mappers;
using WireMock.Util; using WireMock.Util;
@@ -16,7 +15,7 @@ using WireMock.Validation;
namespace WireMock.Owin namespace WireMock.Owin
{ {
internal class AspNetCoreSelfHost : IOwinSelfHost internal partial class AspNetCoreSelfHost : IOwinSelfHost
{ {
private readonly CancellationTokenSource _cts = new CancellationTokenSource(); private readonly CancellationTokenSource _cts = new CancellationTokenSource();
private readonly IWireMockMiddlewareOptions _options; private readonly IWireMockMiddlewareOptions _options;
@@ -78,31 +77,9 @@ namespace WireMock.Owin
}) })
.UseKestrel(options => .UseKestrel(options =>
{ {
var urlDetails = _urlOptions.GetDetails(); SetKestrelOptionsLimits(options);
#if NETSTANDARD1_3 SetHttpsAndUrls(options, _urlOptions.GetDetails());
var urls = urlDetails.Select(u => u.Url);
if (urls.Any(u => u.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
{
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
}
#else
foreach (var detail in urlDetails)
{
if (detail.Url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
{
options.Listen(System.Net.IPAddress.Any, detail.Port, listenOptions =>
{
listenOptions.UseHttps(); // PublicCertificateHelper.GetX509Certificate2()
});
}
else
{
options.Listen(System.Net.IPAddress.Any, detail.Port);
}
}
#endif
}) })
#if NETSTANDARD1_3 #if NETSTANDARD1_3
@@ -144,6 +121,7 @@ namespace WireMock.Owin
#elif NET46 #elif NET46
_logger.Info("WireMock.Net server using .net 4.6.1 or higher"); _logger.Info("WireMock.Net server using .net 4.6.1 or higher");
#endif #endif
#if NETSTANDARD1_3 #if NETSTANDARD1_3
return Task.Run(() => return Task.Run(() =>
{ {

View File

@@ -16,7 +16,7 @@ namespace WireMock.Owin
var list = new List<(string Url, int Port)>(); var list = new List<(string Url, int Port)>();
if (Urls == null) if (Urls == null)
{ {
int port = Port ?? FindFreeTcpPort(); int port = Port > 0 ? Port.Value : FindFreeTcpPort();
list.Add(($"{(UseSSL ? "https" : "http")}://localhost:{port}", port)); list.Add(($"{(UseSSL ? "https" : "http")}://localhost:{port}", port));
} }
else else

View File

@@ -43,5 +43,7 @@ namespace WireMock.Owin
bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
bool? DisableJsonBodyParsing { get; set; } bool? DisableJsonBodyParsing { get; set; }
bool? DisableRequestBodyDecompressing { get; set; }
} }
} }

View File

@@ -2,6 +2,7 @@
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Threading.Tasks; using System.Threading.Tasks;
using WireMock.Http;
using WireMock.Models; using WireMock.Models;
using WireMock.Util; using WireMock.Util;
#if !USE_ASPNETCORE #if !USE_ASPNETCORE
@@ -27,12 +28,18 @@ namespace WireMock.Owin.Mappers
string method = request.Method; string method = request.Method;
Dictionary<string, string[]> headers = null; Dictionary<string, string[]> headers = null;
IEnumerable<string> contentEncodingHeader = null;
if (request.Headers.Any()) if (request.Headers.Any())
{ {
headers = new Dictionary<string, string[]>(); headers = new Dictionary<string, string[]>();
foreach (var header in request.Headers) foreach (var header in request.Headers)
{ {
headers.Add(header.Key, header.Value); headers.Add(header.Key, header.Value);
if (string.Equals(header.Key, HttpKnownHeaderNames.ContentEncoding, StringComparison.OrdinalIgnoreCase))
{
contentEncodingHeader = header.Value;
}
} }
} }
@@ -49,7 +56,15 @@ namespace WireMock.Owin.Mappers
BodyData body = null; BodyData body = null;
if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true)) if (request.Body != null && BodyParser.ShouldParseBody(method, options.AllowBodyForAllHttpMethods == true))
{ {
body = await BodyParser.Parse(request.Body, request.ContentType, !options.DisableJsonBodyParsing.GetValueOrDefault(false)); var bodyParserSettings = new BodyParserSettings
{
Stream = request.Body,
ContentType = request.ContentType,
DeserializeJson = !options.DisableJsonBodyParsing.GetValueOrDefault(false),
ContentEncoding = contentEncodingHeader?.FirstOrDefault(),
DecompressGZipAndDeflate = !options.DisableRequestBodyDecompressing.GetValueOrDefault(false)
};
body = await BodyParser.Parse(bodyParserSettings);
} }
return new RequestMessage(urldetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow }; return new RequestMessage(urldetails, method, clientIP, body, headers, cookies) { DateTime = DateTime.UtcNow };

View File

@@ -46,7 +46,10 @@ namespace WireMock.Owin
/// <inheritdoc cref="IWireMockMiddlewareOptions.AllowOnlyDefinedHttpStatusCodeInResponse"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.AllowOnlyDefinedHttpStatusCodeInResponse"/>
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.DisableResponseBodyParsing"/> /// <inheritdoc cref="IWireMockMiddlewareOptions.DisableJsonBodyParsing"/>
public bool? DisableJsonBodyParsing { get; set; } public bool? DisableJsonBodyParsing { get; set; }
/// <inheritdoc cref="IWireMockMiddlewareOptions.DisableRequestBodyDecompressing"/>
public bool? DisableRequestBodyDecompressing { get; set; }
} }
} }

View File

@@ -1,4 +1,6 @@
using System.Linq; // 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 System.Linq;
using WireMock.Http; using WireMock.Http;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;

View File

@@ -1,4 +1,6 @@
using System; // 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 System;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using WireMock.Validation; using WireMock.Validation;

View File

@@ -1,4 +1,6 @@
using System; // 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 System;
using System.Collections.Generic; using System.Collections.Generic;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;

View File

@@ -1,4 +1,6 @@
using System; // 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 System;
using System.Collections.Generic; using System.Collections.Generic;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;

View File

@@ -1,4 +1,6 @@
using System; // 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 System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Collections.ObjectModel; using System.Collections.ObjectModel;
using System.Linq; using System.Linq;

View File

@@ -1,4 +1,6 @@
using JetBrains.Annotations; // 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; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -30,6 +32,11 @@ namespace WireMock
/// </summary> /// </summary>
public string AbsoluteUrl { get; } public string AbsoluteUrl { get; }
/// <summary>
/// The ProxyUrl (if a proxy is used).
/// </summary>
public string ProxyUrl { get; set; }
/// <summary> /// <summary>
/// Gets the DateTime. /// Gets the DateTime.
/// </summary> /// </summary>
@@ -110,6 +117,11 @@ namespace WireMock
/// </summary> /// </summary>
public string DetectedBodyTypeFromContentType { get; } public string DetectedBodyTypeFromContentType { get; }
/// <summary>
/// The detected compression from the Content-Encoding header. Convenience getter for Handlebars.
/// </summary>
public string DetectedCompression { get; }
/// <summary> /// <summary>
/// Gets the Host /// Gets the Host
/// </summary> /// </summary>
@@ -168,6 +180,7 @@ namespace WireMock
BodyAsBytes = BodyData?.BodyAsBytes; BodyAsBytes = BodyData?.BodyAsBytes;
DetectedBodyType = BodyData?.DetectedBodyType.ToString(); DetectedBodyType = BodyData?.DetectedBodyType.ToString();
DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString(); DetectedBodyTypeFromContentType = BodyData?.DetectedBodyTypeFromContentType.ToString();
DetectedCompression = BodyData?.DetectedCompression;
Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value)); Headers = headers?.ToDictionary(header => header.Key, header => new WireMockList<string>(header.Value));
Cookies = cookies; Cookies = cookies;

View File

@@ -1,3 +1,5 @@
// 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 System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
@@ -341,11 +343,25 @@ namespace WireMock.ResponseBuilders
if (ProxyUrl != null && _httpClientForProxy != null) if (ProxyUrl != null && _httpClientForProxy != null)
{ {
var requestUri = new Uri(requestMessage.Url); string RemoveFirstOccurrence(string source, string find)
var proxyUri = new Uri(ProxyUrl); {
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); int place = source.IndexOf(find, StringComparison.OrdinalIgnoreCase);
return place >= 0 ? source.Remove(place, find.Length) : source;
}
return await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, !settings.DisableJsonBodyParsing.GetValueOrDefault(false)); 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;
return await HttpClientHelper.SendAsync(
_httpClientForProxy,
requestMessage,
requestMessage.ProxyUrl,
!settings.DisableJsonBodyParsing.GetValueOrDefault(false),
!settings.DisableRequestBodyDecompressing.GetValueOrDefault(false)
);
} }
ResponseMessage responseMessage; ResponseMessage responseMessage;

View File

@@ -1,4 +1,6 @@
using System.Collections.Generic; // 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 System.Collections.Generic;
using System.Linq; using System.Linq;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Types; using WireMock.Types;

View File

@@ -1,4 +1,6 @@
using JetBrains.Annotations; // 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 System.Threading.Tasks;
using WireMock.Settings; using WireMock.Settings;

View File

@@ -20,6 +20,7 @@ namespace WireMock.Serialization
AbsolutePath = logEntry.RequestMessage.AbsolutePath, AbsolutePath = logEntry.RequestMessage.AbsolutePath,
Url = logEntry.RequestMessage.Url, Url = logEntry.RequestMessage.Url,
AbsoluteUrl = logEntry.RequestMessage.AbsoluteUrl, AbsoluteUrl = logEntry.RequestMessage.AbsoluteUrl,
ProxyUrl = logEntry.RequestMessage.ProxyUrl,
Query = logEntry.RequestMessage.Query, Query = logEntry.RequestMessage.Query,
Method = logEntry.RequestMessage.Method, Method = logEntry.RequestMessage.Method,
Headers = logEntry.RequestMessage.Headers, Headers = logEntry.RequestMessage.Headers,

View File

@@ -1,4 +1,6 @@
using System; // 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 System;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
using WireMock.Settings; using WireMock.Settings;

View File

@@ -275,7 +275,13 @@ namespace WireMock.Server
var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url); var proxyUri = new Uri(settings.ProxyAndRecordSettings.Url);
var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery); var proxyUriWithRequestPathAndQuery = new Uri(proxyUri, requestUri.PathAndQuery);
var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri, !settings.DisableJsonBodyParsing.GetValueOrDefault(false)); var responseMessage = await HttpClientHelper.SendAsync(
_httpClientForProxy,
requestMessage,
proxyUriWithRequestPathAndQuery.AbsoluteUri,
!settings.DisableJsonBodyParsing.GetValueOrDefault(false),
!settings.DisableRequestBodyDecompressing.GetValueOrDefault(false)
);
if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) && if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
(settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile)) (settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile))

View File

@@ -1,11 +1,13 @@
using JetBrains.Annotations; // This source file is based on mock4net by Alexandre Victoor which is licensed under the Apache 2.0 License.
using Newtonsoft.Json; // For more details see 'mock4net/LICENSE.txt' and 'mock4net/readme.md' in this project root.
using System; using System;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Exceptions; using WireMock.Exceptions;
using WireMock.Handlers; using WireMock.Handlers;
@@ -17,7 +19,6 @@ using WireMock.RequestBuilders;
using WireMock.ResponseProviders; using WireMock.ResponseProviders;
using WireMock.Serialization; using WireMock.Serialization;
using WireMock.Settings; using WireMock.Settings;
using WireMock.Util;
using WireMock.Validation; using WireMock.Validation;
namespace WireMock.Server namespace WireMock.Server

View File

@@ -151,5 +151,11 @@ namespace WireMock.Settings
/// </summary> /// </summary>
[PublicAPI] [PublicAPI]
bool? DisableJsonBodyParsing { get; set; } bool? DisableJsonBodyParsing { get; set; }
/// <summary>
/// Disable support for GZip and Deflate request body decompression. (default set to false).
/// </summary>
[PublicAPI]
bool? DisableRequestBodyDecompressing { get; set; }
} }
} }

View File

@@ -103,10 +103,15 @@ namespace WireMock.Settings
public bool? AllowBodyForAllHttpMethods { get; set; } public bool? AllowBodyForAllHttpMethods { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/> /// <inheritdoc cref="IWireMockServerSettings.AllowOnlyDefinedHttpStatusCodeInResponse"/>
[PublicAPI]
public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; } public bool? AllowOnlyDefinedHttpStatusCodeInResponse { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.DisableJsonBodyParsing"/> /// <inheritdoc cref="IWireMockServerSettings.DisableJsonBodyParsing"/>
[PublicAPI] [PublicAPI]
public bool? DisableJsonBodyParsing { get; set; } public bool? DisableJsonBodyParsing { get; set; }
/// <inheritdoc cref="IWireMockServerSettings.DisableRequestBodyDecompressing"/>
[PublicAPI]
public bool? DisableRequestBodyDecompressing { get; set; }
} }
} }

View File

@@ -5,7 +5,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsFile internal static class HandlebarsFile
{ {
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler) public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
{ {

View File

@@ -1,25 +0,0 @@
using HandlebarsDotNet;
using WireMock.Handlers;
namespace WireMock.Transformers
{
internal static class HandlebarsHelpers
{
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
{
HandleBarsRegex.Register(handlebarsContext);
HandleBarsJsonPath.Register(handlebarsContext);
HandleBarsLinq.Register(handlebarsContext);
HandleBarsRandom.Register(handlebarsContext);
HandleBarsXeger.Register(handlebarsContext);
HandleBarsXPath.Register(handlebarsContext);
HandleBarsFile.Register(handlebarsContext, fileSystemHandler);
}
}
}

View File

@@ -9,7 +9,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsJsonPath internal static class HandlebarsJsonPath
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -9,7 +9,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsLinq internal static class HandlebarsLinq
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -11,7 +11,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsRandom internal static class HandlebarsRandom
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -7,7 +7,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsRegex internal static class HandlebarsRegex
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -10,7 +10,7 @@ using Wmhelp.XPath2;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsXPath internal static class HandlebarsXPath
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -5,7 +5,7 @@ using WireMock.Validation;
namespace WireMock.Transformers namespace WireMock.Transformers
{ {
internal static class HandleBarsXeger internal static class HandlebarsXeger
{ {
public static void Register(IHandlebars handlebarsContext) public static void Register(IHandlebars handlebarsContext)
{ {

View File

@@ -24,7 +24,7 @@ namespace WireMock.Transformers
{ {
var handlebars = Handlebars.Create(HandlebarsConfiguration); var handlebars = Handlebars.Create(HandlebarsConfiguration);
HandlebarsHelpers.Register(handlebars, _fileSystemHandler); WireMockHandlebarsHelpers.Register(handlebars, _fileSystemHandler);
_action?.Invoke(handlebars, _fileSystemHandler); _action?.Invoke(handlebars, _fileSystemHandler);

View File

@@ -5,6 +5,7 @@ using Newtonsoft.Json.Linq;
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Linq; using System.Linq;
using System.Text;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using WireMock.Validation; using WireMock.Validation;
@@ -106,6 +107,7 @@ namespace WireMock.Transformers
responseMessage.BodyData = new BodyData responseMessage.BodyData = new BodyData
{ {
Encoding = original.BodyData.Encoding,
DetectedBodyType = original.BodyData.DetectedBodyType, DetectedBodyType = original.BodyData.DetectedBodyType,
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
BodyAsJson = jToken BodyAsJson = jToken
@@ -195,6 +197,7 @@ namespace WireMock.Transformers
responseMessage.BodyData = new BodyData responseMessage.BodyData = new BodyData
{ {
Encoding = original.BodyData.Encoding,
DetectedBodyType = original.BodyData.DetectedBodyType, DetectedBodyType = original.BodyData.DetectedBodyType,
DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType, DetectedBodyTypeFromContentType = original.BodyData.DetectedBodyTypeFromContentType,
BodyAsString = templateBodyAsString(template) BodyAsString = templateBodyAsString(template)

View File

@@ -0,0 +1,30 @@
using HandlebarsDotNet;
using HandlebarsDotNet.Helpers;
using WireMock.Handlers;
namespace WireMock.Transformers
{
internal static class WireMockHandlebarsHelpers
{
public static void Register(IHandlebars handlebarsContext, IFileSystemHandler fileSystemHandler)
{
// Register https://github.com/StefH/Handlebars.Net.Helpers
HandlebarsHelpers.Register(handlebarsContext);
// Register WireMock.Net specific helpers
HandlebarsRegex.Register(handlebarsContext);
HandlebarsJsonPath.Register(handlebarsContext);
HandlebarsLinq.Register(handlebarsContext);
HandlebarsRandom.Register(handlebarsContext);
HandlebarsXeger.Register(handlebarsContext);
HandlebarsXPath.Register(handlebarsContext);
HandlebarsFile.Register(handlebarsContext, fileSystemHandler);
}
}
}

View File

@@ -52,5 +52,10 @@ namespace WireMock.Util
/// The detected body type (detection based on Content-Type). /// The detected body type (detection based on Content-Type).
/// </summary> /// </summary>
public BodyType DetectedBodyTypeFromContentType { get; set; } public BodyType DetectedBodyTypeFromContentType { get; set; }
/// <summary>
/// The detected compression.
/// </summary>
public string DetectedCompression { get; set; }
} }
} }

View File

@@ -5,7 +5,6 @@ using System.Net.Http.Headers;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json;
using WireMock.Http; using WireMock.Http;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.Types; using WireMock.Types;
@@ -108,15 +107,17 @@ namespace WireMock.Util
return BodyType.Bytes; return BodyType.Bytes;
} }
public static async Task<BodyData> Parse([NotNull] Stream stream, [CanBeNull] string contentType = null, bool deserializeJson = true) public static async Task<BodyData> Parse([NotNull] BodyParserSettings settings)
{ {
Check.NotNull(stream, nameof(stream)); Check.NotNull(settings, nameof(settings));
var bodyWithContentEncoding = await ReadBytesAsync(settings.Stream, settings.ContentEncoding, settings.DecompressGZipAndDeflate);
var data = new BodyData var data = new BodyData
{ {
BodyAsBytes = await ReadBytesAsync(stream), BodyAsBytes = bodyWithContentEncoding.Value,
DetectedCompression = bodyWithContentEncoding.Key,
DetectedBodyType = BodyType.Bytes, DetectedBodyType = BodyType.Bytes,
DetectedBodyTypeFromContentType = DetectBodyTypeFromContentType(contentType) DetectedBodyTypeFromContentType = DetectBodyTypeFromContentType(settings.ContentType)
}; };
// In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is // In case of MultiPart: check if the BodyAsBytes is a valid UTF8 or ASCII string, in that case read as String else keep as-is
@@ -141,7 +142,7 @@ namespace WireMock.Util
data.DetectedBodyType = BodyType.String; data.DetectedBodyType = BodyType.String;
// If string is not null or empty, try to deserialize the string to a JObject // If string is not null or empty, try to deserialize the string to a JObject
if (deserializeJson && !string.IsNullOrEmpty(data.BodyAsString)) if (settings.DeserializeJson && !string.IsNullOrEmpty(data.BodyAsString))
{ {
try try
{ {
@@ -161,12 +162,21 @@ namespace WireMock.Util
return data; return data;
} }
private static async Task<byte[]> ReadBytesAsync(Stream stream)
private static async Task<KeyValuePair<string, byte[]>> ReadBytesAsync(Stream stream, string contentEncoding = null, bool decompressGZipAndDeflate = true)
{ {
using (var memoryStream = new MemoryStream()) using (var memoryStream = new MemoryStream())
{ {
await stream.CopyToAsync(memoryStream); await stream.CopyToAsync(memoryStream);
return memoryStream.ToArray(); byte[] data = memoryStream.ToArray();
string type = contentEncoding?.ToLowerInvariant();
if (decompressGZipAndDeflate && (type == "gzip" || type == "deflate"))
{
return new KeyValuePair<string, byte[]>(type, CompressionUtils.Decompress(type, data));
}
return new KeyValuePair<string, byte[]>(null, data);
} }
} }
} }

View File

@@ -0,0 +1,17 @@
using System.IO;
namespace WireMock.Util
{
internal class BodyParserSettings
{
public Stream Stream { get; set; }
public string ContentType { get; set; }
public string ContentEncoding { get; set; }
public bool DecompressGZipAndDeflate { get; set; } = true;
public bool DeserializeJson { get; set; } = true;
}
}

View File

@@ -1,29 +0,0 @@
using FastDeepCloner;
using System;
using System.Runtime.Serialization;
namespace WireMock.Util
{
internal static class CloneUtils
{
private static FastDeepClonerSettings settings = new FastDeepCloner.FastDeepClonerSettings()
{
FieldType = FastDeepCloner.FieldType.FieldInfo,
OnCreateInstance = new FastDeepCloner.Extensions.CreateInstance((Type type) =>
{
#if !NETSTANDARD1_3
return FormatterServices.GetUninitializedObject(type);
#else
#endif
})
};
public static T DeepClone<T>(T objectToBeCloned) where T : class
{
//return CloneExtensionsEx.CloneFactory.GetClone(objectToBeCloned);
// Expression.Lambda<Func<object>>(Expression.New(type)).Compile()
return FastDeepCloner.DeepCloner.Clone(objectToBeCloned, settings);
}
}
}

View File

@@ -0,0 +1,49 @@
using System;
using System.IO;
using System.IO.Compression;
namespace WireMock.Util
{
internal static class CompressionUtils
{
public static byte[] Compress(string contentEncoding, byte[] data)
{
using (var compressedStream = new MemoryStream())
using (var zipStream = Create(contentEncoding, compressedStream, CompressionMode.Compress))
{
zipStream.Write(data, 0, data.Length);
#if !NETSTANDARD1_3
zipStream.Close();
#endif
return compressedStream.ToArray();
}
}
public static byte[] Decompress(string contentEncoding, byte[] data)
{
using (var compressedStream = new MemoryStream(data))
using (var zipStream = Create(contentEncoding, compressedStream, CompressionMode.Decompress))
using (var resultStream = new MemoryStream())
{
zipStream.CopyTo(resultStream);
return resultStream.ToArray();
}
}
private static Stream Create(string contentEncoding, Stream stream, CompressionMode mode)
{
switch (contentEncoding)
{
case "gzip":
return new GZipStream(stream, mode);
case "deflate":
return new DeflateStream(stream, mode);
default:
throw new NotSupportedException($"ContentEncoding '{contentEncoding}' is not supported.");
}
}
}
}

View File

@@ -1,26 +0,0 @@
using System.Collections.Generic;
using System.Linq;
namespace WireMock.Util
{
public class IndexableDictionary<TKey, TValue> : Dictionary<TKey, TValue>
{
/// <summary>
/// Gets the value associated with the specified index.
/// </summary>
/// <param name="index"> The index of the value to get.</param>
/// <returns>The value associated with the specified index.</returns>
public TValue this[int index]
{
get
{
// get the item for that index.
if (index < 0 || index > Count)
{
throw new KeyNotFoundException();
}
return Values.Cast<TValue>().ToArray()[index];
}
}
}
}

View File

@@ -1,80 +0,0 @@
using System;
using System.Collections.Concurrent;
using System.Threading;
namespace WireMock.Util
{
/// <summary>
/// http://johnculviner.com/achieving-named-lock-locker-functionality-in-c-4-0/
/// </summary>
internal class NamedReaderWriterLocker
{
private readonly ConcurrentDictionary<string, ReaderWriterLockSlim> _lockDict = new ConcurrentDictionary<string, ReaderWriterLockSlim>();
public ReaderWriterLockSlim GetLock(string name)
{
return _lockDict.GetOrAdd(name, s => new ReaderWriterLockSlim());
}
public TResult RunWithReadLock<TResult>(string name, Func<TResult> body)
{
var rwLock = GetLock(name);
try
{
rwLock.EnterReadLock();
return body();
}
finally
{
rwLock.ExitReadLock();
}
}
public void RunWithReadLock(string name, Action body)
{
var rwLock = GetLock(name);
try
{
rwLock.EnterReadLock();
body();
}
finally
{
rwLock.ExitReadLock();
}
}
public TResult RunWithWriteLock<TResult>(string name, Func<TResult> body)
{
var rwLock = GetLock(name);
try
{
rwLock.EnterWriteLock();
return body();
}
finally
{
rwLock.ExitWriteLock();
}
}
public void RunWithWriteLock(string name, Action body)
{
var rwLock = GetLock(name);
try
{
rwLock.EnterWriteLock();
body();
}
finally
{
rwLock.ExitWriteLock();
}
}
public void RemoveLock(string name)
{
_lockDict.TryRemove(name, out _);
}
}
}

View File

@@ -16,7 +16,7 @@ namespace WireMock.Validation
internal static class Check internal static class Check
{ {
[ContractAnnotation("value:null => halt")] [ContractAnnotation("value:null => halt")]
public static T Condition<T>([NoEnumeration] T value, [NotNull] Predicate<T> condition, [InvokerParameterName] [NotNull] string parameterName) public static T Condition<T>([NoEnumeration] T value, [ValidatedNotNull, NotNull] Predicate<T> condition, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ {
NotNull(condition, nameof(condition)); NotNull(condition, nameof(condition));
NotNull(value, nameof(value)); NotNull(value, nameof(value));
@@ -32,7 +32,7 @@ namespace WireMock.Validation
} }
[ContractAnnotation("value:null => halt")] [ContractAnnotation("value:null => halt")]
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName) public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ {
if (ReferenceEquals(value, null)) if (ReferenceEquals(value, null))
{ {
@@ -45,7 +45,7 @@ namespace WireMock.Validation
} }
[ContractAnnotation("value:null => halt")] [ContractAnnotation("value:null => halt")]
public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName] [NotNull] string parameterName, [NotNull] string propertyName) public static T NotNull<T>([NoEnumeration] T value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName, [ValidatedNotNull, NotNull] string propertyName)
{ {
if (ReferenceEquals(value, null)) if (ReferenceEquals(value, null))
{ {
@@ -59,7 +59,7 @@ namespace WireMock.Validation
} }
[ContractAnnotation("value:null => halt")] [ContractAnnotation("value:null => halt")]
public static IList<T> NotNullOrEmpty<T>(IList<T> value, [InvokerParameterName] [NotNull] string parameterName) public static IList<T> NotNullOrEmpty<T>(IList<T> value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ {
NotNull(value, parameterName); NotNull(value, parameterName);
@@ -74,7 +74,7 @@ namespace WireMock.Validation
} }
[ContractAnnotation("value:null => halt")] [ContractAnnotation("value:null => halt")]
public static string NotNullOrEmpty(string value, [InvokerParameterName] [NotNull] string parameterName) public static string NotNullOrEmpty(string value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ {
Exception e = null; Exception e = null;
if (ReferenceEquals(value, null)) if (ReferenceEquals(value, null))
@@ -96,20 +96,20 @@ namespace WireMock.Validation
return value; return value;
} }
public static string NullButNotEmpty(string value, [InvokerParameterName] [NotNull] string parameterName) //public static string NullButNotEmpty(string value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ //{
if (!ReferenceEquals(value, null) // if (!ReferenceEquals(value, null)
&& (value.Length == 0)) // && (value.Length == 0))
{ // {
NotNullOrEmpty(parameterName, nameof(parameterName)); // NotNullOrEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName)); // throw new ArgumentException(CoreStrings.ArgumentIsEmpty(parameterName));
} // }
return value; // return value;
} //}
public static IList<T> HasNoNulls<T>(IList<T> value, [InvokerParameterName] [NotNull] string parameterName) public static IList<T> HasNoNulls<T>(IList<T> value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
where T : class where T : class
{ {
NotNull(value, parameterName); NotNull(value, parameterName);
@@ -124,16 +124,16 @@ namespace WireMock.Validation
return value; return value;
} }
public static Type ValidEntityType(Type value, [InvokerParameterName] [NotNull] string parameterName) //public static Type ValidEntityType(Type value, [InvokerParameterName, ValidatedNotNull, NotNull] string parameterName)
{ //{
if (!value.GetTypeInfo().IsClass) // if (!value.GetTypeInfo().IsClass)
{ // {
NotNullOrEmpty(parameterName, nameof(parameterName)); // NotNullOrEmpty(parameterName, nameof(parameterName));
throw new ArgumentException(CoreStrings.InvalidEntityType(value, parameterName)); // throw new ArgumentException(CoreStrings.InvalidEntityType(value, parameterName));
} // }
return value; // return value;
} //}
} }
} }

View File

@@ -0,0 +1,11 @@
using System;
namespace WireMock.Validation
{
/// <summary>
/// To fix 'xxx' is null on at least one execution path. See also https://rules.sonarsource.com/csharp/RSPEC-3900.
/// </summary>
internal class ValidatedNotNullAttribute : Attribute
{
}
}

View File

@@ -3,28 +3,17 @@
<Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description> <Description>Lightweight Http Mocking Server for .Net, inspired by WireMock from the Java landscape.</Description>
<AssemblyTitle>WireMock.Net</AssemblyTitle> <AssemblyTitle>WireMock.Net</AssemblyTitle>
<Authors>Stef Heyenrath</Authors> <Authors>Stef Heyenrath</Authors>
<!--<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netcoreapp2.1</TargetFrameworks>--> <TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;netstandard2.1</TargetFrameworks>
<!--<TargetFrameworks>net451;net452;net46;netstandard1.3;netstandard2.0</TargetFrameworks>-->
<TargetFrameworks>net451;net452;net46;net461;netstandard1.3;netstandard2.0;;netstandard2.1</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net</AssemblyName> <AssemblyName>WireMock.Net</AssemblyName>
<PackageId>WireMock.Net</PackageId> <PackageId>WireMock.Net</PackageId>
<PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags> <PackageTags>tdd;mock;http;wiremock;test;server;unittest</PackageTags>
<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>
<PackageLicenseExpression>MIT</PackageLicenseExpression>
<RepositoryType>git</RepositoryType>
<RepositoryUrl>https://github.com/WireMock-Net/WireMock.Net</RepositoryUrl>
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
<RootNamespace>WireMock</RootNamespace> <RootNamespace>WireMock</RootNamespace>
<!--<DebugType>full</DebugType>
<IncludeSource>True</IncludeSource>
<IncludeSymbols>True</IncludeSymbols>-->
<ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid> <ProjectGuid>{D3804228-91F4-4502-9595-39584E5A01AD}</ProjectGuid>
<PublishRepositoryUrl>true</PublishRepositoryUrl> <PublishRepositoryUrl>true</PublishRepositoryUrl>
<!--<AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder> <AllowedOutputExtensionsInPackageBuildOutputFolder>$(AllowedOutputExtensionsInPackageBuildOutputFolder);.pdb</AllowedOutputExtensionsInPackageBuildOutputFolder>
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects> <EmbedUntrackedSources>true</EmbedUntrackedSources>
<!--<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>--> <GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>-->
<SignAssembly>true</SignAssembly> <SignAssembly>true</SignAssembly>
<AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile> <AssemblyOriginatorKeyFile>WireMock.Net.snk</AssemblyOriginatorKeyFile>
@@ -36,7 +25,8 @@
<None Include="WireMock.Net-Logo.png" Pack="true" PackagePath="../../"/> <None Include="WireMock.Net-Logo.png" Pack="true" PackagePath="../../"/>
</ItemGroup>--> </ItemGroup>-->
<!--https://github.com/aspnet/RoslynCodeDomProvider/issues/51--> <!-- https://github.com/aspnet/RoslynCodeDomProvider/issues/51 -->
<!-- This is needed else we cannot build net452 in Azure DevOps Pipeline -->
<Target Name="CheckIfShouldKillVBCSCompiler" /> <Target Name="CheckIfShouldKillVBCSCompiler" />
<PropertyGroup Condition="'$(Configuration)' == 'Release'"> <PropertyGroup Condition="'$(Configuration)' == 'Release'">
@@ -61,33 +51,21 @@
</PropertyGroup> </PropertyGroup>
<ItemGroup> <ItemGroup>
<Compile Remove="Util\CloneUtils.cs" /> <PackageReference Include="JetBrains.Annotations" Version="2019.1.3" PrivateAssets="All" />
<Compile Remove="Util\IndexableDictionary.cs" /> <PackageReference Include="Microsoft.SourceLink.GitHub" Version="1.0.0" PrivateAssets="All" />
<Compile Remove="Util\NamedReaderWriterLocker.cs" />
</ItemGroup>
<ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="2019.1.3">
<PrivateAssets>all</PrivateAssets>
</PackageReference>
<!--<PackageReference Include="Microsoft.CSharp" Version="4.5.0" />-->
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" /> <PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
<PackageReference Include="Handlebars.Net.Helpers" Version="1.0.0" />
</ItemGroup>
<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
<PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320"> <PackageReference Include="SonarAnalyzer.CSharp" Version="7.8.0.7320">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' ">
<PackageReference Include="Handlebars.Net" Version="[1.9.0]" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'net451' ">
<PackageReference Include="Handlebars.Net" Version="1.9.5" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' != 'netstandard1.3' ">

View File

@@ -243,11 +243,29 @@ namespace WireMock.Net.Tests.RequestMatchers
// assign // assign
BodyData bodyData; BodyData bodyData;
if (body is byte[] b) if (body is byte[] b)
bodyData = await BodyParser.Parse(new MemoryStream(b), null, true); {
var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(b),
ContentType = null,
DeserializeJson = true
};
bodyData = await BodyParser.Parse(bodyParserSettings);
}
else if (body is string s) else if (body is string s)
bodyData = await BodyParser.Parse(new MemoryStream(Encoding.UTF8.GetBytes(s)), null, true); {
var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(Encoding.UTF8.GetBytes(s)),
ContentType = null,
DeserializeJson = true
};
bodyData = await BodyParser.Parse(bodyParserSettings);
}
else else
{
throw new Exception(); throw new Exception();
}
var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", bodyData); var requestMessage = new RequestMessage(new UrlDetails("http://localhost"), "GET", "127.0.0.1", bodyData);
@@ -265,7 +283,7 @@ namespace WireMock.Net.Tests.RequestMatchers
{ {
var json = "{'a':'b'}"; var json = "{'a':'b'}";
var str = "HelloWorld"; var str = "HelloWorld";
var bytes = new byte[] {0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00}; var bytes = new byte[] { 0xFF, 0xD8, 0xFF, 0xE0, 0x00, 0x10, 0x4A, 0x46, 0x49, 0x46, 0x00 };
return new TheoryData<object, RequestMessageBodyMatcher, bool> return new TheoryData<object, RequestMessageBodyMatcher, bool>
{ {

View File

@@ -0,0 +1,36 @@
using System.Threading.Tasks;
using NFluent;
using WireMock.Models;
using WireMock.ResponseBuilders;
using WireMock.Settings;
using WireMock.Types;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.ResponseBuilders
{
public class ResponseWithHandlebarsHelpersTests
{
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private const string ClientIp = "::1";
[Fact]
public async Task Response_ProvideResponseAsync_HandlebarsHelpers_String_Uppercase()
{
// Assign
var body = new BodyData { BodyAsString = "abc", DetectedBodyType = BodyType.String };
var request = new RequestMessage(new UrlDetails("http://localhost:1234"), "POST", ClientIp, body);
var response = Response.Create()
.WithBody("{{String.Uppercase request.body}}")
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// assert
Check.That(responseMessage.BodyData.BodyAsString).Equals("ABC");
}
}
}

View File

@@ -402,5 +402,31 @@ namespace WireMock.Net.Tests.ResponseBuilders
// Assert // Assert
Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("{\"name\":\"WireMock\"}"); Check.That(JsonConvert.SerializeObject(responseMessage.BodyData.BodyAsJson)).Equals("{\"name\":\"WireMock\"}");
} }
[Fact]
public async Task Response_ProvideResponse_Handlebars_WithBodyAsString_KeepsEncoding()
{
// Assign
const string text = "my-text";
Encoding enc = Encoding.Unicode;
var bodyData = new BodyData
{
BodyAsString = text,
DetectedBodyType = BodyType.String,
Encoding = enc
};
var request = new RequestMessage(new UrlDetails("http://localhost/foo_object"), "POST", ClientIp, bodyData);
var response = Response.Create()
.WithBody("{{request.body}}", BodyDestinationFormat.SameAsSource, enc)
.WithTransformer();
// Act
var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert
responseMessage.BodyData.BodyAsString.Should().Be(text);
responseMessage.BodyData.Encoding.Should().Be(enc);
}
} }
} }

View File

@@ -16,6 +16,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
{ {
public class ResponseWithProxyTests : IDisposable public class ResponseWithProxyTests : IDisposable
{ {
private const string ClientIp = "::1";
private readonly WireMockServerSettings _settings = new WireMockServerSettings(); private readonly WireMockServerSettings _settings = new WireMockServerSettings();
private readonly WireMockServer _server; private readonly WireMockServer _server;
private readonly Guid _guid; private readonly Guid _guid;
@@ -27,21 +28,32 @@ namespace WireMock.Net.Tests.ResponseBuilders
_server = WireMockServer.Start(); _server = WireMockServer.Start();
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}")) _server.Given(Request.Create().UsingPost().WithPath($"/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json")); .RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 42 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 10 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 11 }).WithHeader("Content-Type", "application/json"));
_server.Given(Request.Create().UsingPost().WithPath($"/prepend/{_guid}/append"))
.RespondWith(Response.Create().WithStatusCode(201).WithBodyAsJson(new { p = 12 }).WithHeader("Content-Type", "application/json"));
} }
[Fact] [Theory]
public async Task Response_WithProxy() [InlineData("", "", "{\"p\":42}")]
[InlineData("", "/append", "{\"p\":10}")]
[InlineData("/prepend", "", "{\"p\":11}")]
[InlineData("/prepend", "/append", "{\"p\":12}")]
public async Task Response_WithProxy(string prepend, string append, string expectedBody)
{ {
// Assign // Assign
var headers = new Dictionary<string, string[]> { { "Content-Type", new[] { "application/xml" } } }; var headers = new Dictionary<string, string[]> { { "Content-Type", new[] { "application/xml" } } };
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "POST", "::1", new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers); var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}{prepend}/{_guid}{append}"), "POST", ClientIp, new BodyData { DetectedBodyType = BodyType.Json, BodyAsJson = new { a = 1 } }, headers);
var response = Response.Create().WithProxy(_server.Urls[0]); var response = Response.Create().WithProxy(_server.Urls[0]);
// Act // Act
var responseMessage = await response.ProvideResponseAsync(request, _settings); var responseMessage = await response.ProvideResponseAsync(request, _settings);
// Assert // Assert
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo("{\"p\":42}"); Check.That(request.ProxyUrl).IsNotNull();
Check.That(responseMessage.BodyData.BodyAsString).IsEqualTo(expectedBody);
Check.That(responseMessage.StatusCode).IsEqualTo(201); Check.That(responseMessage.StatusCode).IsEqualTo(201);
Check.That(responseMessage.Headers["Content-Type"].ToString()).IsEqualTo("application/json"); Check.That(responseMessage.Headers["Content-Type"].ToString()).IsEqualTo("application/json");
} }
@@ -63,7 +75,7 @@ namespace WireMock.Net.Tests.ResponseBuilders
var response = Response.Create().WithProxy(settings); var response = Response.Create().WithProxy(settings);
// Act // Act
var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "GET", "::1"); var request = new RequestMessage(new UrlDetails($"{_server.Urls[0]}/{_guid}"), "GET", ClientIp);
Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settings)).Throws<HttpRequestException>(); Check.ThatAsyncCode(() => response.ProvideResponseAsync(request, _settings)).Throws<HttpRequestException>();
} }

View File

@@ -1,7 +1,10 @@
using NFluent; using System;
using NFluent;
using System.IO; using System.IO;
using System.IO.Compression;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using FluentAssertions;
using WireMock.Types; using WireMock.Types;
using WireMock.Util; using WireMock.Util;
using Xunit; using Xunit;
@@ -19,10 +22,15 @@ namespace WireMock.Net.Tests.Util
public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType) public async Task BodyParser_Parse_ContentTypeJson(string contentType, string bodyAsJson, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{ {
// Arrange // Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson)); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsJson)),
ContentType = contentType,
DeserializeJson = true
};
// Act // Act
var body = await BodyParser.Parse(memoryStream, contentType, true); var body = await BodyParser.Parse(bodyParserSettings);
// Assert // Assert
Check.That(body.BodyAsBytes).IsNotNull(); Check.That(body.BodyAsBytes).IsNotNull();
@@ -38,10 +46,15 @@ namespace WireMock.Net.Tests.Util
public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType) public async Task BodyParser_Parse_ContentTypeString(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{ {
// Arrange // Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)),
ContentType = contentType,
DeserializeJson = true
};
// Act // Act
var body = await BodyParser.Parse(memoryStream, contentType, true); var body = await BodyParser.Parse(bodyParserSettings);
// Assert // Assert
Check.That(body.BodyAsBytes).IsNotNull(); Check.That(body.BodyAsBytes).IsNotNull();
@@ -52,16 +65,21 @@ namespace WireMock.Net.Tests.Util
} }
[Theory] [Theory]
[InlineData(new byte[] {34, 97, 34}, BodyType.Json)] [InlineData(new byte[] { 34, 97, 34 }, BodyType.Json)]
[InlineData(new byte[] {97}, BodyType.String)] [InlineData(new byte[] { 97 }, BodyType.String)]
[InlineData(new byte[] {0xFF, 0xD8, 0xFF, 0xE0}, BodyType.Bytes)] [InlineData(new byte[] { 0xFF, 0xD8, 0xFF, 0xE0 }, BodyType.Bytes)]
public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType) public async Task BodyParser_Parse_DetectedBodyType(byte[] content, BodyType detectedBodyType)
{ {
// arrange // arrange
var memoryStream = new MemoryStream(content); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(content),
ContentType = null,
DeserializeJson = true
};
// act // act
var body = await BodyParser.Parse(memoryStream, null, true); var body = await BodyParser.Parse(bodyParserSettings);
// assert // assert
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
@@ -74,10 +92,15 @@ namespace WireMock.Net.Tests.Util
public async Task BodyParser_Parse_DetectedBodyTypeNoJsonParsing(byte[] content, BodyType detectedBodyType) public async Task BodyParser_Parse_DetectedBodyTypeNoJsonParsing(byte[] content, BodyType detectedBodyType)
{ {
// arrange // arrange
var memoryStream = new MemoryStream(content); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(content),
ContentType = null,
DeserializeJson = false
};
// act // act
var body = await BodyParser.Parse(memoryStream, null, false); var body = await BodyParser.Parse(bodyParserSettings);
// assert // assert
Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType); Check.That(body.DetectedBodyType).IsEqualTo(detectedBodyType);
@@ -108,10 +131,15 @@ Content-Type: text/html
-----------------------------9051914041544843365972754266--"; -----------------------------9051914041544843365972754266--";
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(body)); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(Encoding.UTF8.GetBytes(body)),
ContentType = contentType,
DeserializeJson = true
};
// Act // Act
var result = await BodyParser.Parse(memoryStream, contentType, true); var result = await BodyParser.Parse(bodyParserSettings);
// Assert // Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String); Check.That(result.DetectedBodyType).IsEqualTo(BodyType.String);
@@ -127,11 +155,15 @@ Content-Type: text/html
// Arrange // Arrange
string contentType = "multipart/form-data"; string contentType = "multipart/form-data";
string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE string body = char.ConvertFromUtf32(0x1D161); //U+1D161 = MUSICAL SYMBOL SIXTEENTH NOTE
var bodyParserSettings = new BodyParserSettings
var memoryStream = new MemoryStream(Encoding.UTF32.GetBytes(body)); {
Stream = new MemoryStream(Encoding.UTF8.GetBytes(body)),
ContentType = contentType,
DeserializeJson = true
};
// Act // Act
var result = await BodyParser.Parse(memoryStream, contentType, true); var result = await BodyParser.Parse(bodyParserSettings);
// Assert // Assert
Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes); Check.That(result.DetectedBodyType).IsEqualTo(BodyType.Bytes);
@@ -142,14 +174,19 @@ Content-Type: text/html
} }
[Theory] [Theory]
[InlineData(null, "hello", BodyType.String, BodyType.Bytes)] [InlineData("hello", BodyType.String, BodyType.Bytes)]
public async Task BodyParser_Parse_ContentTypeIsNull(string contentType, string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType) public async Task BodyParser_Parse_ContentTypeIsNull(string bodyAsString, BodyType detectedBodyType, BodyType detectedBodyTypeFromContentType)
{ {
// Arrange // Arrange
var memoryStream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)); var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(Encoding.UTF8.GetBytes(bodyAsString)),
ContentType = null,
DeserializeJson = true
};
// Act // Act
var body = await BodyParser.Parse(memoryStream, contentType, true); var body = await BodyParser.Parse(bodyParserSettings);
// Assert // Assert
Check.That(body.BodyAsBytes).IsNotNull(); Check.That(body.BodyAsBytes).IsNotNull();
@@ -159,6 +196,60 @@ Content-Type: text/html
Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType); Check.That(body.DetectedBodyTypeFromContentType).IsEqualTo(detectedBodyTypeFromContentType);
} }
[Theory]
[InlineData("gzip")]
[InlineData("deflate")]
public async Task BodyParser_Parse_ContentEncoding_GZip_And_DecompressGzipAndDeflate_Is_True_Should_Decompress(string compression)
{
// Arrange
var bytes = Encoding.ASCII.GetBytes("0");
var compressed = CompressionUtils.Compress(compression, bytes);
var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(compressed),
ContentType = "text/plain",
DeserializeJson = false,
ContentEncoding = compression.ToUpperInvariant(),
DecompressGZipAndDeflate = true
};
// Act
var result = await BodyParser.Parse(bodyParserSettings);
// Assert
result.DetectedBodyType.Should().Be(BodyType.String);
result.DetectedBodyTypeFromContentType.Should().Be(BodyType.String);
result.BodyAsBytes.Should().BeEquivalentTo(new byte[] { 48 });
result.BodyAsJson.Should().BeNull();
result.BodyAsString.Should().Be("0");
result.DetectedCompression.Should().Be(compression);
}
[Theory]
[InlineData("gzip")]
[InlineData("deflate")]
public async Task BodyParser_Parse_ContentEncoding_GZip_And_DecompressGzipAndDeflate_Is_False_Should_Not_Decompress(string compression)
{
// Arrange
var bytes = Encoding.ASCII.GetBytes(Guid.NewGuid().ToString());
var compressed = CompressionUtils.Compress(compression, bytes);
var bodyParserSettings = new BodyParserSettings
{
Stream = new MemoryStream(compressed),
ContentType = "text/plain",
DeserializeJson = false,
ContentEncoding = compression.ToUpperInvariant(),
DecompressGZipAndDeflate = false
};
// Act
var result = await BodyParser.Parse(bodyParserSettings);
// Assert
result.BodyAsBytes.Should().BeEquivalentTo(compressed);
result.DetectedCompression.Should().BeNull();
}
[Theory] [Theory]
[InlineData("HEAD", false)] [InlineData("HEAD", false)]
[InlineData("GET", false)] [InlineData("GET", false)]

View File

@@ -35,21 +35,21 @@
</ItemGroup> </ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="Codecov" Version="1.1.0" /> <PackageReference Include="Codecov" Version="1.10.0" />
<PackageReference Include="coverlet.msbuild" Version="2.3.1"> <PackageReference Include="coverlet.msbuild" Version="2.8.1">
<PrivateAssets>all</PrivateAssets> <PrivateAssets>all</PrivateAssets>
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets> <IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
</PackageReference> </PackageReference>
<PackageReference Include="FluentAssertions" Version="5.7.0" /> <PackageReference Include="FluentAssertions" Version="5.10.3" />
<PackageReference Include="System.Threading" Version="4.3.0" /> <PackageReference Include="System.Threading" Version="4.3.0" />
<PackageReference Include="RestEase" Version="1.4.10" /> <PackageReference Include="RestEase" Version="1.4.10" />
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" /> <PackageReference Include="RandomDataGenerator.Net" Version="1.0.10" />
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" /> <PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
<PackageReference Include="Moq" Version="4.10.1" /> <PackageReference Include="Moq" Version="4.13.1" />
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" /> <PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
<PackageReference Include="NFluent" Version="2.5.0" /> <PackageReference Include="NFluent" Version="2.7.0" />
<PackageReference Include="OpenCover" Version="4.6.519" /> <PackageReference Include="OpenCover" Version="4.7.922" />
<PackageReference Include="ReportGenerator" Version="3.1.2" /> <PackageReference Include="ReportGenerator" Version="4.5.4" />
<PackageReference Include="SimMetrics.Net" Version="1.0.5" /> <PackageReference Include="SimMetrics.Net" Version="1.0.5" />
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" /> <PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
<PackageReference Include="xunit" Version="2.4.1" /> <PackageReference Include="xunit" Version="2.4.1" />

View File

@@ -1,13 +1,17 @@
using System; using System;
using System.Diagnostics; using System.Diagnostics;
using System.IO;
using System.IO.Compression;
using System.Net; using System.Net;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Headers; using System.Net.Http.Headers;
using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
using NFluent; using NFluent;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Server; using WireMock.Server;
using WireMock.Util;
using Xunit; using Xunit;
namespace WireMock.Net.Tests namespace WireMock.Net.Tests
@@ -252,5 +256,35 @@ namespace WireMock.Net.Tests
Check.That(response.StatusCode).Equals(HttpStatusCode.Created); Check.That(response.StatusCode).Equals(HttpStatusCode.Created);
Check.That(await response.Content.ReadAsStringAsync()).Contains("Mapping added"); Check.That(await response.Content.ReadAsStringAsync()).Contains("Mapping added");
} }
[Theory]
[InlineData("gzip")]
[InlineData("deflate")]
public async Task WireMockServer_Should_SupportRequestGZipAndDeflate(string contentEncoding)
{
// Arrange
const string body = "hello wiremock";
byte[] compressed = CompressionUtils.Compress(contentEncoding, Encoding.UTF8.GetBytes(body));
var server = WireMockServer.Start();
server.Given(
Request.Create()
.WithPath("/foo")
.WithBody("hello wiremock")
)
.RespondWith(
Response.Create().WithBody("OK")
);
var content = new StreamContent(new MemoryStream(compressed));
content.Headers.ContentType = new MediaTypeHeaderValue("text/plain");
content.Headers.ContentEncoding.Add(contentEncoding);
// Act
var response = await new HttpClient().PostAsync($"{server.Urls[0]}/foo", content);
// Assert
Check.That(await response.Content.ReadAsStringAsync()).Contains("OK");
}
} }
} }