mirror of
https://github.com/wiremock/WireMock.Net.git
synced 2026-03-14 06:17:11 +01:00
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:
@@ -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[] { });
|
||||
|
||||
|
||||
@@ -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; }
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
71
src/WireMock.Net/Util/HttpStatusRangeParser.cs
Normal file
71
src/WireMock.Net/Util/HttpStatusRangeParser.cs
Normal 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;
|
||||
}
|
||||
}
|
||||
}
|
||||
75
test/WireMock.Net.Tests/Util/HttpStatusRangeParserTests.cs
Normal file
75
test/WireMock.Net.Tests/Util/HttpStatusRangeParserTests.cs
Normal 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user