diff --git a/src/KubeClient/Utilities/UriHelper.cs b/src/KubeClient/Utilities/UriHelper.cs
index face9e4..c67331b 100644
--- a/src/KubeClient/Utilities/UriHelper.cs
+++ b/src/KubeClient/Utilities/UriHelper.cs
@@ -7,6 +7,11 @@ namespace KubeClient.Utilities
///
public static class UriHelper
{
+ ///
+ /// A dummy URI to be used as the base URI when dealing with relative URIs.
+ ///
+ static readonly Uri DummyBaseUri = new Uri("https://dummy-host");
+
///
/// Get the path (and, if present, the query) of a URI.
///
@@ -27,10 +32,10 @@ public static string SafeGetPathAndQuery(this Uri uri)
if (uri.IsAbsoluteUri)
return uri.PathAndQuery;
- // Slightly ugly, but System.Uri doesn't attempt to parse relative URIs so we have to resort to System.UriBuilder.
- UriBuilder uriComponents = new UriBuilder(uri.OriginalString);
+ // Slightly ugly, but System.Uri doesn't attempt to parse relative URIs so we have to convert it to an absolute URI.
+ Uri absoluteUri = new Uri(DummyBaseUri, relativeUri: uri);
- return $"{uriComponents.Path}{uriComponents.Query}";
+ return absoluteUri.PathAndQuery;
}
}
}
diff --git a/test/KubeClient.Tests/UriHelperTests.cs b/test/KubeClient.Tests/UriHelperTests.cs
new file mode 100644
index 0000000..9443050
--- /dev/null
+++ b/test/KubeClient.Tests/UriHelperTests.cs
@@ -0,0 +1,96 @@
+using System;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
+
+namespace KubeClient.Tests
+{
+ using Utilities;
+ using Xunit;
+
+ ///
+ /// Tests for .
+ ///
+ public class UriHelperTests
+ {
+ static readonly Uri BaseUri = new Uri("https://localhost");
+
+ [Theory]
+ [InlineData("/")]
+ [InlineData("/?param1=value1¶m2=value2")]
+ [InlineData("path1")]
+ [InlineData("path1?param1=value1¶m2=value2")]
+ [InlineData("path1/path2")]
+ [InlineData("path1/path2?param1=value1¶m2=value2")]
+ [InlineData("path1/path2/")]
+ [InlineData("path1/path2/?param1=value1¶m2=value2")]
+ [InlineData("/path1")]
+ [InlineData("/path1?param1=value1¶m2=value2")]
+ [InlineData("/path1/path2")]
+ [InlineData("/path1/path2?param1=value1¶m2=value2")]
+ [InlineData("/path1/path2/")]
+ [InlineData("/path1/path2/?param1=value1¶m2=value2")]
+ public void Can_SafeGetPathAndQuery_RelativeUri(string input)
+ {
+ Uri uri = new Uri(input, UriKind.RelativeOrAbsolute);
+ Assert.False(uri.IsAbsoluteUri);
+
+ string pathAndQuery = uri.SafeGetPathAndQuery();
+ Assert.Equal(pathAndQuery,
+ NormalizePath(input)
+ );
+ }
+
+ [Theory]
+ [InlineData("/")]
+ [InlineData("/?param1=value1¶m2=value2")]
+ [InlineData("path1")]
+ [InlineData("path1?param1=value1¶m2=value2")]
+ [InlineData("path1/path2")]
+ [InlineData("path1/path2?param1=value1¶m2=value2")]
+ [InlineData("path1/path2/")]
+ [InlineData("path1/path2/?param1=value1¶m2=value2")]
+ [InlineData("/path1")]
+ [InlineData("/path1?param1=value1¶m2=value2")]
+ [InlineData("/path1/path2")]
+ [InlineData("/path1/path2?param1=value1¶m2=value2")]
+ [InlineData("/path1/path2/")]
+ [InlineData("/path1/path2/?param1=value1¶m2=value2")]
+ public void Can_SafeGetPathAndQuery_AbsoluteUri(string input)
+ {
+ Uri relativeUri = new Uri(input, UriKind.RelativeOrAbsolute);
+ Assert.False(relativeUri.IsAbsoluteUri);
+
+ Uri uri = new Uri(BaseUri, relativeUri);
+
+ string pathAndQuery = uri.SafeGetPathAndQuery();
+ Assert.Equal(pathAndQuery,
+ NormalizePath(input)
+ );
+ }
+
+ ///
+ /// Normalise the specified path and query for comparisons in tests.
+ ///
+ ///
+ /// The URI path and query components.
+ ///
+ ///
+ /// The normalised path and query.
+ ///
+ ///
+ /// System.Uri treats the path component of an absolute URI as an absolute path.
+ ///
+ static string NormalizePath(string pathAndQuery)
+ {
+ if (pathAndQuery == null)
+ throw new ArgumentNullException(nameof(pathAndQuery));
+
+ if (pathAndQuery.StartsWith("/"))
+ return pathAndQuery;
+
+ return $"/{pathAndQuery}";
+ }
+ }
+}