Add Proxy Setting for: SaveMappingForStatusCodePattern to only save the mapping when the status code matches the pattern (#357)

* proxy

* HttpStatusRangeParserTests

* test
This commit is contained in:
Stef Heyenrath
2019-10-10 08:18:58 +02:00
committed by GitHub
parent 87534c35f5
commit 4a2d512f83
5 changed files with 163 additions and 3 deletions

View File

@@ -267,7 +267,8 @@ namespace WireMock.Server
var responseMessage = await HttpClientHelper.SendAsync(_httpClientForProxy, requestMessage, proxyUriWithRequestPathAndQuery.AbsoluteUri);
if (settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile)
if (HttpStatusRangeParser.IsMatch(settings.ProxyAndRecordSettings.SaveMappingForStatusCodePattern, responseMessage.StatusCode) &&
(settings.ProxyAndRecordSettings.SaveMapping || settings.ProxyAndRecordSettings.SaveMappingToFile))
{
var mapping = ToMapping(requestMessage, responseMessage, settings.ProxyAndRecordSettings.BlackListedHeaders ?? new string[] { }, settings.ProxyAndRecordSettings.BlackListedCookies ?? new string[] { });

View File

@@ -1,4 +1,6 @@
namespace WireMock.Settings
using JetBrains.Annotations;
namespace WireMock.Settings
{
/// <summary>
/// IProxyAndRecordSettings
@@ -16,7 +18,14 @@
bool SaveMapping { get; set; }
/// <summary>
/// Save the mapping for each request/response to also file. (Note that SaveMapping must also be set to true.)
/// Only save request/response to the internal Mappings if the status code is included in this pattern. (Note that SaveMapping must also be set to true.)
/// The pattern can contain a single value like "200", but also ranges like "2xx", "100,300,600" or "100-299,6xx" are supported.
/// </summary>
[CanBeNull]
string SaveMappingForStatusCodePattern { get; set; }
/// <summary>
/// Save the mapping for each request/response also to a file. (Note that SaveMapping must also be set to true.)
/// </summary>
bool SaveMappingToFile { get; set; }

View File

@@ -15,6 +15,10 @@ namespace WireMock.Settings
[PublicAPI]
public bool SaveMapping { get; set; } = true;
/// <inheritdoc cref="IProxyAndRecordSettings.SaveMappingForStatusCodePattern"/>
[PublicAPI]
public string SaveMappingForStatusCodePattern { get; set; } = "*";
/// <inheritdoc cref="IProxyAndRecordSettings.SaveMappingToFile"/>
[PublicAPI]
public bool SaveMappingToFile { get; set; } = true;

View File

@@ -0,0 +1,71 @@
using System;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace WireMock.Util
{
/// <summary>
/// Based on https://github.com/tmenier/Flurl/blob/129565361e135e639f1d44a35a78aea4302ac6ca/src/Flurl.Http/HttpStatusRangeParser.cs
/// </summary>
internal static class HttpStatusRangeParser
{
/// <summary>
/// Determines whether the specified pattern is match.
/// </summary>
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
/// <param name="httpStatusCode">The value.</param>
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
public static bool IsMatch(string pattern, HttpStatusCode httpStatusCode)
{
return IsMatch(pattern, (int)httpStatusCode);
}
/// <summary>
/// Determines whether the specified pattern is match.
/// </summary>
/// <param name="pattern">The pattern. (Can be null, in that case it's allowed.)</param>
/// <param name="httpStatusCode">The value.</param>
/// <exception cref="ArgumentException"><paramref name="pattern"/> is invalid.</exception>
public static bool IsMatch(string pattern, int httpStatusCode)
{
if (pattern == null)
{
return true;
}
foreach (var range in pattern.Split(',').Select(p => p.Trim()))
{
switch (range)
{
case "":
continue;
case "*":
return true; // special case - allow everything
}
string[] bounds = range.Split('-');
int lower = 0;
int upper = 0;
bool valid =
bounds.Length <= 2 &&
int.TryParse(Regex.Replace(bounds.First().Trim(), "[*xX]", "0"), out lower) &&
int.TryParse(Regex.Replace(bounds.Last().Trim(), "[*xX]", "9"), out upper);
if (!valid)
{
throw new ArgumentException($"Invalid range pattern: \"{pattern}\". Examples of allowed patterns: \"400\", \"4xx\", \"300,400-403\", \"*\".");
}
if (httpStatusCode >= lower && httpStatusCode <= upper)
{
return true;
}
}
return false;
}
}
}

View File

@@ -0,0 +1,75 @@
using FluentAssertions;
using System;
using System.Net;
using WireMock.Util;
using Xunit;
namespace WireMock.Net.Tests.Util
{
/// <summary>
/// Based on https://raw.githubusercontent.com/tmenier/Flurl/129565361e135e639f1d44a35a78aea4302ac6ca/Test/Flurl.Test/Http/HttpStatusRangeParserTests.cs
/// </summary>
public class HttpStatusRangeParserTests
{
[Theory]
[InlineData("4**", 399, false)]
[InlineData("4**", 400, true)]
[InlineData("4**", 499, true)]
[InlineData("4**", 500, false)]
[InlineData("4xx", 399, false)]
[InlineData("4xx", 400, true)]
[InlineData("4xx", 499, true)]
[InlineData("4xx", 500, false)]
[InlineData("4XX", 399, false)]
[InlineData("4XX", 400, true)]
[InlineData("4XX", 499, true)]
[InlineData("4XX", 500, false)]
[InlineData("400-499", 399, false)]
[InlineData("400-499", 400, true)]
[InlineData("400-499", 499, true)]
[InlineData("400-499", 500, false)]
[InlineData("100,3xx,600", 100, true)]
[InlineData("100,3xx,600", 101, false)]
[InlineData("100,3xx,600", 300, true)]
[InlineData("100,3xx,600", 399, true)]
[InlineData("100,3xx,600", 400, false)]
[InlineData("100,3xx,600", 600, true)]
[InlineData("400-409,490-499", 399, false)]
[InlineData("400-409,490-499", 405, true)]
[InlineData("400-409,490-499", 450, false)]
[InlineData("400-409,490-499", 495, true)]
[InlineData("400-409,490-499", 500, false)]
[InlineData("*", 0, true)]
[InlineData(",,,*", 9999, true)]
[InlineData("", 0, false)]
[InlineData(",,,", 9999, false)]
[InlineData(null, 399, true)]
public void HttpStatusRangeParser_ValidPattern_IsMatch(string pattern, int value, bool expectedResult)
{
HttpStatusRangeParser.IsMatch(pattern, value).Should().Be(expectedResult);
}
[Fact]
public void HttpStatusRangeParser_ValidPattern_HttpStatusCode_IsMatch()
{
HttpStatusRangeParser.IsMatch("4xx", HttpStatusCode.BadRequest).Should().BeTrue();
}
[Theory]
[InlineData("-100")]
[InlineData("100-")]
[InlineData("1yy")]
public void HttpStatusRangeParser_InvalidPattern_ThrowsException(string pattern)
{
Assert.Throws<ArgumentException>(() => HttpStatusRangeParser.IsMatch(pattern, 100));
}
}
}