mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-04-23 16:58:27 +02:00
RegexExtended in settings (#700)
* Add extra unittest for RegexExtended * settings
This commit is contained in:
@@ -18,7 +18,7 @@ namespace WireMock.Matchers
|
|||||||
public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
public class RegexMatcher : IStringMatcher, IIgnoreCaseMatcher
|
||||||
{
|
{
|
||||||
private readonly AnyOf<string, StringPattern>[] _patterns;
|
private readonly AnyOf<string, StringPattern>[] _patterns;
|
||||||
private readonly RegexExtended[] _expressions;
|
private readonly Regex[] _expressions;
|
||||||
|
|
||||||
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
/// <inheritdoc cref="IMatcher.MatchBehaviour"/>
|
||||||
public MatchBehaviour MatchBehaviour { get; }
|
public MatchBehaviour MatchBehaviour { get; }
|
||||||
@@ -31,7 +31,10 @@ namespace WireMock.Matchers
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
/// <param name="pattern">The pattern.</param>
|
/// <param name="pattern">The pattern.</param>
|
||||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||||
public RegexMatcher([NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(new[] { pattern }, ignoreCase)
|
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||||
|
/// <param name="useRegexExtended">Use RegexExtended (default = true).</param>
|
||||||
|
public RegexMatcher([NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false, bool throwException = false, bool useRegexExtended = true) :
|
||||||
|
this(MatchBehaviour.AcceptOnMatch, new[] { pattern }, ignoreCase, throwException, useRegexExtended)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -41,16 +44,10 @@ namespace WireMock.Matchers
|
|||||||
/// <param name="matchBehaviour">The match behaviour.</param>
|
/// <param name="matchBehaviour">The match behaviour.</param>
|
||||||
/// <param name="pattern">The pattern.</param>
|
/// <param name="pattern">The pattern.</param>
|
||||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||||
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false) : this(matchBehaviour, new[] { pattern }, ignoreCase)
|
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||||
{
|
/// <param name="useRegexExtended">Use RegexExtended (default = true).</param>
|
||||||
}
|
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern> pattern, bool ignoreCase = false, bool throwException = false, bool useRegexExtended = true) :
|
||||||
|
this(matchBehaviour, new[] { pattern }, ignoreCase, throwException, useRegexExtended)
|
||||||
/// <summary>
|
|
||||||
/// Initializes a new instance of the <see cref="RegexMatcher"/> class.
|
|
||||||
/// </summary>
|
|
||||||
/// <param name="patterns">The patterns.</param>
|
|
||||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
|
||||||
public RegexMatcher([NotNull, RegexPattern] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false) : this(MatchBehaviour.AcceptOnMatch, patterns, ignoreCase)
|
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -61,7 +58,8 @@ namespace WireMock.Matchers
|
|||||||
/// <param name="patterns">The patterns.</param>
|
/// <param name="patterns">The patterns.</param>
|
||||||
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
/// <param name="ignoreCase">Ignore the case from the pattern.</param>
|
||||||
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
/// <param name="throwException">Throw an exception when the internal matching fails because of invalid input.</param>
|
||||||
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false, bool throwException = false)
|
/// <param name="useRegexExtended">Use RegexExtended (default = true).</param>
|
||||||
|
public RegexMatcher(MatchBehaviour matchBehaviour, [NotNull, RegexPattern] AnyOf<string, StringPattern>[] patterns, bool ignoreCase = false, bool throwException = false, bool useRegexExtended = true)
|
||||||
{
|
{
|
||||||
Check.NotNull(patterns, nameof(patterns));
|
Check.NotNull(patterns, nameof(patterns));
|
||||||
|
|
||||||
@@ -77,7 +75,7 @@ namespace WireMock.Matchers
|
|||||||
options |= RegexOptions.IgnoreCase;
|
options |= RegexOptions.IgnoreCase;
|
||||||
}
|
}
|
||||||
|
|
||||||
_expressions = patterns.Select(p => new RegexExtended(p.GetPattern(), options)).ToArray();
|
_expressions = patterns.Select(p => useRegexExtended ? new RegexExtended(p.GetPattern(), options) : new Regex(p.GetPattern(), options)).ToArray();
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
/// <inheritdoc cref="IStringMatcher.IsMatch"/>
|
||||||
|
|||||||
@@ -16,16 +16,13 @@ namespace WireMock.RegularExpressions
|
|||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Regex"/>
|
/// <inheritdoc cref="Regex"/>
|
||||||
public RegexExtended(string pattern,
|
public RegexExtended(string pattern, RegexOptions options)
|
||||||
RegexOptions options)
|
|
||||||
: this(pattern, options, Regex.InfiniteMatchTimeout)
|
: this(pattern, options, Regex.InfiniteMatchTimeout)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
|
|
||||||
/// <inheritdoc cref="Regex"/>
|
/// <inheritdoc cref="Regex"/>
|
||||||
public RegexExtended(string pattern,
|
public RegexExtended(string pattern, RegexOptions options, TimeSpan matchTimeout)
|
||||||
RegexOptions options,
|
|
||||||
TimeSpan matchTimeout)
|
|
||||||
: base(ReplaceGuidPattern(pattern), options, matchTimeout)
|
: base(ReplaceGuidPattern(pattern), options, matchTimeout)
|
||||||
{
|
{
|
||||||
}
|
}
|
||||||
@@ -35,22 +32,31 @@ namespace WireMock.RegularExpressions
|
|||||||
{
|
{
|
||||||
// Lower case format `B` Guid pattern
|
// Lower case format `B` Guid pattern
|
||||||
{ @"\guidb", @"(\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\})" },
|
{ @"\guidb", @"(\{[a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\})" },
|
||||||
|
|
||||||
// Upper case format `B` Guid pattern
|
// Upper case format `B` Guid pattern
|
||||||
{ @"\GUIDB", @"(\{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\})" },
|
{ @"\GUIDB", @"(\{[A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\})" },
|
||||||
|
|
||||||
// Lower case format `D` Guid pattern
|
// Lower case format `D` Guid pattern
|
||||||
{ @"\guidd", "([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12})" },
|
{ @"\guidd", "([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12})" },
|
||||||
|
|
||||||
// Upper case format `D` Guid pattern
|
// Upper case format `D` Guid pattern
|
||||||
{ @"\GUIDD", "([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12})" },
|
{ @"\GUIDD", "([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12})" },
|
||||||
|
|
||||||
// Lower case format `N` Guid pattern
|
// Lower case format `N` Guid pattern
|
||||||
{ @"\guidn", "([a-z0-9]{32})" },
|
{ @"\guidn", "([a-z0-9]{32})" },
|
||||||
|
|
||||||
// Upper case format `N` Guid pattern
|
// Upper case format `N` Guid pattern
|
||||||
{ @"\GUIDN", "([A-Z0-9]{32})" },
|
{ @"\GUIDN", "([A-Z0-9]{32})" },
|
||||||
|
|
||||||
// Lower case format `P` Guid pattern
|
// Lower case format `P` Guid pattern
|
||||||
{ @"\guidp", @"(\([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\))" },
|
{ @"\guidp", @"(\([a-z0-9]{8}-([a-z0-9]{4}-){3}[a-z0-9]{12}\))" },
|
||||||
|
|
||||||
// Upper case format `P` Guid pattern
|
// Upper case format `P` Guid pattern
|
||||||
{ @"\GUIDP", @"(\([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\))" },
|
{ @"\GUIDP", @"(\([A-Z0-9]{8}-([A-Z0-9]{4}-){3}[A-Z0-9]{12}\))" },
|
||||||
|
|
||||||
// Lower case format `X` Guid pattern
|
// Lower case format `X` Guid pattern
|
||||||
{ @"\guidx", @"(\{0x[a-f0-9]{8},0x[a-f0-9]{4},0x[a-f0-9]{4},\{(0x[a-f0-9]{2},){7}(0x[a-f0-9]{2})\}\})" },
|
{ @"\guidx", @"(\{0x[a-f0-9]{8},0x[a-f0-9]{4},0x[a-f0-9]{4},\{(0x[a-f0-9]{2},){7}(0x[a-f0-9]{2})\}\})" },
|
||||||
|
|
||||||
// Upper case format `X` Guid pattern
|
// Upper case format `X` Guid pattern
|
||||||
{ @"\GUIDX", @"(\{0x[A-F0-9]{8},0x[A-F0-9]{4},0x[A-F0-9]{4},\{(0x[A-F0-9]{2},){7}(0x[A-F0-9]{2})\}\})" },
|
{ @"\GUIDX", @"(\{0x[A-F0-9]{8},0x[A-F0-9]{4},0x[A-F0-9]{4},\{(0x[A-F0-9]{2},){7}(0x[A-F0-9]{2})\}\})" },
|
||||||
};
|
};
|
||||||
@@ -62,11 +68,13 @@ namespace WireMock.RegularExpressions
|
|||||||
private static string ReplaceGuidPattern(string pattern)
|
private static string ReplaceGuidPattern(string pattern)
|
||||||
{
|
{
|
||||||
Check.NotNull(pattern, nameof(pattern));
|
Check.NotNull(pattern, nameof(pattern));
|
||||||
|
|
||||||
foreach (var tokenPattern in GuidTokenPatterns)
|
foreach (var tokenPattern in GuidTokenPatterns)
|
||||||
{
|
{
|
||||||
pattern = pattern.Replace(tokenPattern.Key, tokenPattern.Value);
|
pattern = pattern.Replace(tokenPattern.Key, tokenPattern.Value);
|
||||||
}
|
}
|
||||||
|
|
||||||
return pattern;
|
return pattern;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -41,6 +41,7 @@ namespace WireMock.Serialization
|
|||||||
var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
var matchBehaviour = matcher.RejectOnMatch == true ? MatchBehaviour.RejectOnMatch : MatchBehaviour.AcceptOnMatch;
|
||||||
bool ignoreCase = matcher.IgnoreCase == true;
|
bool ignoreCase = matcher.IgnoreCase == true;
|
||||||
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
bool throwExceptionWhenMatcherFails = _settings.ThrowExceptionWhenMatcherFails == true;
|
||||||
|
bool useRegexExtended = _settings.UseRegexExtended == true;
|
||||||
|
|
||||||
switch (matcherName)
|
switch (matcherName)
|
||||||
{
|
{
|
||||||
@@ -65,7 +66,7 @@ namespace WireMock.Serialization
|
|||||||
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
return CreateExactObjectMatcher(matchBehaviour, stringPatterns[0], throwExceptionWhenMatcherFails);
|
||||||
|
|
||||||
case nameof(RegexMatcher):
|
case nameof(RegexMatcher):
|
||||||
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails);
|
return new RegexMatcher(matchBehaviour, stringPatterns, ignoreCase, throwExceptionWhenMatcherFails, useRegexExtended);
|
||||||
|
|
||||||
case nameof(JsonMatcher):
|
case nameof(JsonMatcher):
|
||||||
object valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns;
|
object valueForJsonMatcher = matcher.Pattern ?? matcher.Patterns;
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
using System.IO;
|
using System.IO;
|
||||||
using System.Linq;
|
using System.Linq;
|
||||||
using System.Text;
|
using System.Text;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
@@ -9,7 +9,7 @@ namespace WireMock.Server
|
|||||||
{
|
{
|
||||||
public partial class WireMockServer
|
public partial class WireMockServer
|
||||||
{
|
{
|
||||||
private readonly RegexMatcher _adminFilesFilenamePathMatcher = new RegexMatcher(MatchBehaviour.AcceptOnMatch, @"^\/__admin\/files\/.*$");
|
private readonly RegexMatcher _adminFilesFilenamePathMatcher = new RegexMatcher(@"^\/__admin\/files\/.*$");
|
||||||
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
|
private static readonly Encoding[] FileBodyIsString = { Encoding.UTF8, Encoding.ASCII };
|
||||||
|
|
||||||
#region Files/{filename}
|
#region Files/{filename}
|
||||||
|
|||||||
@@ -1,9 +1,11 @@
|
|||||||
using System;
|
using System;
|
||||||
|
using System.Text.RegularExpressions;
|
||||||
using HandlebarsDotNet;
|
using HandlebarsDotNet;
|
||||||
using JetBrains.Annotations;
|
using JetBrains.Annotations;
|
||||||
using WireMock.Handlers;
|
using WireMock.Handlers;
|
||||||
using WireMock.Logging;
|
using WireMock.Logging;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
|
using WireMock.RegularExpressions;
|
||||||
#if USE_ASPNETCORE
|
#if USE_ASPNETCORE
|
||||||
using Microsoft.Extensions.DependencyInjection;
|
using Microsoft.Extensions.DependencyInjection;
|
||||||
#endif
|
#endif
|
||||||
@@ -215,5 +217,11 @@ namespace WireMock.Settings
|
|||||||
/// </summary>
|
/// </summary>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
IWebhookSettings WebhookSettings { get; set; }
|
IWebhookSettings WebhookSettings { get; set; }
|
||||||
|
|
||||||
|
/// <summary>
|
||||||
|
/// Use the <see cref="RegexExtended"/> instead of the default <see cref="Regex"/>.
|
||||||
|
/// </summary>
|
||||||
|
[PublicAPI]
|
||||||
|
bool? UseRegexExtended { get; }
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -151,5 +151,9 @@ namespace WireMock.Settings
|
|||||||
/// <inheritdoc cref="IWireMockServerSettings.WebhookSettings"/>
|
/// <inheritdoc cref="IWireMockServerSettings.WebhookSettings"/>
|
||||||
[PublicAPI]
|
[PublicAPI]
|
||||||
public IWebhookSettings WebhookSettings { get; set; }
|
public IWebhookSettings WebhookSettings { get; set; }
|
||||||
|
|
||||||
|
/// <inheritdoc cref="IWireMockServerSettings.UseRegexExtended"/>
|
||||||
|
[PublicAPI]
|
||||||
|
public bool? UseRegexExtended { get; set; } = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -1,3 +1,5 @@
|
|||||||
|
using System;
|
||||||
|
using FluentAssertions;
|
||||||
using NFluent;
|
using NFluent;
|
||||||
using WireMock.Matchers;
|
using WireMock.Matchers;
|
||||||
using Xunit;
|
using Xunit;
|
||||||
@@ -70,6 +72,32 @@ namespace WireMock.Net.Tests.Matchers
|
|||||||
Check.That(result).IsEqualTo(0.0d);
|
Check.That(result).IsEqualTo(0.0d);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RegexMatcher_IsMatch_RegexExtended_Guid()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var matcher = new RegexMatcher(@"\GUIDB", true);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
double result = matcher.IsMatch(Guid.NewGuid().ToString("B"));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be(1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
[Fact]
|
||||||
|
public void RegexMatcher_IsMatch_Regex_Guid()
|
||||||
|
{
|
||||||
|
// Assign
|
||||||
|
var matcher = new RegexMatcher(@"\GUIDB", true, false, false);
|
||||||
|
|
||||||
|
// Act
|
||||||
|
double result = matcher.IsMatch(Guid.NewGuid().ToString("B"));
|
||||||
|
|
||||||
|
// Assert
|
||||||
|
result.Should().Be(0);
|
||||||
|
}
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RegexMatcher_IsMatch_IgnoreCase()
|
public void RegexMatcher_IsMatch_IgnoreCase()
|
||||||
{
|
{
|
||||||
|
|||||||
@@ -10,7 +10,7 @@ namespace WireMock.Net.Tests.RegularExpressions
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Input guid used for testing
|
/// Input guid used for testing
|
||||||
/// </summary>
|
/// </summary>
|
||||||
public Guid InputGuid { get; } = Guid.NewGuid();
|
public Guid InputGuid => Guid.NewGuid();
|
||||||
|
|
||||||
[Fact]
|
[Fact]
|
||||||
public void RegexExtended_GuidB_Pattern()
|
public void RegexExtended_GuidB_Pattern()
|
||||||
|
|||||||
Reference in New Issue
Block a user