Added X509Certificate2Filename (#27)

This commit is contained in:
Stef Heyenrath
2017-05-16 20:20:55 +02:00
parent 961e8b555f
commit 360a1227e4
17 changed files with 122 additions and 65 deletions

View File

@@ -8,7 +8,8 @@ A C# .NET version based on [mock4net](https://github.com/alexvictoor/mock4net) w
### Frameworks ### Frameworks
The following frameworks are supported: The following frameworks are supported:
- net45 and up - net 4.5
- net 4.5.2 and up
- netstandard 1.3 - netstandard 1.3
## Stubbing ## Stubbing

View File

@@ -2,21 +2,19 @@
using WireMock.Server; using WireMock.Server;
using WireMock.Settings; using WireMock.Settings;
namespace WireMock.Net.Console.NETCoreApp namespace WireMock.Net.Console.Record.NETCoreApp
{ {
static class Program static class Program
{ {
static void Main(params string[] args) static void Main(params string[] args)
{ {
string url = "http://localhost:9095/";
var server = FluentMockServer.Start(new FluentMockServerSettings var server = FluentMockServer.Start(new FluentMockServerSettings
{ {
Urls = new[] { url }, Urls = new[] { "http://localhost:9095/", "https://localhost:9096/" },
StartAdminInterface = true, StartAdminInterface = true,
ProxyAndRecordSettings = new ProxyAndRecordSettings ProxyAndRecordSettings = new ProxyAndRecordSettings
{ {
Url = "http://www.bbc.com", Url = "https://www.msn.com",
SaveMapping = true SaveMapping = true
} }
}); });

View File

@@ -27,8 +27,11 @@ namespace WireMock.Net.StandAlone.NETCoreApp
[ValueArgument(typeof(string), "ProxyURL", Description = "The ProxyURL to use.", Optional = true)] [ValueArgument(typeof(string), "ProxyURL", Description = "The ProxyURL to use.", Optional = true)]
public string ProxyURL { get; set; } public string ProxyURL { get; set; }
[SwitchArgument("SaveProxyMapping", false, Description = "Save the proxied request and response mapping files in ./__admin/mappings. (default set to false).", Optional = true)] [SwitchArgument("SaveProxyMapping", true, Description = "Save the proxied request and response mapping files in ./__admin/mappings. (default set to true).", Optional = true)]
public bool SaveMapping { get; set; } public bool SaveMapping { get; set; }
[ValueArgument(typeof(string), "X509Certificate2", Description = "The X509Certificate2 Filename to use.", Optional = true)]
public string X509Certificate2Filename { get; set; }
} }
static void Main(string[] args) static void Main(string[] args)
@@ -58,7 +61,8 @@ namespace WireMock.Net.StandAlone.NETCoreApp
settings.ProxyAndRecordSettings = new ProxyAndRecordSettings settings.ProxyAndRecordSettings = new ProxyAndRecordSettings
{ {
Url = options.ProxyURL, Url = options.ProxyURL,
SaveMapping = options.SaveMapping SaveMapping = options.SaveMapping,
X509Certificate2Filename = options.X509Certificate2Filename
}; };
} }

View File

@@ -27,8 +27,11 @@ namespace WireMock.Net.StandAlone
[ValueArgument(typeof(string), "ProxyURL", Description = "The ProxyURL to use.", Optional = true)] [ValueArgument(typeof(string), "ProxyURL", Description = "The ProxyURL to use.", Optional = true)]
public string ProxyURL { get; set; } public string ProxyURL { get; set; }
[SwitchArgument("SaveProxyMapping", false, Description = "Save the proxied request and response mapping files in ./__admin/mappings. (default set to false).", Optional = true)] [SwitchArgument("SaveProxyMapping", true, Description = "Save the proxied request and response mapping files in ./__admin/mappings. (default set to true).", Optional = true)]
public bool SaveMapping { get; set; } public bool SaveMapping { get; set; }
[ValueArgument(typeof(string), "X509Certificate2", Description = "The X509Certificate2 Filename to use.", Optional = true)]
public string X509Certificate2Filename { get; set; }
} }
static void Main(params string[] args) static void Main(params string[] args)
@@ -58,7 +61,8 @@ namespace WireMock.Net.StandAlone
settings.ProxyAndRecordSettings = new ProxyAndRecordSettings settings.ProxyAndRecordSettings = new ProxyAndRecordSettings
{ {
Url = options.ProxyURL, Url = options.ProxyURL,
SaveMapping = options.SaveMapping SaveMapping = options.SaveMapping,
X509Certificate2Filename = options.X509Certificate2Filename
}; };
} }

