public Impl(string pattern) { this.Pattern = pattern; Regex = new(() => { string regexPattern = ""; foreach (string part in SRegex.Split(pattern.Trim(), "(\\*+|[\\?\\|])")) { if (part.Length == 0) { continue; } regexPattern += part[0] switch { '*' => ".*", '?' => "\\w+", '|' => "\\b", _ => SRegex.Escape(part), }; } return(new SRegex($"^{regexPattern}$")); }); }
/// <summary> /// Remove all query parameters matching a particular parameter name from a URI. /// </summary> /// <remarks> /// <para>This method handles percent-encoded octets as UTF-8 encoded characters in both the /// <paramref name="parameter"/> argument and the query string.</para> /// </remarks> /// <param name="uri">The URI.</param> /// <param name="parameter">The name of the parameter to remove.</param> /// <returns>A <see cref="Uri"/> representing the input <paramref name="uri"/> with all query parameters with a name matching <paramref name="parameter"/> removed from the query string.</returns> /// <exception cref="ArgumentNullException"> /// <para>If <paramref name="uri"/> is <see langword="null"/>.</para> /// <para>-or-</para> /// <para>If <paramref name="parameter"/> is <see langword="null"/>.</para> /// </exception> /// <exception cref="ArgumentException">If <paramref name="parameter"/> is empty.</exception> public static Uri RemoveQueryParameter(Uri uri, string parameter) { if (uri == null) { throw new ArgumentNullException("uri"); } if (parameter == null) { throw new ArgumentNullException("parameter"); } if (string.IsNullOrEmpty(parameter)) { throw new ArgumentException("parameter cannot be empty"); } string query = uri.Query; if (string.IsNullOrEmpty(query)) { return(uri); } StringBuilder expressionBuilder = new StringBuilder(); byte[] encodedParameter = Encoding.UTF8.GetBytes(UriDecode(parameter)); expressionBuilder.Append("[?&]"); foreach (byte b in encodedParameter) { string escapedUpper = b.ToString("X2"); expressionBuilder.Append("(?:"); if (b == '&' || b == '?' || b == '=') { // these character can only appear percent-encoded in a parameter name expressionBuilder.Append('%'); } else { expressionBuilder.Append(Regex.Escape(((char)b).ToString())); expressionBuilder.Append("|%"); } foreach (var escaped in escapedUpper) { if (escaped != char.ToLowerInvariant(escaped)) { expressionBuilder.Append('[').Append(escaped).Append(char.ToLowerInvariant(escaped)).Append(']'); } else { expressionBuilder.Append(escaped); } } expressionBuilder.Append(")"); } expressionBuilder.Append("=[^?&]*"); Regex expression = new Regex(expressionBuilder.ToString()); UriBuilder uriBuilder = new UriBuilder(uri); string modifiedQuery = expression.Replace(uriBuilder.Query, string.Empty); // setting the UriBuilder.Query property adds a leading `?` even if one is already present in `modifiedQuery` if (!string.IsNullOrEmpty(modifiedQuery)) { modifiedQuery = modifiedQuery.Substring(1); } uriBuilder.Query = modifiedQuery; return(uriBuilder.Uri); }