Skip to content

Commit 9ab1a6e

Browse files
committed
Simplify logic for SafeGetPathAndQuery by converting relative URIs into absolute ones
#163
1 parent bb32297 commit 9ab1a6e

File tree

2 files changed

+104
-3
lines changed

2 files changed

+104
-3
lines changed

src/KubeClient/Utilities/UriHelper.cs

+8-3
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,11 @@ namespace KubeClient.Utilities
77
/// </summary>
88
public static class UriHelper
99
{
10+
/// <summary>
11+
/// A dummy URI to be used as the base URI when dealing with relative URIs.
12+
/// </summary>
13+
static readonly Uri DummyBaseUri = new Uri("https://dummy-host");
14+
1015
/// <summary>
1116
/// Get the path (and, if present, the query) of a URI.
1217
/// </summary>
@@ -27,10 +32,10 @@ public static string SafeGetPathAndQuery(this Uri uri)
2732
if (uri.IsAbsoluteUri)
2833
return uri.PathAndQuery;
2934

30-
// Slightly ugly, but System.Uri doesn't attempt to parse relative URIs so we have to resort to System.UriBuilder.
31-
UriBuilder uriComponents = new UriBuilder(uri.OriginalString);
35+
// Slightly ugly, but System.Uri doesn't attempt to parse relative URIs so we have to convert it to an absolute URI.
36+
Uri absoluteUri = new Uri(DummyBaseUri, relativeUri: uri);
3237

33-
return $"{uriComponents.Path}{uriComponents.Query}";
38+
return absoluteUri.PathAndQuery;
3439
}
3540
}
3641
}
+96
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,96 @@
1+
using System;
2+
using System.Collections.Generic;
3+
using System.Linq;
4+
using System.Text;
5+
using System.Threading.Tasks;
6+
7+
namespace KubeClient.Tests
8+
{
9+
using Utilities;
10+
using Xunit;
11+
12+
/// <summary>
13+
/// Tests for <see cref="UriHelper"/>.
14+
/// </summary>
15+
public class UriHelperTests
16+
{
17+
static readonly Uri BaseUri = new Uri("https://localhost");
18+
19+
[Theory]
20+
[InlineData("/")]
21+
[InlineData("/?param1=value1&param2=value2")]
22+
[InlineData("path1")]
23+
[InlineData("path1?param1=value1&param2=value2")]
24+
[InlineData("path1/path2")]
25+
[InlineData("path1/path2?param1=value1&param2=value2")]
26+
[InlineData("path1/path2/")]
27+
[InlineData("path1/path2/?param1=value1&param2=value2")]
28+
[InlineData("/path1")]
29+
[InlineData("/path1?param1=value1&param2=value2")]
30+
[InlineData("/path1/path2")]
31+
[InlineData("/path1/path2?param1=value1&param2=value2")]
32+
[InlineData("/path1/path2/")]
33+
[InlineData("/path1/path2/?param1=value1&param2=value2")]
34+
public void Can_SafeGetPathAndQuery_RelativeUri(string input)
35+
{
36+
Uri uri = new Uri(input, UriKind.RelativeOrAbsolute);
37+
Assert.False(uri.IsAbsoluteUri);
38+
39+
string pathAndQuery = uri.SafeGetPathAndQuery();
40+
Assert.Equal(pathAndQuery,
41+
NormalizePath(input)
42+
);
43+
}
44+
45+
[Theory]
46+
[InlineData("/")]
47+
[InlineData("/?param1=value1&param2=value2")]
48+
[InlineData("path1")]
49+
[InlineData("path1?param1=value1&param2=value2")]
50+
[InlineData("path1/path2")]
51+
[InlineData("path1/path2?param1=value1&param2=value2")]
52+
[InlineData("path1/path2/")]
53+
[InlineData("path1/path2/?param1=value1&param2=value2")]
54+
[InlineData("/path1")]
55+
[InlineData("/path1?param1=value1&param2=value2")]
56+
[InlineData("/path1/path2")]
57+
[InlineData("/path1/path2?param1=value1&param2=value2")]
58+
[InlineData("/path1/path2/")]
59+
[InlineData("/path1/path2/?param1=value1&param2=value2")]
60+
public void Can_SafeGetPathAndQuery_AbsoluteUri(string input)
61+
{
62+
Uri relativeUri = new Uri(input, UriKind.RelativeOrAbsolute);
63+
Assert.False(relativeUri.IsAbsoluteUri);
64+
65+
Uri uri = new Uri(BaseUri, relativeUri);
66+
67+
string pathAndQuery = uri.SafeGetPathAndQuery();
68+
Assert.Equal(pathAndQuery,
69+
NormalizePath(input)
70+
);
71+
}
72+
73+
/// <summary>
74+
/// Normalise the specified path and query for comparisons in tests.
75+
/// </summary>
76+
/// <param name="pathAndQuery">
77+
/// The URI path and query components.
78+
/// </param>
79+
/// <returns>
80+
/// The normalised path and query.
81+
/// </returns>
82+
/// <remarks>
83+
/// System.Uri treats the path component of an absolute URI as an absolute path.
84+
/// </remarks>
85+
static string NormalizePath(string pathAndQuery)
86+
{
87+
if (pathAndQuery == null)
88+
throw new ArgumentNullException(nameof(pathAndQuery));
89+
90+
if (pathAndQuery.StartsWith("/"))
91+
return pathAndQuery;
92+
93+
return $"/{pathAndQuery}";
94+
}
95+
}
96+
}

0 commit comments

Comments
 (0)