Skip to content

Commit

Permalink
Fix URI joining (#1125)
Browse files Browse the repository at this point in the history
  • Loading branch information
chrisdunelm authored Dec 7, 2017
1 parent 4122daf commit 77debdc
Show file tree
Hide file tree
Showing 4 changed files with 4,094 additions and 3 deletions.
32 changes: 29 additions & 3 deletions Src/Support/Google.Apis.Core/Requests/RequestBuilder.cs
Original file line number Diff line number Diff line change
Expand Up @@ -96,8 +96,7 @@ public RequestBuilder()
/// <summary>Constructs a Uri as defined by the parts of this request builder.</summary>
public Uri BuildUri()
{
// URL-encode ':', so it doesn't get interpreted as a scheme.
var restPath = BuildRestPath().Replace(":", "%3A");
var restPath = BuildRestPath();

if (QueryParameters.Count > 0)
{
Expand All @@ -112,7 +111,34 @@ public Uri BuildUri()
.ToArray()));
}

return new Uri(this.BaseUri, restPath.ToString());
return UriJoin(this.BaseUri, restPath.ToString());
}

private Uri UriJoin(Uri baseUri, string path)
{
// This emulates the subset of behaviour we require from Uri(Uri, string).
// Except it does not treat ':' as a special, scheme-indicating, character in path.
if (path == "")
{
return baseUri;
}
var baseUriStr = baseUri.AbsoluteUri;
if (path.StartsWith("/"))
{
// Path is absolute; remove any path on the base URI.
baseUriStr = Regex.Replace(baseUriStr, "^([^:]+://[^/]+)/.*$", "$1");
}
else
{
if (!path.StartsWith("?") && !path.StartsWith("#"))
{
while (!baseUriStr.EndsWith("/"))
{
baseUriStr = baseUriStr.Substring(0, baseUriStr.Length - 1);
}
}
}
return new Uri(baseUriStr + path);
}

/// <summary>Operator list that can appear in the path argument.</summary>
Expand Down
15 changes: 15 additions & 0 deletions Src/Support/Google.Apis.Tests/Apis/Requests/RequestBuilderTest.cs
Original file line number Diff line number Diff line change
Expand Up @@ -61,14 +61,26 @@ public void TestPostWebRequest()
[InlineData("http://www.example.com/", "test/a:path", "http://www.example.com/test/a:path")]
[InlineData("http://www.example.com/", "a:test/path", "http://www.example.com/a:test/path")]
[InlineData("http://www.example.com/", "a:test", "http://www.example.com/a:test")]
[InlineData("http://www.example.com/z", "test/path", "http://www.example.com/test/path")]
[InlineData("http://www.example.com/z", "test/a:path", "http://www.example.com/test/a:path")]
[InlineData("http://www.example.com/z", "a:test/path", "http://www.example.com/a:test/path")]
[InlineData("http://www.example.com/z", "a:test", "http://www.example.com/a:test")]
[InlineData("http://www.example.com/z/", "test/path", "http://www.example.com/z/test/path")]
[InlineData("http://www.example.com/z/", "test/a:path", "http://www.example.com/z/test/a:path")]
[InlineData("http://www.example.com/z/", "a:test/path", "http://www.example.com/z/a:test/path")]
[InlineData("http://www.example.com/z/", "a:test", "http://www.example.com/z/a:test")]
[InlineData("http://www.example.com/z", "/test/path", "http://www.example.com/test/path")]
[InlineData("http://www.example.com/z", "/test/a:path", "http://www.example.com/test/a:path")]
[InlineData("http://www.example.com/z", "/a:test/path", "http://www.example.com/a:test/path")]
[InlineData("http://www.example.com/z", "/a:test", "http://www.example.com/a:test")]
[InlineData("http://www.example.com/z/", "/test/path", "http://www.example.com/test/path")]
[InlineData("http://www.example.com/z/", "/test/a:path", "http://www.example.com/test/a:path")]
[InlineData("http://www.example.com/z/", "/a:test/path", "http://www.example.com/a:test/path")]
[InlineData("http://www.example.com/z/", "/a:test", "http://www.example.com/a:test")]
[InlineData("http://www.example.com/z", "?abc", "http://www.example.com/z?abc")]
[InlineData("http://www.example.com/z", "#abc", "http://www.example.com/z#abc")]
[InlineData("http://www.example.com/z/", "?abc", "http://www.example.com/z/?abc")]
[InlineData("http://www.example.com/z/", "#abc", "http://www.example.com/z/#abc")]
public void TestBasePlusPath(string baseUri, string path, string expectedRequestUri)
{
var builder = new RequestBuilder()
Expand All @@ -80,7 +92,10 @@ public void TestBasePlusPath(string baseUri, string path, string expectedRequest

var request = builder.CreateRequest();
Assert.Equal(HttpMethod.Put, request.Method);
// Verify both the URI and the string representation.
// Required because URI equality hides some special character processing.
Assert.Equal(new Uri(expectedRequestUri), request.RequestUri);
Assert.Equal(new Uri(expectedRequestUri).AbsoluteUri, request.RequestUri.AbsoluteUri);
}

/// <summary>Verifies that a single query parameter is correctly encoded in the request URI.</summary>
Expand Down
Loading

0 comments on commit 77debdc

Please sign in to comment.