View File

@@ -7,10 +7,39 @@ namespace WireMock.Http
{ {
internal static class HttpClientHelper internal static class HttpClientHelper
{ {
private static HttpClient client = new HttpClient(); private static HttpClient CreateHttpClient(string clientX509Certificate2Filename = null)
public static async Task<ResponseMessage> SendAsync(RequestMessage requestMessage, string url)
{ {
if (!string.IsNullOrEmpty(clientX509Certificate2Filename))
{
#if NETSTANDARD || NET46
var handler = new HttpClientHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
SslProtocols = System.Security.Authentication.SslProtocols.Tls12 | System.Security.Authentication.SslProtocols.Tls11 | System.Security.Authentication.SslProtocols.Tls,
ServerCertificateCustomValidationCallback = (message, cert, chain, errors) => true
};
handler.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate2(clientX509Certificate2Filename));
return new HttpClient(handler);
#else
var handler = new WebRequestHandler
{
ClientCertificateOptions = ClientCertificateOption.Manual,
ServerCertificateValidationCallback = (sender, certificate, chain, errors) => true
};
handler.ClientCertificates.Add(new System.Security.Cryptography.X509Certificates.X509Certificate2(clientX509Certificate2Filename));
return new HttpClient(handler);
#endif
}
return new HttpClient();
}
public static async Task<ResponseMessage> SendAsync(RequestMessage requestMessage, string url, string clientX509Certificate2Filename = null)
{
var client = CreateHttpClient(clientX509Certificate2Filename);
var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url); var httpRequestMessage = new HttpRequestMessage(new HttpMethod(requestMessage.Method), url);
// Overwrite the host header // Overwrite the host header

View File

@@ -43,25 +43,12 @@ namespace WireMock.Matchers.Request
/// </returns> /// </returns>
public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult) public double GetMatchingScore(RequestMessage requestMessage, RequestMatchResult requestMatchResult)
{ {
var list = new List<double>();
if (_type == CompositeMatcherType.And) if (_type == CompositeMatcherType.And)
{ {
foreach (var requestMatcher in RequestMatchers) return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
{
double score = requestMatcher.GetMatchingScore(requestMessage, requestMatchResult);
list.Add(score);
}
return list.Sum() / list.Count;
}
foreach (var requestMatcher in RequestMatchers)
{
double score = requestMatcher.GetMatchingScore(requestMessage, requestMatchResult);
list.Add(score);
} }
return list.Max(); return RequestMatchers.Max(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
} }
} }
} }

View File

