mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-01-11 22:30:41 +01:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
2d95167866 | ||
|
|
b14bc01bf2 | ||
|
|
c104b8beba | ||
|
|
09533f1e3a | ||
|
|
a0fdc002c8 | ||
|
|
e107b5cfca | ||
|
|
5d3cbdbfc6 | ||
|
|
b8cbeb55b9 | ||
|
|
5b083d753e | ||
|
|
99dbb3f9b6 | ||
|
|
6b3bbd8540 | ||
|
|
c465ecdd40 |
15
CHANGELOG.md
15
CHANGELOG.md
@@ -1,3 +1,18 @@
|
||||
# 1.3.6 (10 November 2020)
|
||||
- [#529](https://github.com/WireMock-Net/WireMock.Net/pull/529) - Add assertions for ClientIP, Url and ProxyUrl [feature] contributed by [akamud](https://github.com/akamud)
|
||||
- [#535](https://github.com/WireMock-Net/WireMock.Net/pull/535) - WithCallback should use also use enum HttpStatusCode [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#537](https://github.com/WireMock-Net/WireMock.Net/pull/537) - Add Custom Certificate settings [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#533](https://github.com/WireMock-Net/WireMock.Net/issues/533) - Stubbed response with only callback returns unexpected status code. [bug]
|
||||
- [#536](https://github.com/WireMock-Net/WireMock.Net/issues/536) - Overriding the default ssl certificate via file. [feature]
|
||||
|
||||
# 1.3.5 (04 November 2020)
|
||||
- [#530](https://github.com/WireMock-Net/WireMock.Net/pull/530) - Fix dotnet-sonarscanner [bug] contributed by [StefH](https://github.com/StefH)
|
||||
- [#531](https://github.com/WireMock-Net/WireMock.Net/pull/531) - Add WithCallback-Async [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.3.4 (17 October 2020)
|
||||
- [#522](https://github.com/WireMock-Net/WireMock.Net/pull/522) - Add ContinuousIntegrationBuild property [feature] contributed by [StefH](https://github.com/StefH)
|
||||
- [#525](https://github.com/WireMock-Net/WireMock.Net/pull/525) - Handlebars.Net.Helpers Version="1.1.0" [feature] contributed by [StefH](https://github.com/StefH)
|
||||
|
||||
# 1.3.3 (15 October 2020)
|
||||
- [#520](https://github.com/WireMock-Net/WireMock.Net/pull/520) - Make kestrel limits configurable contributed by [eduherminio](https://github.com/eduherminio)
|
||||
- [#521](https://github.com/WireMock-Net/WireMock.Net/issues/521) - Make Kestrel limits configurable [feature]
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup>
|
||||
<VersionPrefix>1.3.3</VersionPrefix>
|
||||
<VersionPrefix>1.3.6</VersionPrefix>
|
||||
<PackageReleaseNotes>See CHANGELOG.md</PackageReleaseNotes>
|
||||
<PackageIconUrl>https://raw.githubusercontent.com/WireMock-Net/WireMock.Net/master/WireMock.Net-Logo.png</PackageIconUrl>
|
||||
<PackageProjectUrl>https://github.com/WireMock-Net/WireMock.Net</PackageProjectUrl>
|
||||
@@ -14,6 +14,10 @@
|
||||
<ApplicationIcon>../../WireMock.Net-Logo.ico</ApplicationIcon>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(TF_BUILD)' == 'true'">
|
||||
<ContinuousIntegrationBuild>true</ContinuousIntegrationBuild>
|
||||
</PropertyGroup>
|
||||
|
||||
<Choose>
|
||||
<!-- The environment variable `Prerelease` is set in the azure-pipelines.yml file. -->
|
||||
<When Condition=" '$(Prerelease)' != '' ">
|
||||
@@ -23,4 +27,4 @@
|
||||
</PropertyGroup>
|
||||
</When>
|
||||
</Choose>
|
||||
</Project>
|
||||
</Project>
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
https://github.com/StefH/GitHubReleaseNotes
|
||||
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.3.3
|
||||
GitHubReleaseNotes.exe --output CHANGELOG.md --skip-empty-releases --exclude-labels question invalid doc --version 1.3.6
|
||||
@@ -71,6 +71,8 @@ Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication
|
||||
EndProject
|
||||
Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "WireMock.Net.WebApplication.NETCore3", "examples\WireMock.Net.WebApplication.NETCore3\WireMock.Net.WebApplication.NETCore3.csproj", "{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}"
|
||||
EndProject
|
||||
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "WireMock.Net.Console.NETCoreApp3WithCertificate", "examples\WireMock.Net.Console.NETCoreApp3WithCertificate\WireMock.Net.Console.NETCoreApp3WithCertificate.csproj", "{925E421A-1B3F-4202-B48F-734743573A4B}"
|
||||
EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
@@ -173,6 +175,10 @@ Global
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
EndGlobalSection
|
||||
GlobalSection(SolutionProperties) = preSolution
|
||||
HideSolutionNode = FALSE
|
||||
@@ -202,6 +208,7 @@ Global
|
||||
{B6269AAC-170A-4346-8B9A-579DED3D9A95} = {8F890C6F-9ACC-438D-928A-AD61CDA862F2}
|
||||
{6F38CB3A-6DA1-408A-AECD-E434523C2838} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{E1C56967-3DC7-46CB-A1DF-B13167A0D9D4} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
{925E421A-1B3F-4202-B48F-734743573A4B} = {985E0ADB-D4B4-473A-AA40-567E279B7946}
|
||||
EndGlobalSection
|
||||
GlobalSection(ExtensibilityGlobals) = postSolution
|
||||
SolutionGuid = {DC539027-9852-430C-B19F-FD035D018458}
|
||||
|
||||
@@ -28,7 +28,7 @@
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.0.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.1.0" />
|
||||
<PackageReference Include="log4net" Version="2.0.8" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<!--<PackageReference Include="Microsoft.CodeAnalysis.Scripting.Common" Version="3.4.0" />-->
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
using WireMock.Logging;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
|
||||
namespace WireMock.Net.Console.NETCoreApp3WithCertificate
|
||||
{
|
||||
class Program
|
||||
{
|
||||
static void Main(string[] args)
|
||||
{
|
||||
string url = "https://localhost:8433/";
|
||||
|
||||
var server = WireMockServer.Start(new WireMockServerSettings
|
||||
{
|
||||
Urls = new[] { url },
|
||||
StartAdminInterface = true,
|
||||
Logger = new WireMockConsoleLogger(),
|
||||
CertificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
X509StoreName = "My",
|
||||
X509StoreLocation = "CurrentUser",
|
||||
X509StoreThumbprintOrSubjectName = "FE16586076A8B3F3E2F1466803A6C4C7CA35455B"
|
||||
|
||||
// X509CertificateFilePath = "example.pfx",
|
||||
// X509CertificatePassword = "wiremock"
|
||||
}
|
||||
|
||||
});
|
||||
System.Console.WriteLine("WireMockServer listening at {0}", string.Join(",", server.Urls));
|
||||
|
||||
System.Console.WriteLine("Press any key to stop the server");
|
||||
System.Console.ReadKey();
|
||||
server.Stop();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.StandAlone\WireMock.Net.StandAlone.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="example.pfx">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
@@ -0,0 +1,28 @@
|
||||
-----BEGIN CERTIFICATE-----
|
||||
MIIEsDCCApigAwIBAgIQJbH6hSGKdoFI0B7qCIOK7jANBgkqhkiG9w0BAQUFADAU
|
||||
MRIwEAYDVQQDEwlsb2NhbGhvc3QwHhcNMjAxMDMwMjMwMDAwWhcNMzAxMTA2MjMw
|
||||
MDAwWjAUMRIwEAYDVQQDEwlsb2NhbGhvc3QwggIiMA0GCSqGSIb3DQEBAQUAA4IC
|
||||
DwAwggIKAoICAQCl5fQSrRgT3Q6WoULR98Y+rrDWtTTgVpbLU04G0hLZ4yUeP7Wa
|
||||
yuVbvx7zX8XT4lA8Hu5T/GG91U077JcSSEjnPBFsh4hE7FkRoSYIEW6BFG7D7eUG
|
||||
dGHnDV8UkSRQ97LJPyjXuHVDJzNDJ9xQGMzOZ4n8vQ7SEKBw9hRG2ugkP5b2jVIN
|
||||
e1E549tq2jnIVpKCZ4+prf64ZLsaokX7VHe+b/CW3GoAqUUaUjdTpAQ7LpypJuFz
|
||||
415enOrKQe+UEBdqhGlgcC/O/Bw0uq4qVk+NNe5DEINVwoYs9XjNdzxuIkkAtcCt
|
||||
avTEzhHf8zWYLb5Nt2DIOcRGVELvRhsBX4um5f7dOGzMbXzBfUdjkP2O4hi6crhm
|
||||
Hba5bNkj4Zw2EHR9Xua3nadGCj22z0vpMKP2gXdFVnxFqQlaUWBLtwwN9p6tCQHl
|
||||
kU7wypvOHUsMa2Ojg5eZP4RpYFvZG3kkc9zTZCSakgw2n0ampBbvxPP11/AYIXtz
|
||||
HKu3CKcpjVQ+lE0DAU/Mm77QJ24TMbXmAydwCf1UCdFbDUZhdM9lspHvA0J9eiCv
|
||||
LOE94BrpVKuZ6TrAW0LZjAmBnkqYQAewhTW7GSgARE+QQcwfyu03Ck7id3Zt4FeQ
|
||||
sQDo0NNj7zQOy3Y1GK0ZYAVZv/GUeHMkxpClSWPoub/f5SJ4YzD5Il0cQQIDAQAB
|
||||
MA0GCSqGSIb3DQEBBQUAA4ICAQBd91xfUepnWcKwmupie2h1CAAQZEunyW78i++t
|
||||
evABfBu0TgV4s6Xe0umFv9V4r+O+rrF3ddSudbSOPBEb0Ooe+e3YGlNk1JrI1EEn
|
||||
fhb0YI8bMfBNpl85yNqxgByra7JF2mG4qbAnjrCs/PZkXo/34N29SY6dyZ7mffR3
|
||||
r/l01Rdm3ogRwGkiMUeKb3iGwLUy1T55svuI3Zc13N+NJT1s9NqpwWeK/jFK/WRN
|
||||
5Hi9W3DmlGCYAwFPCyBaQagxpGuGIpNsU0hKp86W5EvJpBpmCihfwlydH8ZbkHJ9
|
||||
jx2UDgTCaDzmaiKysiTP2HHDBsReL4tjakBksa9jkTfy5ajB53F3aUVs4jvTA46L
|
||||
w8wcAJlRPBz5siBrv4CH/0lBMyNeYzuqmDY3ulF4IMKNb5Kk9Ye4Pt0474z50A4v
|
||||
fSah+9iwI/mubaJ5tK522AtWtUoOIAswIwpDQyNeJPOggyzT2Y2OYZdGuFAoMYuq
|
||||
ZD58k4Yo+vky9K88l8NuzNJJvtgTKtT+/9qfMucxFmnvwbKEEULP3sw1FUKkPtM4
|
||||
f242FIV/XnOeloDmhGGeTB7aODB+gGCvgmOH92njjUEIv+SnYQkflQaRhhyNIACi
|
||||
ZvWlP/96H+X4fUG5kVNBHY021ZWmurUDqVxWUaswg63+DfsZcYtt6wgxiAN4ssXG
|
||||
wLnLPw==
|
||||
-----END CERTIFICATE-----
|
||||
Binary file not shown.
Binary file not shown.
@@ -12,6 +12,7 @@ using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Util;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace WireMock.Net.ConsoleApplication
|
||||
{
|
||||
@@ -249,6 +250,13 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithProxy("http://www.google.com")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithHeader("ProxyThisHttps", "true")
|
||||
.UsingGet())
|
||||
.RespondWith(Response.Create()
|
||||
.WithProxy("https://www.google.com")
|
||||
);
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/bodyasbytes.png")
|
||||
.UsingGet())
|
||||
@@ -521,9 +529,29 @@ namespace WireMock.Net.ConsoleApplication
|
||||
.WithBodyAsJson(new { Id = "5bdf076c-5654-4b3e-842c-7caf1fabf8c9" }));
|
||||
server
|
||||
.Given(Request.Create().WithPath("/random200or505").UsingGet())
|
||||
.RespondWith(Response.Create().WithCallback(request => new ResponseMessage
|
||||
.RespondWith(Response.Create().WithCallback(request =>
|
||||
{
|
||||
StatusCode = new Random().Next(1, 100) == 1 ? 504 : 200
|
||||
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
||||
return new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData { BodyAsString = "random200or505:" + code, DetectedBodyType = Types.BodyType.String },
|
||||
StatusCode = code
|
||||
};
|
||||
}));
|
||||
|
||||
server
|
||||
.Given(Request.Create().WithPath("/random200or505async").UsingGet())
|
||||
.RespondWith(Response.Create().WithCallback(async request =>
|
||||
{
|
||||
await Task.Delay(1);
|
||||
|
||||
int code = new Random().Next(1, 2) == 1 ? 505 : 200;
|
||||
|
||||
return new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData { BodyAsString = "random200or505async:" + code, DetectedBodyType = Types.BodyType.String },
|
||||
StatusCode = code
|
||||
};
|
||||
}));
|
||||
|
||||
System.Console.WriteLine(JsonConvert.SerializeObject(server.MappingModels, Formatting.Indented));
|
||||
|
||||
@@ -16,8 +16,7 @@ namespace WireMock.FluentAssertions
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> AtAbsoluteUrl(string absoluteUrl, string because = "",
|
||||
params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> AtAbsoluteUrl(string absoluteUrl, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
@@ -36,13 +35,11 @@ namespace WireMock.FluentAssertions
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value,
|
||||
string because = "", params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string value, string because = "", params object[] becauseArgs)
|
||||
=> WithHeader(expectedKey, new[] {value}, because, becauseArgs);
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues,
|
||||
string because = "", params object[] becauseArgs)
|
||||
public AndConstraint<WireMockAssertions> WithHeader(string expectedKey, string[] expectedValues, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
var headersDictionary = _subject.LogEntries.SelectMany(x => x.RequestMessage.Headers)
|
||||
.ToDictionary(x => x.Key, x => x.Value);
|
||||
@@ -72,5 +69,62 @@ namespace WireMock.FluentAssertions
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> AtUrl(string url, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but no calls were made.",
|
||||
url)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.Url == url))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called at address matching the url {0}{reason}, but didn't find it among the calls to {1}.",
|
||||
_ => url, requests => requests.Select(request => request.Url));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> WithProxyUrl(string proxyUrl, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but no calls were made.",
|
||||
proxyUrl)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.ProxyUrl == proxyUrl))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called with proxy url {0}{reason}, but didn't find it among the calls with {1}.",
|
||||
_ => proxyUrl, requests => requests.Select(request => request.ProxyUrl));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
|
||||
[CustomAssertion]
|
||||
public AndConstraint<WireMockAssertions> FromClientIP(string clientIP, string because = "", params object[] becauseArgs)
|
||||
{
|
||||
Execute.Assertion
|
||||
.BecauseOf(because, becauseArgs)
|
||||
.Given(() => _subject.LogEntries.Select(x => x.RequestMessage).ToList())
|
||||
.ForCondition(requests => requests.Any())
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but no calls were made.",
|
||||
clientIP)
|
||||
.Then
|
||||
.ForCondition(x => x.Any(y => y.ClientIP == clientIP))
|
||||
.FailWith(
|
||||
"Expected {context:wiremockserver} to have been called from client IP {0}{reason}, but didn't find it among the calls from IP(s) {1}.",
|
||||
_ => clientIP, requests => requests.Select(request => request.ClientIP));
|
||||
|
||||
return new AndConstraint<WireMockAssertions>(this);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,7 +41,7 @@ namespace WireMock.Http
|
||||
{
|
||||
handler.ClientCertificateOptions = ClientCertificateOption.Manual;
|
||||
|
||||
var x509Certificate2 = ClientCertificateHelper.GetCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName);
|
||||
var x509Certificate2 = CertificateLoader.LoadCertificate(settings.ClientX509Certificate2ThumbprintOrSubjectName);
|
||||
handler.ClientCertificates.Add(x509Certificate2);
|
||||
}
|
||||
|
||||
|
||||
100
src/WireMock.Net/HttpsCertificate/CertificateLoader.cs
Normal file
100
src/WireMock.Net/HttpsCertificate/CertificateLoader.cs
Normal file
@@ -0,0 +1,100 @@
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
{
|
||||
internal static class CertificateLoader
|
||||
{
|
||||
/// <summary>
|
||||
/// Used by the WireMock.Net server
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(
|
||||
string storeName,
|
||||
string storeLocation,
|
||||
string thumbprintOrSubjectName,
|
||||
string filePath,
|
||||
string password,
|
||||
string host)
|
||||
{
|
||||
if (!string.IsNullOrEmpty(storeName) && !string.IsNullOrEmpty(storeLocation))
|
||||
{
|
||||
var thumbprintOrSubjectNameOrHost = thumbprintOrSubjectName ?? host;
|
||||
|
||||
var certStore = new X509Store((StoreName)Enum.Parse(typeof(StoreName), storeName), (StoreLocation)Enum.Parse(typeof(StoreLocation), storeLocation));
|
||||
try
|
||||
{
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectNameOrHost, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException($"No Certificate found with in store '{storeName}', location '{storeLocation}' for Thumbprint or SubjectName '{thumbprintOrSubjectNameOrHost}'.");
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
|
||||
if (!string.IsNullOrEmpty(filePath) && !string.IsNullOrEmpty(password))
|
||||
{
|
||||
return new X509Certificate2(filePath, password);
|
||||
}
|
||||
|
||||
throw new InvalidOperationException("X509StoreName and X509StoreLocation OR X509CertificateFilePath and X509CertificatePassword are mandatory.");
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Used for Proxy
|
||||
/// </summary>
|
||||
public static X509Certificate2 LoadCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
var certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by Thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to SubjectName
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,42 +0,0 @@
|
||||
using System.IO;
|
||||
using System.Security.Cryptography.X509Certificates;
|
||||
|
||||
namespace WireMock.HttpsCertificate
|
||||
{
|
||||
internal static class ClientCertificateHelper
|
||||
{
|
||||
public static X509Certificate2 GetCertificate(string thumbprintOrSubjectName)
|
||||
{
|
||||
X509Store certStore = new X509Store(StoreName.My, StoreLocation.LocalMachine);
|
||||
try
|
||||
{
|
||||
// Certificate must be in the local machine store
|
||||
certStore.Open(OpenFlags.ReadOnly);
|
||||
|
||||
// Attempt to find by thumbprint first
|
||||
var matchingCertificates = certStore.Certificates.Find(X509FindType.FindByThumbprint, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// Fallback to subject name
|
||||
matchingCertificates = certStore.Certificates.Find(X509FindType.FindBySubjectName, thumbprintOrSubjectName, false);
|
||||
if (matchingCertificates.Count == 0)
|
||||
{
|
||||
// No certificates matched the search criteria.
|
||||
throw new FileNotFoundException("No certificate found with specified Thumbprint or SubjectName.", thumbprintOrSubjectName);
|
||||
}
|
||||
}
|
||||
|
||||
// Use the first matching certificate.
|
||||
return matchingCertificates[0];
|
||||
}
|
||||
finally
|
||||
{
|
||||
#if NETSTANDARD || NET46
|
||||
certStore.Dispose();
|
||||
#else
|
||||
certStore.Close();
|
||||
#endif
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,10 +1,10 @@
|
||||
#if USE_ASPNETCORE && !NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel.Core;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using WireMock.HttpsCertificate;
|
||||
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
@@ -18,20 +18,34 @@ namespace WireMock.Owin
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions kestrelOptions, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
{
|
||||
foreach (var detail in urlDetails)
|
||||
foreach (var urlDetail in urlDetails)
|
||||
{
|
||||
if (detail.Url.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
|
||||
if (urlDetail.IsHttps)
|
||||
{
|
||||
options.Listen(System.Net.IPAddress.Any, detail.Port, listenOptions =>
|
||||
kestrelOptions.Listen(System.Net.IPAddress.Any, urlDetail.Port, listenOptions =>
|
||||
{
|
||||
listenOptions.UseHttps();
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
listenOptions.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
listenOptions.UseHttps();
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
options.Listen(System.Net.IPAddress.Any, detail.Port);
|
||||
kestrelOptions.Listen(System.Net.IPAddress.Any, urlDetail.Port);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
#if USE_ASPNETCORE && NETSTANDARD1_3
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Microsoft.AspNetCore.Hosting;
|
||||
using Microsoft.AspNetCore.Server.Kestrel;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
@@ -19,12 +17,28 @@ namespace WireMock.Owin
|
||||
options.Limits.MaxResponseBufferSize = null;
|
||||
}
|
||||
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, ICollection<(string Url, int Port)> urlDetails)
|
||||
private static void SetHttpsAndUrls(KestrelServerOptions options, IWireMockMiddlewareOptions wireMockMiddlewareOptions, IEnumerable<HostUrlDetails> urlDetails)
|
||||
{
|
||||
var urls = urlDetails.Select(u => u.Url);
|
||||
if (urls.Any(u => u.StartsWith("https://", StringComparison.OrdinalIgnoreCase)))
|
||||
foreach (var urlDetail in urlDetails)
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
if (urlDetail.IsHttps)
|
||||
{
|
||||
if (wireMockMiddlewareOptions.CustomCertificateDefined)
|
||||
{
|
||||
options.UseHttps(CertificateLoader.LoadCertificate(
|
||||
wireMockMiddlewareOptions.X509StoreName,
|
||||
wireMockMiddlewareOptions.X509StoreLocation,
|
||||
wireMockMiddlewareOptions.X509ThumbprintOrSubjectName,
|
||||
wireMockMiddlewareOptions.X509CertificateFilePath,
|
||||
wireMockMiddlewareOptions.X509CertificatePassword,
|
||||
urlDetail.Host)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
options.UseHttps(PublicCertificateHelper.GetX509Certificate2());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -18,7 +18,7 @@ namespace WireMock.Owin
|
||||
internal partial class AspNetCoreSelfHost : IOwinSelfHost
|
||||
{
|
||||
private readonly CancellationTokenSource _cts = new CancellationTokenSource();
|
||||
private readonly IWireMockMiddlewareOptions _options;
|
||||
private readonly IWireMockMiddlewareOptions _wireMockMiddlewareOptions;
|
||||
private readonly IWireMockLogger _logger;
|
||||
private readonly HostUrlOptions _urlOptions;
|
||||
|
||||
@@ -33,14 +33,14 @@ namespace WireMock.Owin
|
||||
|
||||
public Exception RunningException => _runningException;
|
||||
|
||||
public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions options, [NotNull] HostUrlOptions urlOptions)
|
||||
public AspNetCoreSelfHost([NotNull] IWireMockMiddlewareOptions wireMockMiddlewareOptions, [NotNull] HostUrlOptions urlOptions)
|
||||
{
|
||||
Check.NotNull(options, nameof(options));
|
||||
Check.NotNull(wireMockMiddlewareOptions, nameof(wireMockMiddlewareOptions));
|
||||
Check.NotNull(urlOptions, nameof(urlOptions));
|
||||
|
||||
_logger = options.Logger ?? new WireMockConsoleLogger();
|
||||
_logger = wireMockMiddlewareOptions.Logger ?? new WireMockConsoleLogger();
|
||||
|
||||
_options = options;
|
||||
_wireMockMiddlewareOptions = wireMockMiddlewareOptions;
|
||||
_urlOptions = urlOptions;
|
||||
}
|
||||
|
||||
@@ -61,7 +61,7 @@ namespace WireMock.Owin
|
||||
.ConfigureAppConfigurationUsingEnvironmentVariables()
|
||||
.ConfigureServices(services =>
|
||||
{
|
||||
services.AddSingleton(_options);
|
||||
services.AddSingleton(_wireMockMiddlewareOptions);
|
||||
services.AddSingleton<IMappingMatcher, MappingMatcher>();
|
||||
services.AddSingleton<IOwinRequestMapper, OwinRequestMapper>();
|
||||
services.AddSingleton<IOwinResponseMapper, OwinResponseMapper>();
|
||||
@@ -70,17 +70,17 @@ namespace WireMock.Owin
|
||||
{
|
||||
appBuilder.UseMiddleware<GlobalExceptionMiddleware>();
|
||||
|
||||
_options.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
_wireMockMiddlewareOptions.PreWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
|
||||
appBuilder.UseMiddleware<WireMockMiddleware>();
|
||||
|
||||
_options.PostWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
_wireMockMiddlewareOptions.PostWireMockMiddlewareInit?.Invoke(appBuilder);
|
||||
})
|
||||
.UseKestrel(options =>
|
||||
{
|
||||
SetKestrelOptionsLimits(options);
|
||||
|
||||
SetHttpsAndUrls(options, _urlOptions.GetDetails());
|
||||
SetHttpsAndUrls(options, _wireMockMiddlewareOptions, _urlOptions.GetDetails());
|
||||
})
|
||||
.ConfigureKestrelServerOptions()
|
||||
|
||||
@@ -107,7 +107,7 @@ namespace WireMock.Owin
|
||||
{
|
||||
Urls.Add(address.Replace("0.0.0.0", "localhost"));
|
||||
|
||||
PortUtils.TryExtract(address, out string protocol, out string host, out int port);
|
||||
PortUtils.TryExtract(address, out bool isHttps, out string protocol, out string host, out int port);
|
||||
Ports.Add(port);
|
||||
}
|
||||
|
||||
|
||||
15
src/WireMock.Net/Owin/HostUrlDetails.cs
Normal file
15
src/WireMock.Net/Owin/HostUrlDetails.cs
Normal file
@@ -0,0 +1,15 @@
|
||||
namespace WireMock.Owin
|
||||
{
|
||||
internal class HostUrlDetails
|
||||
{
|
||||
public bool IsHttps { get; set; }
|
||||
|
||||
public string Url { get; set; }
|
||||
|
||||
public string Protocol { get; set; }
|
||||
|
||||
public string Host { get; set; }
|
||||
|
||||
public int Port { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -5,26 +5,29 @@ namespace WireMock.Owin
|
||||
{
|
||||
internal class HostUrlOptions
|
||||
{
|
||||
private const string LOCALHOST = "localhost";
|
||||
|
||||
public ICollection<string> Urls { get; set; }
|
||||
|
||||
public int? Port { get; set; }
|
||||
|
||||
public bool UseSSL { get; set; }
|
||||
|
||||
public ICollection<(string Url, int Port)> GetDetails()
|
||||
public ICollection<HostUrlDetails> GetDetails()
|
||||
{
|
||||
var list = new List<(string Url, int Port)>();
|
||||
var list = new List<HostUrlDetails>();
|
||||
if (Urls == null)
|
||||
{
|
||||
int port = Port > 0 ? Port.Value : FindFreeTcpPort();
|
||||
list.Add(($"{(UseSSL ? "https" : "http")}://localhost:{port}", port));
|
||||
string protocol = UseSSL ? "https" : "http";
|
||||
list.Add(new HostUrlDetails { IsHttps = UseSSL, Url = $"{protocol}://{LOCALHOST}:{port}", Protocol = protocol, Host = LOCALHOST, Port = port });
|
||||
}
|
||||
else
|
||||
{
|
||||
foreach (string url in Urls)
|
||||
{
|
||||
PortUtils.TryExtract(url, out string protocol, out string host, out int port);
|
||||
list.Add((url, port));
|
||||
PortUtils.TryExtract(url, out bool isHttps, out string protocol, out string host, out int port);
|
||||
list.Add(new HostUrlDetails { IsHttps = isHttps, Url = url, Protocol = protocol, Host = host, Port = port });
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -47,5 +47,17 @@ namespace WireMock.Owin
|
||||
bool? DisableRequestBodyDecompressing { get; set; }
|
||||
|
||||
bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
string X509StoreName { get; set; }
|
||||
|
||||
string X509StoreLocation { get; set; }
|
||||
|
||||
string X509ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
string X509CertificateFilePath { get; set; }
|
||||
|
||||
string X509CertificatePassword { get; set; }
|
||||
|
||||
bool CustomCertificateDefined { get; }
|
||||
}
|
||||
}
|
||||
@@ -2,6 +2,7 @@
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Net;
|
||||
using System.Reflection;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using Newtonsoft.Json;
|
||||
@@ -79,16 +80,21 @@ namespace WireMock.Owin.Mappers
|
||||
break;
|
||||
}
|
||||
|
||||
switch (responseMessage.StatusCode)
|
||||
var statusCodeType = responseMessage.StatusCode?.GetType();
|
||||
|
||||
switch (statusCodeType)
|
||||
{
|
||||
case int statusCodeAsInteger:
|
||||
response.StatusCode = MapStatusCode(statusCodeAsInteger);
|
||||
case Type typeAsIntOrEnum when typeAsIntOrEnum == typeof(int) || typeAsIntOrEnum == typeof(int?) || typeAsIntOrEnum.GetTypeInfo().IsEnum:
|
||||
response.StatusCode = MapStatusCode((int)responseMessage.StatusCode);
|
||||
break;
|
||||
|
||||
case Type typeAsString when typeAsString == typeof(string):
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(responseMessage.StatusCode as string, out int result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
break;
|
||||
|
||||
case string statusCodeAsString:
|
||||
// Note: this case will also match on null
|
||||
int.TryParse(statusCodeAsString, out int result);
|
||||
response.StatusCode = MapStatusCode(result);
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
|
||||
@@ -53,5 +53,25 @@ namespace WireMock.Owin
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.HandleRequestsSynchronously"/>
|
||||
public bool? HandleRequestsSynchronously { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreName"/>
|
||||
public string X509StoreName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509StoreLocation"/>
|
||||
public string X509StoreLocation { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509ThumbprintOrSubjectName"/>
|
||||
public string X509ThumbprintOrSubjectName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificateFilePath"/>
|
||||
public string X509CertificateFilePath { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.X509CertificatePassword"/>
|
||||
public string X509CertificatePassword { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockMiddlewareOptions.CustomCertificateDefined"/>
|
||||
public bool CustomCertificateDefined =>
|
||||
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
|
||||
!string.IsNullOrEmpty(X509CertificateFilePath) && !string.IsNullOrEmpty(X509CertificatePassword);
|
||||
}
|
||||
}
|
||||
@@ -1,19 +1,27 @@
|
||||
using System;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.ResponseProviders;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
|
||||
}
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using JetBrains.Annotations;
|
||||
using WireMock.ResponseProviders;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
/// <summary>
|
||||
/// The CallbackResponseBuilder interface.
|
||||
/// </summary>
|
||||
public interface ICallbackResponseBuilder : IResponseProvider
|
||||
{
|
||||
/// <summary>
|
||||
/// The callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, ResponseMessage> callbackHandler);
|
||||
|
||||
/// <summary>
|
||||
/// The async callback builder
|
||||
/// </summary>
|
||||
/// <returns>The <see cref="IResponseBuilder"/>.</returns>
|
||||
[PublicAPI]
|
||||
IResponseBuilder WithCallback([NotNull] Func<RequestMessage, Task<ResponseMessage>> callbackHandler);
|
||||
}
|
||||
}
|
||||
60
src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
Normal file
60
src/WireMock.Net/ResponseBuilders/Response.WithCallback.cs
Normal file
@@ -0,0 +1,60 @@
|
||||
using System;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Validation;
|
||||
|
||||
namespace WireMock.ResponseBuilders
|
||||
{
|
||||
public partial class Response
|
||||
{
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response async.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, Task<ResponseMessage>> CallbackAsync { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, ResponseMessage})"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback(Func{RequestMessage, Task{ResponseMessage}})"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, Task<ResponseMessage>> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
CallbackAsync = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -42,16 +42,6 @@ namespace WireMock.ResponseBuilders
|
||||
/// </summary>
|
||||
public ResponseMessage ResponseMessage { get; }
|
||||
|
||||
/// <summary>
|
||||
/// A delegate to execute to generate the response.
|
||||
/// </summary>
|
||||
public Func<RequestMessage, ResponseMessage> Callback { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if the method WithCallback(...) is used.
|
||||
/// </summary>
|
||||
public bool WithCallbackUsed { get; private set; }
|
||||
|
||||
/// <summary>
|
||||
/// Creates this instance.
|
||||
/// </summary>
|
||||
@@ -311,25 +301,6 @@ namespace WireMock.ResponseBuilders
|
||||
return WithDelay(TimeSpan.FromMilliseconds(milliseconds));
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
|
||||
public IResponseBuilder WithCallback(Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
return WithCallbackInternal(true, callbackHandler);
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="ICallbackResponseBuilder.WithCallback"/>
|
||||
private IResponseBuilder WithCallbackInternal(bool withCallbackUsed, Func<RequestMessage, ResponseMessage> callbackHandler)
|
||||
{
|
||||
Check.NotNull(callbackHandler, nameof(callbackHandler));
|
||||
|
||||
WithCallbackUsed = withCallbackUsed;
|
||||
Callback = callbackHandler;
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
/// <inheritdoc cref="IResponseProvider.ProvideResponseAsync(RequestMessage, IWireMockServerSettings)"/>
|
||||
public async Task<ResponseMessage> ProvideResponseAsync(RequestMessage requestMessage, IWireMockServerSettings settings)
|
||||
{
|
||||
@@ -365,13 +336,20 @@ namespace WireMock.ResponseBuilders
|
||||
}
|
||||
|
||||
ResponseMessage responseMessage;
|
||||
if (Callback == null)
|
||||
if (Callback == null && CallbackAsync == null)
|
||||
{
|
||||
responseMessage = ResponseMessage;
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
if (Callback != null)
|
||||
{
|
||||
responseMessage = Callback(requestMessage);
|
||||
}
|
||||
else
|
||||
{
|
||||
responseMessage = await CallbackAsync(requestMessage);
|
||||
}
|
||||
|
||||
if (!WithCallbackUsed)
|
||||
{
|
||||
|
||||
@@ -230,6 +230,15 @@ namespace WireMock.Server
|
||||
_options.DisableJsonBodyParsing = _settings.DisableJsonBodyParsing;
|
||||
_options.HandleRequestsSynchronously = settings.HandleRequestsSynchronously;
|
||||
|
||||
if (settings.CustomCertificateDefined)
|
||||
{
|
||||
_options.X509StoreName = settings.CertificateSettings.X509StoreName;
|
||||
_options.X509StoreLocation = settings.CertificateSettings.X509StoreLocation;
|
||||
_options.X509ThumbprintOrSubjectName = settings.CertificateSettings.X509StoreThumbprintOrSubjectName;
|
||||
_options.X509CertificateFilePath = settings.CertificateSettings.X509CertificateFilePath;
|
||||
_options.X509CertificatePassword = settings.CertificateSettings.X509CertificatePassword;
|
||||
}
|
||||
|
||||
_matcherMapper = new MatcherMapper(_settings);
|
||||
_mappingConverter = new MappingConverter(_matcherMapper);
|
||||
|
||||
|
||||
44
src/WireMock.Net/Settings/IWireMockCertificateSettings.cs
Normal file
44
src/WireMock.Net/Settings/IWireMockCertificateSettings.cs
Normal file
@@ -0,0 +1,44 @@
|
||||
namespace WireMock.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
|
||||
///
|
||||
/// X509StoreName and X509StoreLocation should be defined
|
||||
/// OR
|
||||
/// X509CertificateFilePath and X509CertificatePassword should be defined
|
||||
/// </summary>
|
||||
public interface IWireMockCertificateSettings
|
||||
{
|
||||
/// <summary>
|
||||
/// X509 StoreName (AddressBook, AuthRoot, CertificateAuthority, My, Root, TrustedPeople or TrustedPublisher)
|
||||
/// </summary>
|
||||
string X509StoreName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X509 StoreLocation (CurrentUser or LocalMachine)
|
||||
/// </summary>
|
||||
string X509StoreLocation { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X509 Thumbprint or SubjectName (if not defined, the 'host' is used)
|
||||
/// </summary>
|
||||
string X509StoreThumbprintOrSubjectName { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X509Certificate FilePath
|
||||
/// </summary>
|
||||
string X509CertificateFilePath { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X509Certificate Password
|
||||
/// </summary>
|
||||
string X509CertificatePassword { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// X509StoreName and X509StoreLocation should be defined
|
||||
/// OR
|
||||
/// X509CertificateFilePath and X509CertificatePassword should be defined
|
||||
/// </summary>
|
||||
bool IsDefined { get; }
|
||||
}
|
||||
}
|
||||
@@ -170,5 +170,21 @@ namespace WireMock.Settings
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// If https is used, these settings can be used to configure the CertificateSettings in case a custom certificate instead the default .NET certificate should be used.
|
||||
///
|
||||
/// X509StoreName and X509StoreLocation should be defined
|
||||
/// OR
|
||||
/// X509CertificateFilePath and X509CertificatePassword should be defined
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
IWireMockCertificateSettings CertificateSettings { get; set; }
|
||||
|
||||
/// <summary>
|
||||
/// Defines if custom CertificateSettings are defined
|
||||
/// </summary>
|
||||
[PublicAPI]
|
||||
bool CustomCertificateDefined { get; }
|
||||
}
|
||||
}
|
||||
36
src/WireMock.Net/Settings/WireMockCertificateSettings.cs
Normal file
36
src/WireMock.Net/Settings/WireMockCertificateSettings.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using JetBrains.Annotations;
|
||||
|
||||
namespace WireMock.Settings
|
||||
{
|
||||
/// <summary>
|
||||
/// <see cref="IWireMockCertificateSettings"/>
|
||||
/// </summary>
|
||||
public class WireMockCertificateSettings : IWireMockCertificateSettings
|
||||
{
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreName"/>
|
||||
[PublicAPI]
|
||||
public string X509StoreName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreLocation"/>
|
||||
[PublicAPI]
|
||||
public string X509StoreLocation { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.X509StoreThumbprintOrSubjectName"/>
|
||||
[PublicAPI]
|
||||
public string X509StoreThumbprintOrSubjectName { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.X509CertificateFilePath"/>
|
||||
[PublicAPI]
|
||||
public string X509CertificateFilePath { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.X509CertificatePassword"/>
|
||||
[PublicAPI]
|
||||
public string X509CertificatePassword { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockCertificateSettings.IsDefined"/>
|
||||
[PublicAPI]
|
||||
public bool IsDefined =>
|
||||
!string.IsNullOrEmpty(X509StoreName) && !string.IsNullOrEmpty(X509StoreLocation) ||
|
||||
!string.IsNullOrEmpty(X509CertificateFilePath) && !string.IsNullOrEmpty(X509CertificatePassword);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
using HandlebarsDotNet;
|
||||
using System;
|
||||
using HandlebarsDotNet;
|
||||
using JetBrains.Annotations;
|
||||
using System;
|
||||
using Newtonsoft.Json;
|
||||
using WireMock.Handlers;
|
||||
using WireMock.Logging;
|
||||
@@ -121,5 +121,13 @@ namespace WireMock.Settings
|
||||
/// <inheritdoc cref="IWireMockServerSettings.ThrowExceptionWhenMatcherFails"/>
|
||||
[PublicAPI]
|
||||
public bool? ThrowExceptionWhenMatcherFails { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockServerSettings.CertificateSettings"/>
|
||||
[PublicAPI]
|
||||
public IWireMockCertificateSettings CertificateSettings { get; set; }
|
||||
|
||||
/// <inheritdoc cref="IWireMockServerSettings.CustomCertificateDefined"/>
|
||||
[PublicAPI]
|
||||
public bool CustomCertificateDefined => CertificateSettings?.IsDefined == true;
|
||||
}
|
||||
}
|
||||
@@ -60,12 +60,12 @@ namespace WireMock.Settings
|
||||
settings.Urls = parser.GetValues("Urls", new[] { "http://*:9091/" });
|
||||
}
|
||||
|
||||
string proxyURL = parser.GetStringValue("ProxyURL");
|
||||
if (!string.IsNullOrEmpty(proxyURL))
|
||||
string proxyUrl = parser.GetStringValue("ProxyURL") ?? parser.GetStringValue("ProxyUrl");
|
||||
if (!string.IsNullOrEmpty(proxyUrl))
|
||||
{
|
||||
settings.ProxyAndRecordSettings = new ProxyAndRecordSettings
|
||||
{
|
||||
Url = proxyURL,
|
||||
Url = proxyUrl,
|
||||
SaveMapping = parser.GetBoolValue("SaveMapping"),
|
||||
SaveMappingToFile = parser.GetBoolValue("SaveMappingToFile"),
|
||||
SaveMappingForStatusCodePattern = parser.GetStringValue("SaveMappingForStatusCodePattern"),
|
||||
@@ -87,6 +87,19 @@ namespace WireMock.Settings
|
||||
}
|
||||
}
|
||||
|
||||
var certificateSettings = new WireMockCertificateSettings
|
||||
{
|
||||
X509StoreName = parser.GetStringValue("X509StoreName"),
|
||||
X509StoreLocation = parser.GetStringValue("X509StoreLocation"),
|
||||
X509StoreThumbprintOrSubjectName = parser.GetStringValue("X509StoreThumbprintOrSubjectName"),
|
||||
X509CertificateFilePath = parser.GetStringValue("X509CertificateFilePath"),
|
||||
X509CertificatePassword = parser.GetStringValue("X509CertificatePassword")
|
||||
};
|
||||
if (certificateSettings.IsDefined)
|
||||
{
|
||||
settings.CertificateSettings = certificateSettings;
|
||||
}
|
||||
|
||||
return settings;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
using System.Net;
|
||||
using System;
|
||||
using System.Net;
|
||||
using System.Net.Sockets;
|
||||
using System.Text.RegularExpressions;
|
||||
|
||||
@@ -32,21 +33,23 @@ namespace WireMock.Util
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Extract the protocol, host and port from a URL.
|
||||
/// Extract the if-isHttps, protocol, host and port from a URL.
|
||||
/// </summary>
|
||||
public static bool TryExtract(string url, out string protocol, out string host, out int port)
|
||||
public static bool TryExtract(string url, out bool isHttps, out string protocol, out string host, out int port)
|
||||
{
|
||||
isHttps = false;
|
||||
protocol = null;
|
||||
host = null;
|
||||
port = default(int);
|
||||
port = default;
|
||||
|
||||
Match m = UrlDetailsRegex.Match(url);
|
||||
if (m.Success)
|
||||
var match = UrlDetailsRegex.Match(url);
|
||||
if (match.Success)
|
||||
{
|
||||
protocol = m.Groups["proto"].Value;
|
||||
host = m.Groups["host"].Value;
|
||||
protocol = match.Groups["proto"].Value;
|
||||
isHttps = protocol.StartsWith("https", StringComparison.OrdinalIgnoreCase);
|
||||
host = match.Groups["host"].Value;
|
||||
|
||||
return int.TryParse(m.Groups["port"].Value, out port);
|
||||
return int.TryParse(match.Groups["port"].Value, out port);
|
||||
}
|
||||
|
||||
return false;
|
||||
|
||||
@@ -58,7 +58,7 @@
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||
<PackageReference Include="JmesPath.Net" Version="1.0.125" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.0.0" />
|
||||
<PackageReference Include="Handlebars.Net.Helpers" Version="1.1.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(Configuration)' == 'Debug - Sonar'">
|
||||
|
||||
@@ -9,6 +9,7 @@ using WireMock.Server;
|
||||
using Xunit;
|
||||
using WireMock.FluentAssertions;
|
||||
using System.Threading.Tasks;
|
||||
using WireMock.Settings;
|
||||
using static System.Environment;
|
||||
|
||||
namespace WireMock.Net.Tests.FluentAssertions
|
||||
@@ -23,10 +24,10 @@ namespace WireMock.Net.Tests.FluentAssertions
|
||||
{
|
||||
_server = WireMockServer.Start();
|
||||
_server.Given(Request.Create().UsingAnyMethod())
|
||||
.RespondWith(Response.Create().WithStatusCode(200));
|
||||
.RespondWith(Response.Create().WithSuccess());
|
||||
_portUsed = _server.Ports.First();
|
||||
|
||||
_httpClient = new HttpClient { BaseAddress = new Uri($"http://localhost:{_portUsed}") };
|
||||
_httpClient = new HttpClient { BaseAddress = new Uri(_server.Urls[0]) };
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -155,6 +156,134 @@ namespace WireMock.Net.Tests.FluentAssertions
|
||||
.And.Message.Should()
|
||||
.Be($"{string.Join(NewLine, missingValue1Message, missingValue2Message)}{NewLine}");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AtUrl_WhenACallWasMadeToUrl_Should_BeOK()
|
||||
{
|
||||
await _httpClient.GetAsync("anyurl");
|
||||
|
||||
_server.Should()
|
||||
.HaveReceivedACall()
|
||||
.AtUrl($"http://localhost:{_portUsed}/anyurl");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void AtUrl_Should_ThrowWhenNoCallsWereMade()
|
||||
{
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.AtUrl("anyurl");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
"Expected _server to have been called at address matching the url \"anyurl\", but no calls were made.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task AtUrl_Should_ThrowWhenNoCallsMatchingTheUrlWereMade()
|
||||
{
|
||||
await _httpClient.GetAsync("");
|
||||
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.AtUrl("anyurl");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
$"Expected _server to have been called at address matching the url \"anyurl\", but didn't find it among the calls to {{\"http://localhost:{_portUsed}/\"}}.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WithProxyUrl_WhenACallWasMadeWithProxyUrl_Should_BeOK()
|
||||
{
|
||||
_server.ResetMappings();
|
||||
_server.Given(Request.Create().UsingAnyMethod())
|
||||
.RespondWith(Response.Create().WithProxy(new ProxyAndRecordSettings {Url = "http://localhost:9999"}));
|
||||
|
||||
await _httpClient.GetAsync("");
|
||||
|
||||
_server.Should()
|
||||
.HaveReceivedACall()
|
||||
.WithProxyUrl($"http://localhost:9999");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void WithProxyUrl_Should_ThrowWhenNoCallsWereMade()
|
||||
{
|
||||
_server.ResetMappings();
|
||||
_server.Given(Request.Create().UsingAnyMethod())
|
||||
.RespondWith(Response.Create().WithProxy(new ProxyAndRecordSettings {Url = "http://localhost:9999"}));
|
||||
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.WithProxyUrl("anyurl");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
"Expected _server to have been called with proxy url \"anyurl\", but no calls were made.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task WithProxyUrl_Should_ThrowWhenNoCallsWithTheProxyUrlWereMade()
|
||||
{
|
||||
_server.ResetMappings();
|
||||
_server.Given(Request.Create().UsingAnyMethod())
|
||||
.RespondWith(Response.Create().WithProxy(new ProxyAndRecordSettings {Url = "http://localhost:9999"}));
|
||||
|
||||
await _httpClient.GetAsync("");
|
||||
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.WithProxyUrl("anyurl");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
$"Expected _server to have been called with proxy url \"anyurl\", but didn't find it among the calls with {{\"http://localhost:9999\"}}.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FromClientIP_whenACallWasMadeFromClientIP_Should_BeOK()
|
||||
{
|
||||
await _httpClient.GetAsync("");
|
||||
var clientIP = _server.LogEntries.Last().RequestMessage.ClientIP;
|
||||
|
||||
_server.Should()
|
||||
.HaveReceivedACall()
|
||||
.FromClientIP(clientIP);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void FromClientIP_Should_ThrowWhenNoCallsWereMade()
|
||||
{
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.FromClientIP("different-ip");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
"Expected _server to have been called from client IP \"different-ip\", but no calls were made.");
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task FromClientIP_Should_ThrowWhenNoCallsFromClientIPWereMade()
|
||||
{
|
||||
await _httpClient.GetAsync("");
|
||||
var clientIP = _server.LogEntries.Last().RequestMessage.ClientIP;
|
||||
|
||||
Action act = () => _server.Should()
|
||||
.HaveReceivedACall()
|
||||
.FromClientIP("different-ip");
|
||||
|
||||
act.Should().Throw<Exception>()
|
||||
.And.Message.Should()
|
||||
.Be(
|
||||
$"Expected _server to have been called from client IP \"different-ip\", but didn't find it among the calls from IP(s) {{\"{clientIP}\"}}.");
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
|
||||
@@ -1,65 +1,94 @@
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithCallbackTests
|
||||
{
|
||||
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallback()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
var response = Response.Create()
|
||||
.WithCallback(request => new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = request.Path + "Bar"
|
||||
},
|
||||
StatusCode = 302
|
||||
});
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
|
||||
|
||||
// Assert
|
||||
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
|
||||
responseMessage.StatusCode.Should().Be(302);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallback_And_UseTransformer_Is_True()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
var response = Response.Create()
|
||||
.WithCallback(request => new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = "{{request.Path}}Bar"
|
||||
},
|
||||
StatusCode = 302
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
|
||||
|
||||
// Assert
|
||||
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
|
||||
responseMessage.StatusCode.Should().Be(302);
|
||||
}
|
||||
}
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using WireMock.Models;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Settings;
|
||||
using WireMock.Types;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests.ResponseBuilders
|
||||
{
|
||||
public class ResponseWithCallbackTests
|
||||
{
|
||||
private readonly WireMockServerSettings _settings = new WireMockServerSettings();
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallbackAsync()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
var response = Response.Create()
|
||||
.WithCallback(async request =>
|
||||
{
|
||||
await Task.Delay(1);
|
||||
|
||||
return new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = request.Path + "Bar"
|
||||
},
|
||||
StatusCode = 302
|
||||
};
|
||||
});
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
|
||||
|
||||
// Assert
|
||||
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
|
||||
responseMessage.StatusCode.Should().Be(302);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallback()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
var response = Response.Create()
|
||||
.WithCallback(request => new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = request.Path + "Bar"
|
||||
},
|
||||
StatusCode = 302
|
||||
});
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
|
||||
|
||||
// Assert
|
||||
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
|
||||
responseMessage.StatusCode.Should().Be(302);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public async Task Response_WithCallback_And_UseTransformer_Is_True()
|
||||
{
|
||||
// Assign
|
||||
var requestMessage = new RequestMessage(new UrlDetails("http://localhost/foo"), "GET", "::1");
|
||||
var response = Response.Create()
|
||||
.WithCallback(request => new ResponseMessage
|
||||
{
|
||||
BodyData = new BodyData
|
||||
{
|
||||
DetectedBodyType = BodyType.String,
|
||||
BodyAsString = "{{request.Path}}Bar"
|
||||
},
|
||||
StatusCode = 302
|
||||
})
|
||||
.WithTransformer();
|
||||
|
||||
// Act
|
||||
var responseMessage = await response.ProvideResponseAsync(requestMessage, _settings);
|
||||
|
||||
// Assert
|
||||
responseMessage.BodyData.BodyAsString.Should().Be("/fooBar");
|
||||
responseMessage.StatusCode.Should().Be(302);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using FluentAssertions;
|
||||
using NFluent;
|
||||
using WireMock.Util;
|
||||
using Xunit;
|
||||
@@ -13,13 +14,14 @@ namespace WireMock.Net.Tests.Util
|
||||
string url = "test";
|
||||
|
||||
// Act
|
||||
bool result = PortUtils.TryExtract(url, out string proto, out string host, out int port);
|
||||
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsFalse();
|
||||
Check.That(proto).IsNull();
|
||||
Check.That(host).IsNull();
|
||||
Check.That(port).IsEqualTo(default(int));
|
||||
result.Should().BeFalse();
|
||||
isHttps.Should().BeFalse();
|
||||
proto.Should().BeNull();
|
||||
host.Should().BeNull();
|
||||
port.Should().Be(default(int));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
@@ -29,39 +31,58 @@ namespace WireMock.Net.Tests.Util
|
||||
string url = "http://0.0.0.0";
|
||||
|
||||
// Act
|
||||
bool result = PortUtils.TryExtract(url, out string proto, out string host, out int port);
|
||||
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsFalse();
|
||||
Check.That(proto).IsNull();
|
||||
Check.That(host).IsNull();
|
||||
Check.That(port).IsEqualTo(default(int));
|
||||
result.Should().BeFalse();
|
||||
isHttps.Should().BeFalse();
|
||||
proto.Should().BeNull();
|
||||
host.Should().BeNull();
|
||||
port.Should().Be(default(int));
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PortUtils_TryExtract_ValidUrl1_Returns_True()
|
||||
public void PortUtils_TryExtract_Http_Returns_True()
|
||||
{
|
||||
// Assign
|
||||
string url = "http://wiremock.net:1234";
|
||||
|
||||
// Act
|
||||
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
|
||||
|
||||
// Assert
|
||||
result.Should().BeTrue();
|
||||
isHttps.Should().BeFalse();
|
||||
proto.Should().Be("http");
|
||||
host.Should().Be("wiremock.net");
|
||||
port.Should().Be(1234);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PortUtils_TryExtract_Https_Returns_True()
|
||||
{
|
||||
// Assign
|
||||
string url = "https://wiremock.net:5000";
|
||||
|
||||
// Act
|
||||
bool result = PortUtils.TryExtract(url, out string proto, out string host, out int port);
|
||||
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsTrue();
|
||||
Check.That(proto).IsEqualTo("https");
|
||||
Check.That(host).IsEqualTo("wiremock.net");
|
||||
Check.That(port).IsEqualTo(5000);
|
||||
result.Should().BeTrue();
|
||||
isHttps.Should().BeTrue();
|
||||
proto.Should().Be("https");
|
||||
host.Should().Be("wiremock.net");
|
||||
port.Should().Be(5000);
|
||||
}
|
||||
|
||||
[Fact]
|
||||
public void PortUtils_TryExtract_ValidUrl2_Returns_True()
|
||||
public void PortUtils_TryExtract_Https0_0_0_0_Returns_True()
|
||||
{
|
||||
// Assign
|
||||
string url = "https://0.0.0.0:5000";
|
||||
|
||||
// Act
|
||||
bool result = PortUtils.TryExtract(url, out string proto, out string host, out int port);
|
||||
bool result = PortUtils.TryExtract(url, out bool isHttps, out string proto, out string host, out int port);
|
||||
|
||||
// Assert
|
||||
Check.That(result).IsTrue();
|
||||
|
||||
@@ -1,104 +1,104 @@
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<!--<TargetFrameworks>net452;netcoreapp2.1</TargetFrameworks>-->
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<DebugType>full</DebugType>
|
||||
<AssemblyName>WireMock.Net.Tests</AssemblyName>
|
||||
<PackageId>WireMock.Net.Tests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<ProjectGuid>{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}</ProjectGuid>
|
||||
|
||||
<!-- https://github.com/tonerdo/coverlet/issues/6 -->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<SonarQubeTestProject>True</SonarQubeTestProject>
|
||||
<SonarQubeExclude>True</SonarQubeExclude>
|
||||
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
|
||||
<!--https://developercommunity.visualstudio.com/content/problem/26347/unit-tests-fail-with-fileloadexception-newtonsoftj-1.html-->
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Codecov" Version="1.10.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.8.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.5" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NFluent" Version="2.7.0" />
|
||||
<PackageReference Include="OpenCover" Version="4.7.922" />
|
||||
<PackageReference Include="ReportGenerator" Version="4.6.7" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
|
||||
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="3.1.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="responsebody.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d87.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<Project Sdk="Microsoft.NET.Sdk">
|
||||
|
||||
<PropertyGroup>
|
||||
<Authors>Stef Heyenrath</Authors>
|
||||
<!--<TargetFrameworks>net452;netcoreapp2.1</TargetFrameworks>-->
|
||||
<TargetFramework>netcoreapp3.1</TargetFramework>
|
||||
<DebugType>full</DebugType>
|
||||
<AssemblyName>WireMock.Net.Tests</AssemblyName>
|
||||
<PackageId>WireMock.Net.Tests</PackageId>
|
||||
<GenerateRuntimeConfigurationFiles>true</GenerateRuntimeConfigurationFiles>
|
||||
<ProjectGuid>{31DC2EF8-C3FE-467D-84BE-FB5D956E612E}</ProjectGuid>
|
||||
|
||||
<!-- https://github.com/tonerdo/coverlet/issues/6 -->
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<SonarQubeTestProject>True</SonarQubeTestProject>
|
||||
<SonarQubeExclude>True</SonarQubeExclude>
|
||||
|
||||
<SignAssembly>true</SignAssembly>
|
||||
<AssemblyOriginatorKeyFile>../../src/WireMock.Net/WireMock.Net.snk</AssemblyOriginatorKeyFile>
|
||||
<!--<DelaySign>true</DelaySign>-->
|
||||
<PublicSign Condition=" '$(OS)' != 'Windows_NT' ">true</PublicSign>
|
||||
|
||||
<!--https://developercommunity.visualstudio.com/content/problem/26347/unit-tests-fail-with-fileloadexception-newtonsoftj-1.html-->
|
||||
<AutoGenerateBindingRedirects>true</AutoGenerateBindingRedirects>
|
||||
<GenerateBindingRedirectsOutputType>true</GenerateBindingRedirectsOutputType>
|
||||
</PropertyGroup>
|
||||
|
||||
<PropertyGroup Condition="'$(Configuration)' == 'Release'">
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.Abstractions\WireMock.Net.Abstractions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.FluentAssertions\WireMock.Net.FluentAssertions.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net.RestClient\WireMock.Net.RestClient.csproj" />
|
||||
<ProjectReference Include="..\..\src\WireMock.Net\WireMock.Net.csproj" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Codecov" Version="1.10.0" />
|
||||
<PackageReference Include="coverlet.msbuild" Version="2.8.1">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<PackageReference Include="FluentAssertions" Version="5.10.3" />
|
||||
<PackageReference Include="System.Threading" Version="4.3.0" />
|
||||
<PackageReference Include="RestEase" Version="1.4.10" />
|
||||
<PackageReference Include="RandomDataGenerator.Net" Version="1.0.12" />
|
||||
<PackageReference Include="Microsoft.NET.Test.Sdk" Version="16.4.0" />
|
||||
<PackageReference Include="Moq" Version="4.14.5" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="11.0.2" />
|
||||
<PackageReference Include="NFluent" Version="2.7.0" />
|
||||
<PackageReference Include="OpenCover" Version="4.7.922" />
|
||||
<PackageReference Include="ReportGenerator" Version="4.6.7" />
|
||||
<PackageReference Include="SimMetrics.Net" Version="1.0.5" />
|
||||
<PackageReference Include="System.Linq.Dynamic.Core" Version="1.0.12" />
|
||||
<PackageReference Include="xunit" Version="2.4.1" />
|
||||
<PackageReference Include="xunit.runner.visualstudio" Version="2.4.3">
|
||||
<PrivateAssets>all</PrivateAssets>
|
||||
<IncludeAssets>runtime; build; native; contentfiles; analyzers</IncludeAssets>
|
||||
</PackageReference>
|
||||
<!--<PackageReference Include="StrongNamer" Version="0.0.8" />-->
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net452'">
|
||||
<PackageReference Include="Microsoft.Owin.Host.HttpListener" Version="3.1.0" />
|
||||
<PackageReference Include="System.ValueTuple" Version="4.5.0" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup Condition="'$(TargetFramework)' == 'net462'">
|
||||
<PackageReference Include="Microsoft.AspNetCore" Version="2.1.4" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="responsebody.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d86.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\00000002-ee28-4f29-ae63-1ac9b0802d87.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\351f0240-bba0-4bcb-93c6-1feba0fe8799.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\array.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\documentdb_root.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\subdirectory\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</None>
|
||||
<None Update="__admin\mappings\array.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\documentdb_root.json">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
<None Update="__admin\mappings\subdirectory\MyXmlResponse.xml">
|
||||
<CopyToOutputDirectory>PreserveNewest</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Service Include="{82a7f48d-3b50-4b1e-b82e-3ada8210c358}" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
37
test/WireMock.Net.Tests/WireMockServerTests.WithCallback.cs
Normal file
37
test/WireMock.Net.Tests/WireMockServerTests.WithCallback.cs
Normal file
@@ -0,0 +1,37 @@
|
||||
using System.Net;
|
||||
using System.Net.Http;
|
||||
using System.Threading.Tasks;
|
||||
using FluentAssertions;
|
||||
using WireMock.RequestBuilders;
|
||||
using WireMock.ResponseBuilders;
|
||||
using WireMock.Server;
|
||||
using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public partial class WireMockServerTests
|
||||
{
|
||||
[Theory]
|
||||
[InlineData(HttpStatusCode.Conflict)]
|
||||
[InlineData(409)]
|
||||
[InlineData("409")]
|
||||
public async Task WireMockServer_WithCallback_Should_Use_StatusCodeFromResponse(object statusCode)
|
||||
{
|
||||
// Arrange
|
||||
var server = WireMockServer.Start();
|
||||
server.Given(Request.Create().UsingPost().WithPath("/foo"))
|
||||
.RespondWith(Response.Create()
|
||||
.WithCallback(request => new ResponseMessage
|
||||
{
|
||||
StatusCode = statusCode
|
||||
}));
|
||||
|
||||
// Act
|
||||
using var httpClient = new HttpClient();
|
||||
var response = await httpClient.PostAsync("http://localhost:" + server.Ports[0] + "/foo", new StringContent("dummy"));
|
||||
|
||||
// Assert
|
||||
response.StatusCode.Should().Be(409);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -15,7 +15,7 @@ using Xunit;
|
||||
|
||||
namespace WireMock.Net.Tests
|
||||
{
|
||||
public class WireMockServerTests
|
||||
public partial class WireMockServerTests
|
||||
{
|
||||
[Fact]
|
||||
public async Task WireMockServer_Should_reset_requestlogs()
|
||||
|
||||
Reference in New Issue
Block a user