tags:

views:

51

answers:

2

I have a relative or absolute url in a string. I first need to know whether it is absolute or relative. How do I do this? I then want to determine if the domain of the url is in an allow list.

Here is my allow list, as an example:

string[] Allowed =
{
   "google.com",
   "yahoo.com",
   "espn.com"
}

Once I know whether its relative or absolute, its fairly simple I think:

if (Url.IsAbsolute)
{
    if (!Url.Contains("://"))
        Url = "http://" + Url;

    return Allowed.Contains(new Uri(Url).Host);
}
else //Is Relative
{
    return true;
}
A: 
        bool IsAbsoluteUrl(string url)
        {
            Uri result;
            return Uri.TryCreate(url, UriKind.Absolute, out result);                
        }
Hasan Khan
You can use the `Uri.TryCreate` method instead for prettier code.
Ian Henry
Works. Does the Uri.TryCreate check if the url resolves?
Mark
@Ian Henry thanks for the suggestion.
Hasan Khan
+1  A: 

You can achieve what you want more directly with UriBuilder which can handle both relative and absolute URIs (see example below).

@icktoofay makes a good point as well: be sure to either include subdomains (like www.google.com) in your allowed list or do more processing on the builder.Host property to get the actual domain. If you do decide to do more processing, don't forget about URLs with complex TLDs like bbc.co.uk.

using System;
using System.Linq;
using System.Diagnostics;

namespace UriTest
{
    class Program
    {
        static bool IsAllowed(string uri, string[] allowedHosts)
        {
            UriBuilder builder = new UriBuilder(uri);
            return allowedHosts.Contains(builder.Host, StringComparer.OrdinalIgnoreCase);
        }

        static void Main(string[] args)
        {
            string[] allowedHosts =
            {
                "google.com",
                "yahoo.com",
                "espn.com"
            };

            // All true
            Debug.Assert(
                IsAllowed("google.com", allowedHosts) &&
                IsAllowed("google.com/bar", allowedHosts) &&
                IsAllowed("http://google.com/", allowedHosts) &&
                IsAllowed("http://google.com/foo/bar", allowedHosts) &&
                IsAllowed("http://google.com/foo/page.html?bar=baz", allowedHosts)
            );

            // All false
            Debug.Assert(
                !IsAllowed("foo.com", allowedHosts) &&
                !IsAllowed("foo.com/bar", allowedHosts) &&
                !IsAllowed("http://foo.com/", allowedHosts) &&
                !IsAllowed("http://foo.com/foo/bar", allowedHosts) &&
                !IsAllowed("http://foo.com/foo/page.html?bar=baz", allowedHosts)
            );
        }
    }
}
Chris Schmich
Does this work with relative urls? Something like `./page/test.aspx` Edit: just tested and it failed to handle a relative url. Does uribuilder have methods to handle relative stuff?
Mark
@Mark: no, there's no way for `UriBuilder` to know what host you want in that case. It throws an exception. I don't think any approach can handle that case, though, since that is a URL relative to nothing (or at least it's not specified).
Chris Schmich
@Mark: ignore my last comment, I see that you just want to `return true;` for the relative case, so you can use `Uri.TryCreate` as @Ian suggests.
Chris Schmich
I used the other code to determine if the url is absolute or relative, and your code for the contains part. Thanks.
Mark