using System;
using System.Linq;
using System.Net;
using System.Text.RegularExpressions;
namespace WireMock.Util;
///
/// Based on https://github.com/tmenier/Flurl/blob/129565361e135e639f1d44a35a78aea4302ac6ca/src/Flurl.Http/HttpStatusRangeParser.cs
///
internal static class HttpStatusRangeParser
{
///
/// Determines whether the specified pattern is match.
///
/// The pattern. (Can be null, in that case it's allowed.)
/// The value.
/// is invalid.
public static bool IsMatch(string? pattern, object? httpStatusCode)
{
return httpStatusCode switch
{
int statusCodeAsInteger => IsMatch(pattern, statusCodeAsInteger),
string statusCodeAsString => IsMatch(pattern, int.Parse(statusCodeAsString)),
_ => false
};
}
///
/// Determines whether the specified pattern is match.
///
/// The pattern. (Can be null, in that case it's allowed.)
/// The value.
/// is invalid.
public static bool IsMatch(string pattern, HttpStatusCode httpStatusCode)
{
return IsMatch(pattern, (int)httpStatusCode);
}
///
/// Determines whether the specified pattern is match.
///
/// The pattern. (Can be null, in that case it's allowed.)
/// The value.
/// is invalid.
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;
}
}