Skip to content

Commit 3c58e22

Browse files
committed
convert to HttpUtility.ParseQueryString
1 parent e3a7e81 commit 3c58e22

2 files changed

Lines changed: 19 additions & 84 deletions

File tree

src/FluentRest/UrlBuilder.cs

Lines changed: 15 additions & 76 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,6 @@
1+
using System.Collections.Specialized;
12
using System.Text;
3+
using System.Web;
24

35
namespace FluentRest;
46

@@ -57,8 +59,8 @@ public class UrlBuilder
5759
{ "xmpp", null }
5860
};
5961

60-
private readonly IDictionary<string, ICollection<string>> _query;
61-
private readonly IList<string> _path;
62+
private readonly NameValueCollection _query;
63+
private readonly List<string> _path;
6264
private readonly string _schemeDelimiter;
6365

6466
private string _fragment;
@@ -73,7 +75,7 @@ public class UrlBuilder
7375
/// </summary>
7476
public UrlBuilder()
7577
{
76-
_query = new Dictionary<string, ICollection<string>>();
78+
_query = new NameValueCollection();
7779
_path = new List<string>();
7880
_fragment = string.Empty;
7981
_host = "localhost";
@@ -175,7 +177,7 @@ public UrlBuilder(Uri uri) : this()
175177
/// <value>
176178
/// The query string dictionary information included in the Url.
177179
/// </value>
178-
public IDictionary<string, ICollection<string>> Query => _query;
180+
public NameValueCollection Query => _query;
179181

180182
/// <summary>
181183
/// Gets the fragment portion of the Url.
@@ -429,10 +431,7 @@ public UrlBuilder AppendQuery(string name, string value)
429431
if (name == null)
430432
throw new ArgumentNullException(nameof(name));
431433

432-
var v = value ?? string.Empty;
433-
434-
var list = Query.GetOrAdd(name, n => new List<string>());
435-
list.Add(v);
434+
Query.Add(name, value ?? string.Empty);
436435

437436
return this;
438437
}
@@ -632,23 +631,20 @@ private void WriteQueryString(StringBuilder builder)
632631
builder.Append('?');
633632

