DEV Community

Jonas Samuelsson
Jonas Samuelsson

Posted on

6 1

Constructing uris in dotnet is harder than it should

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}");
      }
    }
  }
}
Enter fullscreen mode Exit fullscreen mode

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
Enter fullscreen mode Exit fullscreen mode

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. 😱

Do your career a big favor. Join DEV. (The website you're on right now)

It takes one minute, it's free, and is worth it for your career.

Get started

Community matters

Top comments (2)

Collapse
 
paulasantamaria profile image
Paula Santamaría • Edited

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.

Collapse
 
moejoe profile image
Moritz Haslhofer

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.

👋 Kindness is contagious

Immerse yourself in a wealth of knowledge with this piece, supported by the inclusive DEV Community—every developer, no matter where they are in their journey, is invited to contribute to our collective wisdom.

A simple “thank you” goes a long way—express your gratitude below in the comments!

Gathering insights enriches our journey on DEV and fortifies our community ties. Did you find this article valuable? Taking a moment to thank the author can have a significant impact.

Okay