I'm wondering if someone else can come up with a better way of simplifying relative URLs on either the basis of System.Uri
or other means that are available in the standard .NET framework. My attempt works, but is pretty horrendous:
public static String SimplifyUrl(String url)
{
var baseDummyUri = new Uri("http://example.com", UriKind.Absolute);
var dummyUri = new Uri(baseDummyUri , String.Join("/",
Enumerable.Range(0, url.Split(new[] { ".." }, StringSplitOptions.None).Length)
.Select(i => "x")));
var absoluteResultUri = new Uri(dummyUri, url);
var resultUri = dummyUri.MakeRelativeUri(absoluteResultUri);
return resultUri.ToString();
}
This gives, for example:
./foo -> foo
foo/./bar -> foo/bar
foo/../bar -> bar
The problem that makes this so awkward is that Uri
itself doesn't seem to simplify URLs that are relative and MakeRelativeUri
also only works on absolute URLs. So to trick the Uri
class into doing what I want, I construct a base URL that has the appropriate amount of nesting.
I could also use System.IO.Path
, but then I'd have to search-and-replace backlashes to slashes...
There has to be a better way, right?
You can do it with one-liner:
new Uri(new Uri("http://example.com/"), url).AbsolutePath.TrimStart('/');
The following test shows the results:
[Theory]
[InlineData("./foo", "foo")]
[InlineData("/foo", "foo")]
[InlineData("foo", "foo")]
[InlineData("foo/./bar", "foo/bar")]
[InlineData("/foo/./bar", "foo/bar")]
[InlineData("/foo/../bar", "bar")]
[InlineData("foo/../bar", "bar")]
public void Test(string url, string expected)
{
var result = new Uri(new Uri("http://example.com/"), url).AbsolutePath.TrimStart('/');
Assert.Equal(expected, result);
}
Of course, if you want to leave /
in the beginning just remove TrimStart('/')
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With