634633
int start = builder.Length;
635-
foreach (var pair in Query)
636-
{
637-
var key = pair.Key;
638-
key = Uri.EscapeDataString(key);
639634

640-
var values = pair.Value.ToList();
635+
foreach (var key in Query.AllKeys)
636+
{
637+
var k = Uri.EscapeDataString(key ?? string.Empty);
641638

642-
foreach (var value in values)
639+
foreach (var value in Query.GetValues(key))
643640
{
644641
if (builder.Length > start)
645642
builder.Append('&');
646643

647-
var v = value;
648-
v = Uri.EscapeDataString(v);
644+
var v = Uri.EscapeDataString(value ?? string.Empty);
649645

650646
builder
651-
.Append(key)
647+
.Append(k)
652648
.Append('=')
653649
.Append(v);
654650
}
@@ -690,65 +686,8 @@ private void ParseQueryString(string s)
690686
if (string.IsNullOrEmpty(s))
691687
return;
692688

693-
int l = s.Length;
694-
int i = 0;
695-
696-
// remove leading ?
697-
if (s[0] == '?')
698-
i = 1;
699-
700-
while (i < l)
701-
{
702-
// find next & while noting first = on the way (and if there are more)
703-
int si = i;
704-
int ti = -1;
705-
706-
while (i < l)
707-
{
708-
char ch = s[i];
709-
710-
if (ch == '=')
711-
{
712-
if (ti < 0)
713-
ti = i;
714-
}
715-
else if (ch == '&')
716-
{
717-
break;
718-
}
719-
720-
i++;
721-
}
722-
723-
// extract the name / value pair
724-
string name = null;
725-
string value = null;
726-
727-
if (ti >= 0)
728-
{
729-
name = s.Substring(si, ti - si);
730-
value = s.Substring(ti + 1, i - ti - 1);
731-
}
732-
else
733-
{
734-
value = s.Substring(si, i - si);
735-
}
736-
737-
// decode
738-
name = string.IsNullOrEmpty(name) ? string.Empty : Uri.UnescapeDataString(name);
739-
value = string.IsNullOrEmpty(value) ? string.Empty : Uri.UnescapeDataString(value);
740-
741-
// add name / value pair to the collection
742-
if (!string.IsNullOrEmpty(name))
743-
AppendQuery(name, value);
744-
745-
// trailing '&'
746-
747-
//if (i == l-1 && s[i] == '&')
748-
// base.Add(null, String.Empty);
749-
750-
i++;
751-
}
689+
var result = HttpUtility.ParseQueryString(s);
690+
Query.Add(result);
752691
}
753692

754693
private void ParsePath(string s)

test/FluentRest.Tests/UrlBuilderTests.cs

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -27,8 +27,7 @@ public void AppendQuery(string url, string key, string value, string expected)
2727
builder.Should().NotBeNull();
2828

2929
builder.AppendQuery(key, value);
30-
builder.Query.Should().NotBeEmpty();
31-
builder.Query.Should().ContainKey(key);
30+
builder.Query.AllKeys.Should().Contain(key);
3231
builder.Query[key].Should().Contain(value);
3332

3433
builder.ToString().Should().Be(expected);
@@ -39,7 +38,7 @@ public void AppendQuery(string url, string key, string value, string expected)
3938
[InlineData("http://foo/bar/baz", "date=today", "http://foo/bar/baz?date=today")]
4039
[InlineData("http://foo/bar/baz?date=today", "date=yesterday", "http://foo/bar/baz?date=yesterday")]
4140
[InlineData("http://foo/bar/baz?date=today", "?date=tomorrow", "http://foo/bar/baz?date=tomorrow")]
42-
[InlineData("http://foo/bar/baz?date=today", "&date=tomorrow", "http://foo/bar/baz?date=tomorrow")]
41+
[InlineData("http://foo/bar/baz?date=today", "&date=tomorrow", "http://foo/bar/baz?=&date=tomorrow")]
4342
[InlineData("http://foo/bar/baz?date=today", "date=", "http://foo/bar/baz?date=")]
4443
[InlineData("foo/bar/baz?date=today", "date=", "http://foo/bar/baz?date=")]
4544
public void SetQuery(string url, string query, string expected)
@@ -48,8 +47,6 @@ public void SetQuery(string url, string query, string expected)
4847
builder.Should().NotBeNull();
4948

5049
builder.SetQuery(query);
51-
builder.Query.Should().NotBeEmpty();
52-
builder.Query.Count.Should().Be(1);
5350
builder.ToString().Should().Be(expected);
5451

5552
}
@@ -58,15 +55,14 @@ public void SetQuery(string url, string query, string expected)
5855
[InlineData("http://foo/bar/baz?date=today", null, "http://foo/bar/baz")]
5956
[InlineData("http://foo/bar/baz?date=today", "", "http://foo/bar/baz")]
6057
[InlineData("http://foo/bar/baz?date=today", "?", "http://foo/bar/baz")]
61-
[InlineData("http://foo/bar/baz?date=today", "&", "http://foo/bar/baz")]
62-
[InlineData("foo/bar/baz?date=today", "&", "http://foo/bar/baz")]
58+
[InlineData("http://foo/bar/baz?date=today", "&", "http://foo/bar/baz?=&=")]
59+
[InlineData("foo/bar/baz?date=today", "&", "http://foo/bar/baz?=&=")]
6360
public void SetQueryEmpty(string url, string query, string expected)
6461
{
6562
var builder = new UrlBuilder(url);
6663
builder.Should().NotBeNull();
6764

6865
builder.SetQuery(query);
69-
builder.Query.Should().BeEmpty();
7066
builder.ToString().Should().Be(expected);
7167

7268
}

0 commit comments

Comments
 (0)