@@ -3,7 +3,7 @@ using System.Linq;
using System.Xml; using System.Xml;
using JetBrains.Annotations; using JetBrains.Annotations;
using WireMock.Validation; using WireMock.Validation;
#if NET45 #if !NETSTANDARD
using Wmhelp.XPath2; using Wmhelp.XPath2;
#endif #endif
@@ -41,10 +41,10 @@ namespace WireMock.Matchers
try try
{ {
var nav = new XmlDocument { InnerXml = input }.CreateNavigator(); var nav = new XmlDocument { InnerXml = input }.CreateNavigator();
#if NET45 #if NETSTANDARD
return MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p})"))));
#else
return MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p})")))); return MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.Evaluate($"boolean({p})"))));
#else
return MatchScores.ToScore(_patterns.Select(p => true.Equals(nav.XPath2Evaluate($"boolean({p})"))));
#endif #endif
} }
catch (Exception) catch (Exception)
@@ -65,9 +65,7 @@ namespace WireMock.Matchers
/// <summary> /// <summary>
/// Gets the name. /// Gets the name.
/// </summary> /// </summary>
/// <returns> /// <returns>Name</returns>
/// Name
/// </returns>
public string GetName() public string GetName()
{ {
return "XPathMatcher"; return "XPathMatcher";

View File

@@ -1,4 +1,4 @@
#if !NET45 #if NETSTANDARD
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -4,12 +4,11 @@ using System.IO;
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
#if NET45 #if !NETSTANDARD
using Microsoft.Owin; using Microsoft.Owin;
#else #else
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Http.Extensions; using Microsoft.AspNetCore.Http.Extensions;
using Microsoft.AspNetCore.Http.Features;
#endif #endif
namespace WireMock.Owin namespace WireMock.Owin
@@ -25,14 +24,14 @@ namespace WireMock.Owin
/// <param name="request"></param> /// <param name="request"></param>
/// <returns></returns> /// <returns></returns>
public async Task<RequestMessage> MapAsync( public async Task<RequestMessage> MapAsync(
#if NET45 #if !NETSTANDARD
IOwinRequest request IOwinRequest request
#else #else
HttpRequest request HttpRequest request
#endif #endif
) )
{ {
#if NET45 #if !NETSTANDARD
Uri url = request.Uri; Uri url = request.Uri;
#else #else
Uri url = new Uri(request.GetEncodedUrl()); Uri url = new Uri(request.GetEncodedUrl());

View File

@@ -2,7 +2,7 @@
using System.Linq; using System.Linq;
using System.Text; using System.Text;
using System.Threading.Tasks; using System.Threading.Tasks;
#if NET45 #if !NETSTANDARD
using Microsoft.Owin; using Microsoft.Owin;
#else #else
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@@ -23,7 +23,7 @@ namespace WireMock.Owin
/// <param name="responseMessage"></param> /// <param name="responseMessage"></param>
/// <param name="response"></param> /// <param name="response"></param>
public async Task MapAsync(ResponseMessage responseMessage public async Task MapAsync(ResponseMessage responseMessage
#if NET45 #if !NETSTANDARD
, IOwinResponse response , IOwinResponse response
#else #else
, HttpResponse response , HttpResponse response

View File

@@ -1,4 +1,4 @@
#if NET45 #if !NETSTANDARD
using System; using System;
using System.Collections.Generic; using System.Collections.Generic;
using System.Threading; using System.Threading;

View File

@@ -4,7 +4,7 @@ using System.Threading.Tasks;
using WireMock.Logging; using WireMock.Logging;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using System.Linq; using System.Linq;
#if NET45 #if !NETSTANDARD
using Microsoft.Owin; using Microsoft.Owin;
#else #else
using Microsoft.AspNetCore.Http; using Microsoft.AspNetCore.Http;
@@ -12,7 +12,7 @@ using Microsoft.AspNetCore.Http;
namespace WireMock.Owin namespace WireMock.Owin
{ {
#if NET45 #if !NETSTANDARD
internal class WireMockMiddleware : OwinMiddleware internal class WireMockMiddleware : OwinMiddleware
#else #else
internal class WireMockMiddleware internal class WireMockMiddleware
@@ -24,7 +24,7 @@ namespace WireMock.Owin
private readonly OwinRequestMapper _requestMapper = new OwinRequestMapper(); private readonly OwinRequestMapper _requestMapper = new OwinRequestMapper();
private readonly OwinResponseMapper _responseMapper = new OwinResponseMapper(); private readonly OwinResponseMapper _responseMapper = new OwinResponseMapper();
#if NET45 #if !NETSTANDARD
public WireMockMiddleware(OwinMiddleware next, WireMockMiddlewareOptions options) : base(next) public WireMockMiddleware(OwinMiddleware next, WireMockMiddlewareOptions options) : base(next)
{ {
_options = options; _options = options;
@@ -36,7 +36,7 @@ namespace WireMock.Owin
} }
#endif #endif
#if NET45 #if !NETSTANDARD
public override async Task Invoke(IOwinContext ctx) public override async Task Invoke(IOwinContext ctx)
#else #else
public async Task Invoke(HttpContext ctx) public async Task Invoke(HttpContext ctx)

View File

@@ -8,10 +8,18 @@ namespace WireMock.ResponseBuilders
public interface IProxyResponseBuilder : IStatusCodeResponseBuilder public interface IProxyResponseBuilder : IStatusCodeResponseBuilder
{ {
/// <summary> /// <summary>
/// From Proxy URL. /// With Proxy URL.
/// </summary> /// </summary>
/// <param name="proxyUrl">The proxy url.</param> /// <param name="proxyUrl">The proxy url.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] string proxyUrl); IResponseBuilder WithProxy([NotNull] string proxyUrl);
/// <summary>
/// With Proxy URL using X509Certificate2.
/// </summary>
/// <param name="proxyUrl">The proxy url.</param>
/// <param name="clientX509Certificate2Filename">The X509Certificate2 file to use for client authentication.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
IResponseBuilder WithProxy([NotNull] string proxyUrl, [CanBeNull] string clientX509Certificate2Filename);
} }
} }

View File

@@ -34,6 +34,11 @@ namespace WireMock.ResponseBuilders
/// </summary> /// </summary>
public string ProxyUrl { get; private set; } public string ProxyUrl { get; private set; }
/// <summary>
/// The client X509Certificate2Filename to use.
/// </summary>
public string X509Certificate2Filename { get; private set; } = null;
/// <summary> /// <summary>
/// Gets the response message. /// Gets the response message.
/// </summary> /// </summary>
@@ -190,7 +195,7 @@ namespace WireMock.ResponseBuilders
/// <param name="bodyAsbase64">The body asbase64.</param> /// <param name="bodyAsbase64">The body asbase64.</param>
/// <param name="encoding">The Encoding.</param> /// <param name="encoding">The Encoding.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
public IResponseBuilder WithBodyAsBase64([NotNull] string bodyAsbase64, Encoding encoding = null) public IResponseBuilder WithBodyAsBase64(string bodyAsbase64, Encoding encoding = null)
{ {
Check.NotNull(bodyAsbase64, nameof(bodyAsbase64)); Check.NotNull(bodyAsbase64, nameof(bodyAsbase64));
@@ -237,7 +242,7 @@ namespace WireMock.ResponseBuilders
} }
/// <summary> /// <summary>
/// From Proxy URL. /// With Proxy URL.
/// </summary> /// </summary>
/// <param name="proxyUrl">The proxy url.</param> /// <param name="proxyUrl">The proxy url.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns> /// <returns>A <see cref="IResponseBuilder"/>.</returns>
@@ -250,6 +255,22 @@ namespace WireMock.ResponseBuilders
return this; return this;
} }
/// <summary>
/// With Proxy URL.
/// </summary>
/// <param name="proxyUrl">The proxy url.</param>
/// <param name="clientX509Certificate2Filename">The X509Certificate2 file to use for client authentication.</param>
/// <returns>A <see cref="IResponseBuilder"/>.</returns>
public IResponseBuilder WithProxy(string proxyUrl, string clientX509Certificate2Filename)
{
Check.NotEmpty(proxyUrl, nameof(proxyUrl));
Check.NotEmpty(clientX509Certificate2Filename, nameof(clientX509Certificate2Filename));
ProxyUrl = proxyUrl;
X509Certificate2Filename = clientX509Certificate2Filename;
return this;
}
/// <summary> /// <summary>
/// The provide response. /// The provide response.
/// </summary> /// </summary>
@@ -264,9 +285,10 @@ namespace WireMock.ResponseBuilders
if (ProxyUrl != null) if (ProxyUrl != null)
{ {
return await HttpClientHelper.SendAsync(requestMessage, ProxyUrl); return await HttpClientHelper.SendAsync(requestMessage, ProxyUrl, X509Certificate2Filename);
} }
else if (UseTransformer)
if (UseTransformer)
{ {
return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage); return ResponseMessageTransformer.Transform(requestMessage, ResponseMessage);
} }

View File

@@ -164,10 +164,10 @@ namespace WireMock.Server
Urls = new[] { (settings.UseSSL == true ? "https" : "http") + "://localhost:" + port + "/" }; Urls = new[] { (settings.UseSSL == true ? "https" : "http") + "://localhost:" + port + "/" };
} }
#if NET45 #if NETSTANDARD
_httpServer = new OwinSelfHost(_options, Urls);
#else
_httpServer = new AspNetCoreSelfHost(_options, Urls); _httpServer = new AspNetCoreSelfHost(_options, Urls);
#else
_httpServer = new OwinSelfHost(_options, Urls);
#endif #endif
Ports = _httpServer.Ports; Ports = _httpServer.Ports;

View File

@@ -14,5 +14,10 @@
/// Save the mapping for each request/response. /// Save the mapping for each request/response.
/// </summary> /// </summary>
public bool SaveMapping { get; set; } = true; public bool SaveMapping { get; set; } = true;
/// <summary>
/// The clientCertificateFilename to use. Example : "C:\certificates\cert.pfx"
/// </summary>
public string X509Certificate2Filename { get; set; }
} }
} }

