diff --git a/src/NzbDrone.Common.Test/Http/HttpUriFixture.cs b/src/NzbDrone.Common.Test/Http/HttpUriFixture.cs
new file mode 100644
index 000000000..099ab990f
--- /dev/null
+++ b/src/NzbDrone.Common.Test/Http/HttpUriFixture.cs
@@ -0,0 +1,84 @@
+using FluentAssertions;
+using NUnit.Framework;
+using NzbDrone.Common.Http;
+using NzbDrone.Test.Common;
+
+namespace NzbDrone.Common.Test.Http
+{
+ public class HttpUriFixture : TestBase
+ {
+ [TestCase("", "", "")]
+ [TestCase("/", "", "/")]
+ [TestCase("base", "", "base")]
+ [TestCase("/base", "", "/base")]
+ [TestCase("/base/", "", "/base/")]
+ [TestCase("", "relative", "relative")]
+ [TestCase("", "/relative", "/relative")]
+ [TestCase("/", "relative", "/relative")]
+ [TestCase("/", "/relative", "/relative")]
+ [TestCase("base", "relative", "relative")]
+ [TestCase("base", "/relative", "/relative")]
+ [TestCase("/base", "relative", "/relative")]
+ [TestCase("/base", "/relative", "/relative")]
+ [TestCase("/base/", "relative", "/base/relative")]
+ [TestCase("/base/", "/relative", "/relative")]
+ [TestCase("base/sub", "relative", "base/relative")]
+ [TestCase("base/sub", "/relative", "/relative")]
+ [TestCase("/base/sub", "relative", "/base/relative")]
+ [TestCase("/base/sub", "/relative", "/relative")]
+ [TestCase("/base/sub/", "relative", "/base/sub/relative")]
+ [TestCase("/base/sub/", "/relative", "/relative")]
+ [TestCase("abc://host.com:8080/root/file.xml", "relative/path", "abc://host.com:8080/root/relative/path")]
+ [TestCase("abc://host.com:8080/root/file.xml", "/relative/path", "abc://host.com:8080/relative/path")]
+ [TestCase("abc://host.com:8080/root/file.xml?query=1#fragment", "relative/path", "abc://host.com:8080/root/relative/path")]
+ [TestCase("abc://host.com:8080/root/file.xml?query=1#fragment", "/relative/path", "abc://host.com:8080/relative/path")]
+ [TestCase("abc://host.com:8080/root/api", "relative/path", "abc://host.com:8080/root/relative/path")]
+ [TestCase("abc://host.com:8080/root/api", "/relative/path", "abc://host.com:8080/relative/path")]
+ [TestCase("abc://host.com:8080/root/api/", "relative/path", "abc://host.com:8080/root/api/relative/path")]
+ [TestCase("abc://host.com:8080/root/api/", "/relative/path", "abc://host.com:8080/relative/path")]
+ [TestCase("abc://host.com:8080/root/api/", "//otherhost.com/path", "abc://otherhost.com/path")]
+ public void should_combine_uri(string basePath, string relativePath, string expected)
+ {
+ var newUri = new HttpUri(basePath) + new HttpUri(relativePath);
+ newUri.FullUri.Should().Be(expected);
+ }
+
+ [TestCase("", "", "")]
+ [TestCase("/", "", "/")]
+ [TestCase("base", "", "base")]
+ [TestCase("/base", "", "/base")]
+ [TestCase("/base/", "", "/base/")]
+ [TestCase("", "relative", "relative")]
+ [TestCase("", "/relative", "/relative")]
+ [TestCase("/", "relative", "/relative")]
+ [TestCase("/", "/relative", "/relative")]
+ [TestCase("base", "relative", "base/relative")]
+ [TestCase("base", "/relative", "base/relative")]
+ [TestCase("/base", "relative", "/base/relative")]
+ [TestCase("/base", "/relative", "/base/relative")]
+ [TestCase("/base/", "relative", "/base/relative")]
+ [TestCase("/base/", "/relative", "/base/relative")]
+ [TestCase("base/sub", "relative", "base/sub/relative")]
+ [TestCase("base/sub", "/relative", "base/sub/relative")]
+ [TestCase("/base/sub", "relative", "/base/sub/relative")]
+ [TestCase("/base/sub", "/relative", "/base/sub/relative")]
+ [TestCase("/base/sub/", "relative", "/base/sub/relative")]
+ [TestCase("/base/sub/", "/relative", "/base/sub/relative")]
+ [TestCase("/base/sub/", "relative/", "/base/sub/relative/")]
+ [TestCase("/base/sub/", "/relative/", "/base/sub/relative/")]
+ [TestCase("abc://host.com:8080/root/file.xml", "relative/path", "abc://host.com:8080/root/file.xml/relative/path")]
+ [TestCase("abc://host.com:8080/root/file.xml", "/relative/path", "abc://host.com:8080/root/file.xml/relative/path")]
+ [TestCase("abc://host.com:8080/root/file.xml?query=1#fragment", "relative/path", "abc://host.com:8080/root/file.xml/relative/path?query=1#fragment")]
+ [TestCase("abc://host.com:8080/root/file.xml?query=1#fragment", "/relative/path", "abc://host.com:8080/root/file.xml/relative/path?query=1#fragment")]
+ [TestCase("abc://host.com:8080/root/api", "relative/path", "abc://host.com:8080/root/api/relative/path")]
+ [TestCase("abc://host.com:8080/root/api", "/relative/path", "abc://host.com:8080/root/api/relative/path")]
+ [TestCase("abc://host.com:8080/root/api/", "relative/path", "abc://host.com:8080/root/api/relative/path")]
+ [TestCase("abc://host.com:8080/root/api/", "/relative/path", "abc://host.com:8080/root/api/relative/path")]
+ public void should_combine_relative_path(string basePath, string relativePath, string expected)
+ {
+ var newUri = new HttpUri(basePath).CombinePath(relativePath);
+
+ newUri.FullUri.Should().Be(expected);
+ }
+ }
+}
diff --git a/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj b/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj
index 338a9e926..84892c6b1 100644
--- a/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj
+++ b/src/NzbDrone.Common.Test/NzbDrone.Common.Test.csproj
@@ -83,6 +83,7 @@
+
diff --git a/src/NzbDrone.Common/Http/HttpUri.cs b/src/NzbDrone.Common/Http/HttpUri.cs
index c8c83de66..a52a06137 100644
--- a/src/NzbDrone.Common/Http/HttpUri.cs
+++ b/src/NzbDrone.Common/Http/HttpUri.cs
@@ -131,7 +131,7 @@ namespace NzbDrone.Common.Http
return _queryParams;
}
}
-
+
public HttpUri CombinePath(string path)
{
return new HttpUri(Scheme, Host, Port, CombinePath(Path, path), Query, Fragment);
@@ -144,23 +144,34 @@ namespace NzbDrone.Common.Http
return basePath;
}
- var newPath = "/" + relativePath.TrimStart('/');
-
- if (basePath != null && !relativePath.StartsWith("/"))
+ if (basePath.IsNullOrWhiteSpace())
{
- var baseSlashIndex = basePath.LastIndexOf('/');
-
- if (baseSlashIndex == basePath.Length - 1)
- {
- newPath = basePath.TrimEnd('/') + newPath;
- }
- else if (baseSlashIndex != 0)
- {
- newPath = basePath.Substring(0, baseSlashIndex) + newPath;
- }
+ return relativePath;
}
- return newPath;
+ return basePath.TrimEnd('/') + "/" + relativePath.TrimStart('/');
+ }
+
+ private static string CombineRelativePath(string basePath, string relativePath)
+ {
+ if (relativePath.IsNullOrWhiteSpace())
+ {
+ return basePath;
+ }
+
+ if (relativePath.StartsWith("/"))
+ {
+ return relativePath;
+ }
+
+ var baseSlashIndex = basePath.LastIndexOf('/');
+
+ if (baseSlashIndex >= 0)
+ {
+ return basePath.Substring(0, baseSlashIndex) + "/" + relativePath;
+ }
+
+ return relativePath;
}
public HttpUri SetQuery(string query)
@@ -252,7 +263,7 @@ namespace NzbDrone.Common.Http
if (relativeUrl.Path.IsNotNullOrWhiteSpace())
{
- return new HttpUri(baseUrl.Scheme, baseUrl.Host, baseUrl.Port, HttpUri.CombinePath(baseUrl.Path, relativeUrl.Path), relativeUrl.Query, relativeUrl.Fragment);
+ return new HttpUri(baseUrl.Scheme, baseUrl.Host, baseUrl.Port, CombineRelativePath(baseUrl.Path, relativeUrl.Path), relativeUrl.Query, relativeUrl.Fragment);
}
return new HttpUri(baseUrl.Scheme, baseUrl.Host, baseUrl.Port, baseUrl.Path, relativeUrl.Query, relativeUrl.Fragment);