mirror of
https://github.com/Jackett/Jackett
synced 2025-01-01 04:38:20 +00:00
Add multi value processing to GetQueryString (#7915)
This commit is contained in:
parent
3010f795fd
commit
937aa6b370
2 changed files with 157 additions and 6 deletions
|
@ -138,16 +138,41 @@ namespace Jackett.Common.Utils
|
|||
return changed ? sb.ToString() : text;
|
||||
}
|
||||
|
||||
public static string GetQueryString(this NameValueCollection collection, Encoding encoding = null) =>
|
||||
string.Join("&", collection.AllKeys.Select(a =>
|
||||
$"{a}={WebUtilityHelpers.UrlEncode(collection[a], encoding ?? Encoding.UTF8)}"));
|
||||
/// <summary>
|
||||
/// Converts a NameValueCollection to an appropriately formatted query string.
|
||||
/// Duplicate keys are allowed in a NameValueCollection, but are stored as a csv string in Value.
|
||||
/// This function handles leaving the values together in the csv string or splitting the value into separate keys
|
||||
/// </summary>
|
||||
/// <param name="collection">The NameValueCollection being converted</param>
|
||||
/// <param name="encoding">The Encoding to use in url encoding Value</param>
|
||||
/// <param name="duplicateKeysIfMulti">Duplicate keys are handled as true => {"Key=Val1", "Key=Val2} or false => {"Key=Val1,Val2"}</param>
|
||||
/// <param name="separator">The string used to separate each query value</param>
|
||||
/// <returns>A web encoded string of key=value parameters separated by the separator</returns>
|
||||
public static string GetQueryString(this NameValueCollection collection, Encoding encoding = null,
|
||||
bool duplicateKeysIfMulti = false, string separator = "&") =>
|
||||
collection.ToEnumerable(duplicateKeysIfMulti).GetQueryString(encoding, separator);
|
||||
|
||||
public static string GetQueryString(this ICollection<KeyValuePair<string, string>> collection, Encoding encoding = null) =>
|
||||
string.Join("&", collection.Select(a =>
|
||||
$"{a.Key}={WebUtilityHelpers.UrlEncode(a.Value, encoding ?? Encoding.UTF8)}"));
|
||||
public static string GetQueryString(this IEnumerable<KeyValuePair<string, string>> collection,
|
||||
Encoding encoding = null, string separator = "&") =>
|
||||
string.Join(separator,
|
||||
collection.Select(a => $"{a.Key}={WebUtilityHelpers.UrlEncode(a.Value, encoding ?? Encoding.UTF8)}"));
|
||||
|
||||
public static void Add(this ICollection<KeyValuePair<string, string>> collection, string key, string value) => collection.Add(new KeyValuePair<string, string>(key, value));
|
||||
|
||||
public static IEnumerable<KeyValuePair<string, string>> ToEnumerable(
|
||||
this NameValueCollection collection, bool duplicateKeysIfMulti = false)
|
||||
{
|
||||
foreach (string key in collection.Keys)
|
||||
{
|
||||
var value = collection[key];
|
||||
if (duplicateKeysIfMulti)
|
||||
foreach (var val in value.Split(','))
|
||||
yield return new KeyValuePair<string, string>(key, val);
|
||||
else
|
||||
yield return new KeyValuePair<string, string>(key, value);
|
||||
}
|
||||
}
|
||||
|
||||
public static string ToHtmlPretty(this IElement element)
|
||||
{
|
||||
if (element == null)
|
||||
|
|
126
src/Jackett.Test/Utils/StringUtilTests.cs
Normal file
126
src/Jackett.Test/Utils/StringUtilTests.cs
Normal file
|
@ -0,0 +1,126 @@
|
|||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.Specialized;
|
||||
using System.Text;
|
||||
using NUnit.Framework;
|
||||
|
||||
namespace Jackett.Common.Utils.Tests
|
||||
{
|
||||
[TestFixture]
|
||||
public class StringUtilTests
|
||||
{
|
||||
[Test]
|
||||
public void GetQueryStringTests()
|
||||
{
|
||||
#region Encoding Tests
|
||||
|
||||
//Add windows-1251 to Encoding list if not present
|
||||
Encoding.RegisterProvider(CodePagesEncodingProvider.Instance);
|
||||
var win1251 = Encoding.GetEncoding("windows-1251");
|
||||
const string encodingTestValue = "Ру́сский";
|
||||
var encodingNvc = new NameValueCollection
|
||||
{
|
||||
{"query", encodingTestValue},
|
||||
{"space key", "space value"}
|
||||
};
|
||||
// WebUtilityHelpers.UrlEncode(encodingTestValue, Encoding.UTF8);
|
||||
const string utf8Encoded = "%D0%A0%D1%83%CC%81%D1%81%D1%81%D0%BA%D0%B8%D0%B9";
|
||||
// WebUtilityHelpers.UrlEncode(encodingTestValue, win1251);
|
||||
const string win1251Encoded = "%D0%F3%3F%F1%F1%EA%E8%E9";
|
||||
|
||||
//Default encoding is UTF-8
|
||||
StringAssert.Contains(utf8Encoded, encodingNvc.GetQueryString());
|
||||
|
||||
//Null encoding reverts to default encoding (UTF-8)
|
||||
StringAssert.Contains(utf8Encoded, encodingNvc.GetQueryString(encoding: null));
|
||||
|
||||
//Ensure non-default encoding is utilized
|
||||
StringAssert.Contains(win1251Encoded, encodingNvc.GetQueryString(encoding: win1251));
|
||||
|
||||
//Encoding should make values websafe, but not keys
|
||||
StringAssert.Contains("space key=space+value", encodingNvc.GetQueryString());
|
||||
|
||||
#endregion
|
||||
|
||||
#region Separator Tests
|
||||
|
||||
var separatorNvc = new NameValueCollection
|
||||
{
|
||||
{"one", "value"},
|
||||
{"two", "value2"}
|
||||
};
|
||||
|
||||
//Ensure default value is "&"
|
||||
Assert.AreEqual("one=value&two=value2", separatorNvc.GetQueryString());
|
||||
|
||||
//Ensure separator is overridden
|
||||
Assert.AreEqual("one=value;two=value2", separatorNvc.GetQueryString(separator: ";"));
|
||||
|
||||
//Ensure behavior when string.IsNullOrEmpty(separator)
|
||||
const string noSeparator = "one=valuetwo=value2";
|
||||
Assert.AreEqual(noSeparator, separatorNvc.GetQueryString(separator: null));
|
||||
Assert.AreEqual(noSeparator, separatorNvc.GetQueryString(separator: string.Empty));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Split Keys Tests
|
||||
|
||||
var duplicateKeysNvc = new NameValueCollection
|
||||
{
|
||||
{"key1", "value"},
|
||||
{"key2", "value2"},
|
||||
{"key1", "duplicate"}
|
||||
};
|
||||
|
||||
//Default should keep duplicated keys combined
|
||||
Assert.AreEqual("key1=value%2Cduplicate&key2=value2", duplicateKeysNvc.GetQueryString());
|
||||
|
||||
//Ensure keys are combined when requested
|
||||
Assert.AreEqual(
|
||||
"key1=value%2Cduplicate&key2=value2", duplicateKeysNvc.GetQueryString(duplicateKeysIfMulti: false));
|
||||
|
||||
//Ensure keys are separated when requested
|
||||
Assert.AreEqual(
|
||||
"key1=value&key1=duplicate&key2=value2", duplicateKeysNvc.GetQueryString(duplicateKeysIfMulti: true));
|
||||
|
||||
#endregion
|
||||
|
||||
#region Edge Case Tests
|
||||
|
||||
//Throws NullReferenceException if the NameValueCollection is null in all cases
|
||||
Assert.Throws<NullReferenceException>(() => ((NameValueCollection)null).GetQueryString());
|
||||
|
||||
//Returns empty string on empty collection in all cases
|
||||
Assert.AreEqual(string.Empty, new NameValueCollection().GetQueryString());
|
||||
|
||||
#endregion
|
||||
}
|
||||
|
||||
[Test]
|
||||
public void ToEnumerableTest()
|
||||
{
|
||||
var original = new NameValueCollection
|
||||
{
|
||||
{"first", "firstVal"},
|
||||
{"second", "secondVal"},
|
||||
{"third", "thirdVal"},
|
||||
{"second", "anotherVal"}
|
||||
};
|
||||
var combined = new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("first", "firstVal"),
|
||||
new KeyValuePair<string, string>("second", "secondVal,anotherVal"),
|
||||
new KeyValuePair<string, string>("third", "thirdVal")
|
||||
};
|
||||
var duplicateKeys = new[]
|
||||
{
|
||||
new KeyValuePair<string, string>("first", "firstVal"),
|
||||
new KeyValuePair<string, string>("second", "secondVal"),
|
||||
new KeyValuePair<string, string>("second", "anotherVal"),
|
||||
new KeyValuePair<string, string>("third", "thirdVal")
|
||||
};
|
||||
CollectionAssert.AreEqual(combined, original.ToEnumerable());
|
||||
CollectionAssert.AreEqual(duplicateKeys, original.ToEnumerable(true));
|
||||
}
|
||||
}
|
||||
}
|
Loading…
Reference in a new issue