This commit is contained in:
Stef Heyenrath
2017-02-05 10:25:19 +01:00
parent 44f00cb9fa
commit 8231b25805
10 changed files with 152 additions and 73 deletions
@@ -1,6 +1,14 @@
<?xml version="1.0" encoding="utf-8" ?> <?xml version="1.0" encoding="utf-8"?>
<configuration> <configuration>
<startup> <startup>
<supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" /> <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.5.2" />
</startup> </startup>
<runtime>
<assemblyBinding xmlns="urn:schemas-microsoft-com:asm.v1">
<dependentAssembly>
<assemblyIdentity name="Newtonsoft.Json" publicKeyToken="30ad4fe6b2a6aeed" culture="neutral" />
<bindingRedirect oldVersion="0.0.0.0-9.0.0.0" newVersion="9.0.0.0" />
</dependentAssembly>
</assemblyBinding>
</runtime>
</configuration> </configuration>
@@ -1,4 +1,5 @@
using System; using System;
using System.Linq;
using Newtonsoft.Json; using Newtonsoft.Json;
using WireMock.Matchers; using WireMock.Matchers;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
@@ -20,62 +21,64 @@ namespace WireMock.Net.ConsoleApplication
server.AllowPartialMapping(); server.AllowPartialMapping();
//server server
// .Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet()) .Given(Request.Create().WithPath(p => p.Contains("x")).UsingGet())
// .AtPriority(4) .AtPriority(4)
// .RespondWith(Response.Create() .RespondWith(Response.Create()
// .WithStatusCode(200) .WithStatusCode(200)
// .WithHeader("Content-Type", "application/json") .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""Contains x with FUNC 200""}")); .WithBody(@"{ ""result"": ""Contains x with FUNC 200""}"));
//server
// .Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
//server
// .Given(Request.Create().WithPath("/data", "/ax").UsingPost().WithHeader("Content-Type", "application/json*"))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data posted with 201""}"));
//server
// .Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""json posted with 201""}"));
//server
// .Given(Request.Create().WithPath("/json2").UsingPost().WithBody("x"))
// .RespondWith(Response.Create()
// .WithStatusCode(201)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""json posted with x - 201""}"));
//server
// .Given(Request.Create().WithPath("/data").UsingDelete())
// .RespondWith(Response.Create()
// .WithStatusCode(200)
// .WithHeader("Content-Type", "application/json")
// .WithBody(@"{ ""result"": ""data deleted with 200""}"));
//server
// .Given(Request.Create().WithPath("/nobody").UsingGet())
// .RespondWith(Response.Create().WithDelay(TimeSpan.FromSeconds(1))
// .WithStatusCode(200));
server server
.Given(Request.Create().WithPath("/partial").UsingGet().WithHeader("p", "p")) .Given(Request.Create().WithPath("/data").UsingPost().WithBody(b => b.Contains("e")))
.AtPriority(999)
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data posted with FUNC 201""}"));
server
.Given(Request.Create().WithPath("/data", "/ax").UsingPost().WithHeader("Content-Type", "application/json*"))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data posted with 201""}"));
server
.Given(Request.Create().WithPath("/json").UsingPost().WithBody(new JsonPathMatcher("$.things[?(@.name == 'RequiredThing')]")))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""json posted with 201""}"));
server
.Given(Request.Create().WithPath("/json2").UsingPost().WithBody("x"))
.RespondWith(Response.Create()
.WithStatusCode(201)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""json posted with x - 201""}"));
server
.Given(Request.Create().WithPath("/data").UsingDelete())
.RespondWith(Response.Create()
.WithStatusCode(200)
.WithHeader("Content-Type", "application/json")
.WithBody(@"{ ""result"": ""data deleted with 200""}"));
server
.Given(Request.Create().WithPath("/nobody").UsingGet())
.RespondWith(Response.Create().WithDelay(TimeSpan.FromSeconds(1))
.WithStatusCode(200));
server
.Given(Request.Create().WithPath("/partial").UsingPost().WithBody(new SimMetricsMatcher("cat")))
.RespondWith(Response.Create().WithStatusCode(200).WithBody("partial = 200")); .RespondWith(Response.Create().WithStatusCode(200).WithBody("partial = 200"));
// http://localhost:8080/any/any?start=1000&stop=1&stop=2 // http://localhost:8080/any/any?start=1000&stop=1&stop=2
server server
.Given(Request.Create().WithPath("/*").UsingGet()) .Given(Request.Create().WithPath("/*").UsingGet())
.WithGuid(Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05")) .WithGuid(Guid.Parse("90356dba-b36c-469a-a17e-669cd84f1f05"))
.AtPriority(server.Mappings.Count() + 1)
.RespondWith(Response.Create() .RespondWith(Response.Create()
.WithStatusCode(200) .WithStatusCode(200)
.WithHeader("Content-Type", "application/json") .WithHeader("Content-Type", "application/json")
@@ -37,6 +37,10 @@
<HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath> <HintPath>..\..\packages\Newtonsoft.Json.9.0.1\lib\net45\Newtonsoft.Json.dll</HintPath>
<Private>True</Private> <Private>True</Private>
</Reference> </Reference>
<Reference Include="SimMetrics.Net, Version=1.0.1.0, Culture=neutral, processorArchitecture=MSIL">
<HintPath>..\..\packages\SimMetrics.Net.1.0.1.0\lib\net45\SimMetrics.Net.dll</HintPath>
<Private>True</Private>
</Reference>
<Reference Include="System" /> <Reference Include="System" />
<Reference Include="System.Core" /> <Reference Include="System.Core" />
<Reference Include="WireMock.Net"> <Reference Include="WireMock.Net">
@@ -1,4 +1,5 @@
<?xml version="1.0" encoding="utf-8"?> <?xml version="1.0" encoding="utf-8"?>
<packages> <packages>
<package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" /> <package id="Newtonsoft.Json" version="9.0.1" targetFramework="net452" />
<package id="SimMetrics.Net" version="1.0.1.0" targetFramework="net452" />
</packages> </packages>
@@ -31,6 +31,14 @@ namespace WireMock.Admin.Requests
/// </value> /// </value>
public LogResponseModel Response { get; set; } public LogResponseModel Response { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
/// <summary> /// <summary>
/// Gets or sets the request match result. /// Gets or sets the request match result.
/// </summary> /// </summary>
+8
View File
@@ -39,5 +39,13 @@ namespace WireMock.Logging
/// The request match result. /// The request match result.
/// </value> /// </value>
public RequestMatchResult RequestMatchResult { get; set; } public RequestMatchResult RequestMatchResult { get; set; }
/// <summary>
/// Gets or sets the mapping unique identifier.
/// </summary>
/// <value>
/// The mapping unique identifier.
/// </value>
public Guid? MappingGuid { get; set; }
} }
} }
@@ -108,7 +108,7 @@ namespace WireMock.Matchers
/// <returns>Name</returns> /// <returns>Name</returns>
public string GetName() public string GetName()
{ {
return $"SimMetricsMatcher ({_simMetricType})"; return $"SimMetricsMatcher.{_simMetricType}";
} }
} }
} }
@@ -4,6 +4,7 @@ using System.Linq;
using JetBrains.Annotations; using JetBrains.Annotations;
using Newtonsoft.Json; using Newtonsoft.Json;
using Newtonsoft.Json.Linq; using Newtonsoft.Json.Linq;
using SimMetrics.Net;
using WireMock.Admin.Mappings; using WireMock.Admin.Mappings;
using WireMock.Admin.Requests; using WireMock.Admin.Requests;
using WireMock.Logging; using WireMock.Logging;
@@ -11,6 +12,7 @@ using WireMock.Matchers;
using WireMock.Matchers.Request; using WireMock.Matchers.Request;
using WireMock.RequestBuilders; using WireMock.RequestBuilders;
using WireMock.ResponseBuilders; using WireMock.ResponseBuilders;
using WireMock.Util;
namespace WireMock.Server namespace WireMock.Server
{ {
@@ -203,11 +205,12 @@ namespace WireMock.Server
BodyOriginal = logEntry.ResponseMessage.BodyOriginal, BodyOriginal = logEntry.ResponseMessage.BodyOriginal,
Headers = logEntry.ResponseMessage.Headers Headers = logEntry.ResponseMessage.Headers
}, },
RequestMatchResult = new LogRequestMatchModel MappingGuid = logEntry.MappingGuid,
RequestMatchResult = logEntry.RequestMatchResult != null ? new LogRequestMatchModel
{ {
MatchScore = logEntry.RequestMatchResult.MatchScore, MatchScore = logEntry.RequestMatchResult.MatchScore,
Total = logEntry.RequestMatchResult.Total Total = logEntry.RequestMatchResult.Total
} } : null
}; };
} }
@@ -222,26 +225,31 @@ namespace WireMock.Server
private IRequestBuilder InitRequestBuilder(MappingModel mappingModel) private IRequestBuilder InitRequestBuilder(MappingModel mappingModel)
{ {
IRequestBuilder requestBuilder = Request.Create(); IRequestBuilder requestBuilder = Request.Create();
string path = mappingModel.Request.Path as string;
if (path != null) if (mappingModel.Request.Path != null)
requestBuilder = requestBuilder.WithPath(path);
else
{ {
JToken pathToken = (JToken)mappingModel.Request.Path; string path = mappingModel.Request.Path as string;
PathModel pathModel = pathToken.ToObject<PathModel>(); if (path != null)
if (pathModel?.Matchers != null) requestBuilder = requestBuilder.WithPath(path);
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(Map).ToArray()); else
{
var pathModel = JsonUtils.ParseJTokenToObject<PathModel>(mappingModel.Request.Path);
if (pathModel?.Matchers != null)
requestBuilder = requestBuilder.WithPath(pathModel.Matchers.Select(Map).ToArray());
}
} }
string url = mappingModel.Request.Url as string; if (mappingModel.Request.Url != null)
if (url != null)
requestBuilder = requestBuilder.WithUrl(url);
else
{ {
JToken urlToken = (JToken)mappingModel.Request.Url; string url = mappingModel.Request.Url as string;
UrlModel urlModel = urlToken.ToObject<UrlModel>(); if (url != null)
if (urlModel?.Matchers != null) requestBuilder = requestBuilder.WithUrl(url);
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(Map).ToArray()); else
{
var urlModel = JsonUtils.ParseJTokenToObject<UrlModel>(mappingModel.Request.Url);
if (urlModel?.Matchers != null)
requestBuilder = requestBuilder.WithUrl(urlModel.Matchers.Select(Map).ToArray());
}
} }
if (mappingModel.Request.Methods != null) if (mappingModel.Request.Methods != null)
@@ -412,7 +420,11 @@ namespace WireMock.Server
if (matcher == null) if (matcher == null)
return null; return null;
switch (matcher.Name) var parts = matcher.Name.Split('.');
string matcherName = parts[0];
string matcherType = parts.Length > 1 ? parts[1] : null;
switch (matcherName)
{ {
case "RegexMatcher": case "RegexMatcher":
return new RegexMatcher(matcher.Pattern); return new RegexMatcher(matcher.Pattern);
@@ -423,8 +435,18 @@ namespace WireMock.Server
case "XPathMatcher": case "XPathMatcher":
return new XPathMatcher(matcher.Pattern); return new XPathMatcher(matcher.Pattern);
default: case "WildcardMatcher":
return new WildcardMatcher(matcher.Pattern, matcher.IgnoreCase == true); return new WildcardMatcher(matcher.Pattern, matcher.IgnoreCase == true);
case "SimMetricsMatcher":
SimMetricType type = SimMetricType.Levenstein;
if (!string.IsNullOrEmpty(matcherType) && !Enum.TryParse(matcherType, out type))
throw new NotSupportedException($"Matcher '{matcherName}' with Type '{matcherType}' is not supported.");
return new SimMetricsMatcher(matcher.Pattern, type);
default:
throw new NotSupportedException($"Matcher '{matcherName}' is not supported.");
} }
} }
+9 -3
View File
@@ -331,6 +331,7 @@ namespace WireMock.Server
var request = _requestMapper.Map(ctx.Request); var request = _requestMapper.Map(ctx.Request);
ResponseMessage response = null; ResponseMessage response = null;
Mapping targetMapping = null;
RequestMatchResult requestMatchResult = null; RequestMatchResult requestMatchResult = null;
try try
{ {
@@ -338,15 +339,19 @@ namespace WireMock.Server
.Select(m => new { Mapping = m, MatchResult = m.IsRequestHandled(request) }) .Select(m => new { Mapping = m, MatchResult = m.IsRequestHandled(request) })
.ToList(); .ToList();
Mapping targetMapping;
if (_allowPartialMapping) if (_allowPartialMapping)
{ {
var orderedMappings = possibleMatchingMappings var orderedMappings = possibleMatchingMappings
.OrderBy(m => m.Mapping.Priority) .Where(pm =>
.ThenBy(m => m.MatchResult) (pm.Mapping.Provider is DynamicResponseProvider && pm.MatchResult.IsPerfectMatch) ||
!(pm.Mapping.Provider is DynamicResponseProvider)
)
.OrderBy(m => m.MatchResult)
.ThenBy(m => m.Mapping.Priority)
.ToList(); .ToList();
var bestPartialMatch = orderedMappings.FirstOrDefault(); var bestPartialMatch = orderedMappings.FirstOrDefault();
targetMapping = bestPartialMatch?.Mapping; targetMapping = bestPartialMatch?.Mapping;
requestMatchResult = bestPartialMatch?.MatchResult; requestMatchResult = bestPartialMatch?.MatchResult;
} }
@@ -388,6 +393,7 @@ namespace WireMock.Server
Guid = Guid.NewGuid(), Guid = Guid.NewGuid(),
RequestMessage = request, RequestMessage = request,
ResponseMessage = response, ResponseMessage = response,
MappingGuid = targetMapping?.Guid,
RequestMatchResult = requestMatchResult RequestMatchResult = requestMatchResult
}; };
+19
View File
@@ -0,0 +1,19 @@
using Newtonsoft.Json.Linq;
namespace WireMock.Util
{
internal static class JsonUtils
{
public static T ParseJTokenToObject<T>(object value)
{
if (value == null)
return default(T);
JToken token = value as JToken;
if (token == null)
return default(T);
return token.ToObject<T>();
}
}
}