Skip to content

Commit

Permalink
convert to HttpUtility.ParseQueryString
Browse files Browse the repository at this point in the history
  • Loading branch information
pwelter34 committed Sep 12, 2024
1 parent e3a7e81 commit 3c58e22
Show file tree
Hide file tree
Showing 2 changed files with 19 additions and 84 deletions.
91 changes: 15 additions & 76 deletions src/FluentRest/UrlBuilder.cs
Original file line number Diff line number Diff line change
@@ -1,4 +1,6 @@
using System.Collections.Specialized;
using System.Text;
using System.Web;

namespace FluentRest;

Expand Down Expand Up @@ -57,8 +59,8 @@ public class UrlBuilder
{ "xmpp", null }
};

private readonly IDictionary<string, ICollection<string>> _query;
private readonly IList<string> _path;
private readonly NameValueCollection _query;
private readonly List<string> _path;
private readonly string _schemeDelimiter;

private string _fragment;
Expand All @@ -73,7 +75,7 @@ public class UrlBuilder
/// </summary>
public UrlBuilder()
{
_query = new Dictionary<string, ICollection<string>>();
_query = new NameValueCollection();
_path = new List<string>();
_fragment = string.Empty;
_host = "localhost";
Expand Down Expand Up @@ -175,7 +177,7 @@ public UrlBuilder(Uri uri) : this()
/// <value>
/// The query string dictionary information included in the Url.
/// </value>
public IDictionary<string, ICollection<string>> Query => _query;
public NameValueCollection Query => _query;

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

var v = value ?? string.Empty;

var list = Query.GetOrAdd(name, n => new List<string>());
list.Add(v);
Query.Add(name, value ?? string.Empty);

return this;
}
Expand Down Expand Up @@ -632,23 +631,20 @@ private void WriteQueryString(StringBuilder builder)
builder.Append('?');

int start = builder.Length;
foreach (var pair in Query)
{
var key = pair.Key;
key = Uri.EscapeDataString(key);

var values = pair.Value.ToList();
foreach (var key in Query.AllKeys)
{
var k = Uri.EscapeDataString(key ?? string.Empty);

foreach (var value in values)
foreach (var value in Query.GetValues(key))
{
if (builder.Length > start)
builder.Append('&');

var v = value;
v = Uri.EscapeDataString(v);
var v = Uri.EscapeDataString(value ?? string.Empty);

builder
.Append(key)
.Append(k)
.Append('=')
.Append(v);
}
Expand Down Expand Up @@ -690,65 +686,8 @@ private void ParseQueryString(string s)
if (string.IsNullOrEmpty(s))
return;

int l = s.Length;
int i = 0;

// remove leading ?
if (s[0] == '?')
i = 1;

while (i < l)
{
// find next & while noting first = on the way (and if there are more)
int si = i;
int ti = -1;

while (i < l)
{
char ch = s[i];

if (ch == '=')
{
if (ti < 0)
ti = i;
}
else if (ch == '&')
{
break;
}

i++;
}

// extract the name / value pair
string name = null;
string value = null;

if (ti >= 0)
{
name = s.Substring(si, ti - si);
value = s.Substring(ti + 1, i - ti - 1);
}
else
{
value = s.Substring(si, i - si);
}

// decode
name = string.IsNullOrEmpty(name) ? string.Empty : Uri.UnescapeDataString(name);
value = string.IsNullOrEmpty(value) ? string.Empty : Uri.UnescapeDataString(value);

// add name / value pair to the collection
if (!string.IsNullOrEmpty(name))
AppendQuery(name, value);

// trailing '&'

//if (i == l-1 && s[i] == '&')
// base.Add(null, String.Empty);

i++;
}
var result = HttpUtility.ParseQueryString(s);
Query.Add(result);
}

private void ParsePath(string s)
Expand Down
12 changes: 4 additions & 8 deletions test/FluentRest.Tests/UrlBuilderTests.cs
Original file line number Diff line number Diff line change
Expand Up @@ -27,8 +27,7 @@ public void AppendQuery(string url, string key, string value, string expected)
builder.Should().NotBeNull();

builder.AppendQuery(key, value);
builder.Query.Should().NotBeEmpty();
builder.Query.Should().ContainKey(key);
builder.Query.AllKeys.Should().Contain(key);
builder.Query[key].Should().Contain(value);

builder.ToString().Should().Be(expected);
Expand All @@ -39,7 +38,7 @@ public void AppendQuery(string url, string key, string value, string expected)
[InlineData("http://foo/bar/baz", "date=today", "http://foo/bar/baz?date=today")]
[InlineData("http://foo/bar/baz?date=today", "date=yesterday", "http://foo/bar/baz?date=yesterday")]
[InlineData("http://foo/bar/baz?date=today", "?date=tomorrow", "http://foo/bar/baz?date=tomorrow")]
[InlineData("http://foo/bar/baz?date=today", "&date=tomorrow", "http://foo/bar/baz?date=tomorrow")]
[InlineData("http://foo/bar/baz?date=today", "&date=tomorrow", "http://foo/bar/baz?=&date=tomorrow")]
[InlineData("http://foo/bar/baz?date=today", "date=", "http://foo/bar/baz?date=")]
[InlineData("foo/bar/baz?date=today", "date=", "http://foo/bar/baz?date=")]
public void SetQuery(string url, string query, string expected)
Expand All @@ -48,8 +47,6 @@ public void SetQuery(string url, string query, string expected)
builder.Should().NotBeNull();

builder.SetQuery(query);
builder.Query.Should().NotBeEmpty();
builder.Query.Count.Should().Be(1);
builder.ToString().Should().Be(expected);

}
Expand All @@ -58,15 +55,14 @@ public void SetQuery(string url, string query, string expected)
[InlineData("http://foo/bar/baz?date=today", null, "http://foo/bar/baz")]
[InlineData("http://foo/bar/baz?date=today", "", "http://foo/bar/baz")]
[InlineData("http://foo/bar/baz?date=today", "?", "http://foo/bar/baz")]
[InlineData("http://foo/bar/baz?date=today", "&", "http://foo/bar/baz")]
[InlineData("foo/bar/baz?date=today", "&", "http://foo/bar/baz")]
[InlineData("http://foo/bar/baz?date=today", "&", "http://foo/bar/baz?=&=")]
[InlineData("foo/bar/baz?date=today", "&", "http://foo/bar/baz?=&=")]
public void SetQueryEmpty(string url, string query, string expected)
{
var builder = new UrlBuilder(url);
builder.Should().NotBeNull();

builder.SetQuery(query);
builder.Query.Should().BeEmpty();
builder.ToString().Should().Be(expected);

}
Expand Down

0 comments on commit 3c58e22

Please sign in to comment.