View File

@@ -5,7 +5,7 @@
<AssemblyTitle>WireMock.Net</AssemblyTitle> <AssemblyTitle>WireMock.Net</AssemblyTitle>
<Version>1.0.2.0</Version> <Version>1.0.2.0</Version>
<Authors>Alexandre Victoor;Stef Heyenrath</Authors> <Authors>Alexandre Victoor;Stef Heyenrath</Authors>
<TargetFrameworks>net45;netstandard1.3</TargetFrameworks> <TargetFrameworks>net45;net452;net46;netstandard1.3</TargetFrameworks>
<GenerateDocumentationFile>true</GenerateDocumentationFile> <GenerateDocumentationFile>true</GenerateDocumentationFile>
<AssemblyName>WireMock.Net</AssemblyName> <AssemblyName>WireMock.Net</AssemblyName>
<PackageId>WireMock.Net</PackageId> <PackageId>WireMock.Net</PackageId>
@@ -26,28 +26,31 @@
<DefineConstants>NETSTANDARD</DefineConstants> <DefineConstants>NETSTANDARD</DefineConstants>
</PropertyGroup> </PropertyGroup>
<ItemGroup>
<None Include="Server\FluentMockServer.LogEntries.cs" />
</ItemGroup>
<ItemGroup> <ItemGroup>
<PackageReference Include="JetBrains.Annotations" Version="10.4.0"> <PackageReference Include="JetBrains.Annotations" Version="10.4.0">
<PrivateAssets>All</PrivateAssets> <PrivateAssets>All</PrivateAssets>
</PackageReference> </PackageReference>
<PackageReference Include="Newtonsoft.Json" Version="9.0.1" /> <PackageReference Include="Newtonsoft.Json" Version="9.0.1" />
<PackageReference Include="SimMetrics.Net" Version="1.0.3" /> <PackageReference Include="SimMetrics.Net" Version="1.0.3" />
<PackageReference Include="System.Net.Http" Version="4.3.2" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net45' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net45' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.3" /> <PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.3" />
<PackageReference Include="Handlebars.Net" Version="1.8.0" /> <PackageReference Include="Handlebars.Net" Version="1.8.0" />
<PackageReference Include="XPath2" Version="1.0.3.1" /> <PackageReference Include="XPath2" Version="1.0.3.1" />
<Reference Include="System.Net.Http.WebRequest" />
</ItemGroup> </ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net451' "> <ItemGroup Condition=" '$(TargetFramework)' == 'net452' ">
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.3" />
<PackageReference Include="System.Net.Http" Version="4.3.0" /> <PackageReference Include="Handlebars.Net" Version="1.8.0" />
<PackageReference Include="System.Threading.Tasks" Version="4.3.0" /> <PackageReference Include="XPath2" Version="1.0.3.1" />
<Reference Include="System.Net.Http.WebRequest" />
</ItemGroup>
<ItemGroup Condition=" '$(TargetFramework)' == 'net46' ">
<PackageReference Include="Microsoft.AspNet.WebApi.OwinSelfHost" Version="5.2.3" />
<PackageReference Include="Handlebars.Net" Version="1.8.0" /> <PackageReference Include="Handlebars.Net" Version="1.8.0" />
<PackageReference Include="XPath2" Version="1.0.3.1" /> <PackageReference Include="XPath2" Version="1.0.3.1" />
</ItemGroup> </ItemGroup>
@@ -55,7 +58,6 @@
<ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' "> <ItemGroup Condition=" '$(TargetFramework)' == 'netstandard1.3' ">
<PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" /> <PackageReference Include="Microsoft.AspNetCore" Version="1.1.1" />
<PackageReference Include="Handlebars.NetStandard" Version="1.8.1" /> <PackageReference Include="Handlebars.NetStandard" Version="1.8.1" />
<PackageReference Include="System.Net.Http" Version="4.3.0" />
<PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" /> <PackageReference Include="System.Xml.XmlDocument" Version="4.3.0" />
<PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" /> <PackageReference Include="System.Xml.XPath.XmlDocument" Version="4.3.0" />
</ItemGroup> </ItemGroup>