Skip to content
Merged
10 changes: 9 additions & 1 deletion src/WireMock.Net.Abstractions/Admin/Mappings/RequestModel.cs
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
// Copyright © WireMock.Net

using WireMock.Matchers.Request;

namespace WireMock.Admin.Mappings;

/// <summary>
Expand Down Expand Up @@ -61,9 +63,15 @@ public class RequestModel
/// Gets or sets the Params.
/// </summary>
public IList<ParamModel>? Params { get; set; }

/// <summary>
/// Gets or sets the body.
/// </summary>
public BodyModel? Body { get; set; }

/// <summary>
/// Type of the request matcher to return an immediate mismatch during mapping processing.
/// Optional.
/// </summary>
public RequestMatcherType? EarlyMatcherType { get; set; }
}
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,11 @@ namespace WireMock.Matchers.Request;
/// </summary>
public interface IRequestMatcher
{
/// <summary>
/// Gets the request matcher's type.
/// </summary>
public RequestMatcherType Type { get; }

/// <summary>
/// Determines whether the specified RequestMessage is match.
/// </summary>
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,84 @@
// Copyright © WireMock.Net

namespace WireMock.Matchers.Request;

/// <summary>
/// List of predefined request matcher types.
/// </summary>
public enum RequestMatcherType
{
/// <summary>
/// RequestMessageBodyMatcher
/// </summary>
Body = 0,

/// <summary>
/// RequestMessageBodyMatcher{T}
/// </summary>
BodyOfT = 1,

/// <summary>
/// RequestMessageClientIPMatcher
/// </summary>
ClientIP = 2,

/// <summary>
/// RequestMessageCookieMatcher
/// </summary>
Cookie = 3,

/// <summary>
/// RequestMessageGraphQLMatcher
/// </summary>
GraphQL = 4,

/// <summary>
/// RequestMessageHeaderMatcher
/// </summary>
Header = 5,

/// <summary>
/// RequestMessageHttpVersionMatcher
/// </summary>
HttpVersion = 6,

/// <summary>
/// RequestMessageMethodMatcher
/// </summary>
Method = 7,

/// <summary>
/// RequestMessageMultiPartMatcher
/// </summary>
MultiPart = 8,

/// <summary>
/// RequestMessageParamMatcher
/// </summary>
Param = 9,

/// <summary>
/// RequestMessagePathMatcher
/// </summary>
Path = 10,

/// <summary>
/// RequestMessageProtoBufMatcher
/// </summary>
ProtoBuf = 11,

/// <summary>
/// RequestMessageScenarioAndStateMatcher
/// </summary>
ScenarioAndState = 12,

/// <summary>
/// RequestMessageUrlMatcher
/// </summary>
Url = 13,

/// <summary>
/// RequestMessageCompositeMatcher
/// </summary>
Composite = 14
}
Original file line number Diff line number Diff line change
Expand Up @@ -142,6 +142,9 @@ public RequestMessageBodyMatcher(MatchOperator matchOperator, params IMatcher[]
MatchOperator = matchOperator;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Body;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,9 @@ public RequestMessageBodyMatcher(Func<T?, bool> func)
Func = Guard.NotNull(func);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.BodyOfT;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -74,6 +74,9 @@ public RequestMessageClientIPMatcher(params Func<string, bool>[] funcs)
Funcs = Guard.NotNull(funcs);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ClientIP;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,11 @@ public abstract class RequestMessageCompositeMatcher : IRequestMatcher
/// </value>
private IEnumerable<IRequestMatcher> RequestMatchers { get; }

/// <summary>
/// Selected type to choose the matcher from <see cref="RequestMatchers"/> which will immediately return a mismatch.
/// </summary>
internal RequestMatcherType? EarlyMatcherType { get; private protected set; }

/// <summary>
/// Initializes a new instance of the <see cref="RequestMessageCompositeMatcher"/> class.
/// </summary>
Expand All @@ -31,6 +36,9 @@ protected RequestMessageCompositeMatcher(IEnumerable<IRequestMatcher> requestMat
_type = type;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Composite;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand All @@ -39,6 +47,13 @@ public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResu
return MatchScores.Mismatch;
}

var earlyMatcher = new RequestMessageEarlyMatcher(EarlyMatcherType, RequestMatchers);
var earlyMatchResult = earlyMatcher.GetMatchingScore(requestMessage, requestMatchResult);
if (!MatchScores.IsPerfect(earlyMatchResult))
{
return MatchScores.Mismatch;
}

if (_type == CompositeMatcherType.And)
{
return RequestMatchers.Average(requestMatcher => requestMatcher.GetMatchingScore(requestMessage, requestMatchResult));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -93,6 +93,9 @@ public RequestMessageCookieMatcher(params Func<IDictionary<string, string>, bool
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Cookie;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
// Copyright © WireMock.Net

namespace WireMock.Matchers.Request;

/// <summary>
/// Return the mismatch if the matching score of matchers is not perfect.
/// </summary>
internal sealed class RequestMessageEarlyMatcher(
RequestMatcherType? earlyMatcherType,
IEnumerable<IRequestMatcher> requestMatchers) : IRequestMatcher
{
/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Composite;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
if (earlyMatcherType is null)
Comment thread
StefH marked this conversation as resolved.
{
return MatchScores.Perfect;
}

var earlyMatchers = requestMatchers
.Where(m => m.Type == earlyMatcherType)
.ToList();

if (earlyMatchers.Count is 0)
{
return MatchScores.Perfect;
}

var compositeMatcher = new RequestBuilders.Request(earlyMatchers);
return compositeMatcher.GetMatchingScore(requestMessage, requestMatchResult);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -106,6 +106,9 @@ public RequestMessageHeaderMatcher(params Func<IDictionary<string, string[]>, bo
Name = string.Empty; // Not used when Func, but set to a non-null valid value.
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Header;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -65,6 +65,9 @@ public RequestMessageHttpVersionMatcher(Func<string, bool> func)
MatcherOnStringFunc = Guard.NotNull(func);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.HttpVersion;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,9 @@ public RequestMessageMethodMatcher(MatchBehaviour matchBehaviour, MatchOperator
MatchOperator = matchOperator;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Method;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,9 @@ public RequestMessageMultiPartMatcher(MatchBehaviour matchBehaviour, MatchOperat
MatchOperator = matchOperator;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.MultiPart;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -82,6 +82,9 @@ public RequestMessageParamMatcher(params Func<IDictionary<string, WireMockList<s
Funcs = Guard.NotNull(funcs);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Param;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public RequestMessagePathMatcher(params Func<string, bool>[] funcs)
Funcs = Guard.NotNull(funcs);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Path;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,9 @@ public RequestMessageScenarioAndStateMatcher(string? nextState, string? executio
_executionConditionState = executionConditionState;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ScenarioAndState;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -72,6 +72,9 @@ public RequestMessageUrlMatcher(params Func<string, bool>[] funcs)
Funcs = Guard.NotNull(funcs);
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.Url;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
9 changes: 8 additions & 1 deletion src/WireMock.Net.Minimal/RequestBuilders/Request.cs
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ public static IRequestBuilder Create()
/// Initializes a new instance of the <see cref="Request"/> class.
/// </summary>
/// <param name="requestMatchers">The request matchers.</param>
private Request(IList<IRequestMatcher> requestMatchers) : base(requestMatchers)
internal Request(IList<IRequestMatcher> requestMatchers) : base(requestMatchers)
{
_requestMatchers = Guard.NotNull(requestMatchers);
}
Expand Down Expand Up @@ -81,6 +81,13 @@ public IRequestBuilder Add<T>(T requestMatcher) where T : IRequestMatcher
return this;
}

/// <inheritdoc />
public IRequestBuilder WithEarlyMismatch(RequestMatcherType? earlyMatcherType)
{
EarlyMatcherType = earlyMatcherType;
return this;
}

internal bool TryGetProtoBufMatcher([NotNullWhen(true)] out IProtoBufMatcher? protoBufMatcher)
{
protoBufMatcher = GetRequestMessageMatcher<RequestMessageProtoBufMatcher>()?.Matcher;
Expand Down
10 changes: 9 additions & 1 deletion src/WireMock.Net.Minimal/Serialization/MappingConverter.cs
Original file line number Diff line number Diff line change
Expand Up @@ -66,6 +66,12 @@ public string ToCSharpCode(IMapping mapping, MappingConverterSettings? settings

// Request
sb.AppendLine(" .Given(Request.Create()");

if (request.EarlyMatcherType != null)
{
sb.AppendLine($" .WithEarlyMismatch({request.EarlyMatcherType.Value.GetFullyQualifiedEnumValue()})");
}

sb.AppendLine($" .UsingMethod({To1Or2Or3Arguments(methodMatcher?.MatchBehaviour, methodMatcher?.MatchOperator, methodMatcher?.Methods, HttpRequestMethod.GET)})");

if (pathMatcher?.Matchers != null)
Expand Down Expand Up @@ -300,7 +306,9 @@ public MappingModel ToMappingModel(IMapping mapping)
IgnoreCase = pm.IgnoreCase ? true : null,
RejectOnMatch = pm.MatchBehaviour == MatchBehaviour.RejectOnMatch ? true : null,
Matchers = _mapper.Map(pm.Matchers)
}).ToList() : null
}).ToList() : null,

EarlyMatcherType = request.EarlyMatcherType
},
Response = new ResponseModel()
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -268,6 +268,8 @@ private IRequestBuilder InitRequestBuilder(RequestModel requestModel, MappingMod
}
}

requestBuilder = requestBuilder.WithEarlyMismatch(requestModel.EarlyMatcherType);

return requestBuilder;
}

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -69,6 +69,9 @@ public RequestMessageGraphQLMatcher(MatchOperator matchOperator, params IMatcher
MatchOperator = matchOperator;
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.GraphQL;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,9 @@ public RequestMessageProtoBufMatcher(MatchBehaviour matchBehaviour, Func<IdOrTex
}
}

/// <inheritdoc />
public RequestMatcherType Type => RequestMatcherType.ProtoBuf;

/// <inheritdoc />
public double GetMatchingScore(IRequestMessage requestMessage, IRequestMatchResult requestMatchResult)
{
Expand Down
Loading
Loading