A common pattern for communicating over http in dotnet is to use a HttpClient
with a base address and then add a relative path for every request. If the base address includes a parts of the path, one has to be very careful of where slashes are added or the resulting uri wont be what you expect.
We recently got bit by this at work where we suddenly started getting 404s on all requests going from one service to another.
As it turned out we had made a configuration change and a missing trailing slash in the base address was the reason.
This little sample demonstrates what happened
using System;
using System.Collections.Generic;
using System.Linq;
public class Program
{
public static void Main()
{
var baseAddresses = new [] { "http://host.io/foo", "http://host.io/foo/" };
var relativeAddresses = new [] { "bar", "/bar" };
foreach (var baseAddress in baseAddresses)
{
foreach (var relativeAddress in relativeAddresses)
{
var uri = new Uri(new Uri(baseAddress), relativeAddress).AbsoluteUri;
Console.WriteLine($"{baseAddress} + {relativeAddress} = {uri}");
}
}
}
}
And the output is
http://host.io/foo + bar = http://host.io/bar
http://host.io/foo + /bar = http://host.io/bar
http://host.io/foo/ + bar = http://host.io/foo/bar
http://host.io/foo/ + /bar = http://host.io/bar
As you can see, in three out of four possible combinations the foo
part of the base address is silently removed from the final uri. 😱
Top comments (2)
I had the same issue a while ago. So annoying!
Every time I have to work with URIs on c# I wish the framework had something like
System.IO.Path.Combine(params string[] paths)
but for URIs.i was annoyed too, until someone pointed out to me, that shockingly, this is the specified behavior by tools.ietf.org/html/rfc3986#sectio...
For the first two examples:
as far as i understand, the left url-part - if not ending in a / - could be a container or a file.
from an urls perspective there is no difference between host.io/foo and host.io/foo.html.
So the merging algorithm cuts everything on the left side, after the last slash.
For the 3rd and 4th example:
If the right url-part start with an "/" it is assumed that it is an absoulte path (starting with the resource-servers root).
So any path part after the root of the left side is cut.