Add scheme to URL if needed

后端 未结 5 1913
耶瑟儿~
耶瑟儿~ 2020-12-08 08:49

To create a Uri from a string you can do this:

Uri u = new Uri(\"example.com\");

But the problem is if the string (like the one above) does

相关标签:
5条回答
  • 2020-12-08 09:29

    We had some specific cases where there was a legacy allowance to input stuff like: localhost:8800 or similar. Which means we needed to parse that. We built a little more elaborate ParseUri method that separated the possibility to specify a URI very loosely, but also caught the times where people would specify a non-standard scheme (and also the host in IP-long notation, because sometimes people do that)

    Just like UriBuilder it will default to the http scheme if none is specified. It will have issues if a basic authentication is specified and the password consists only of numbers. (Feel free to fix that community)

            private static Uri ParseUri(string uri)
            {
    
                if (uri.StartsWith("//"))
                    return new Uri("http:" + uri);
                if (uri.StartsWith("://"))
                    return new Uri("http" + uri);
    
                var m = System.Text.RegularExpressions.Regex.Match(uri, @"^([^\/]+):(\d+)(\/*)", System.Text.RegularExpressions.RegexOptions.IgnoreCase | System.Text.RegularExpressions.RegexOptions.Singleline);
                if (m.Success)
                {
                    var port = int.Parse(m.Groups[2].Value);
                    if (port <= 65535) //part2 is a port (65535 highest port number)
                        return new Uri("http://" + uri);
                    else if (port >= 16777217) //part2 is an ip long (16777217 first ip in long notation)
                        return new UriBuilder(uri).Uri;
                    else
                        throw new ArgumentOutOfRangeException("Invalid port or ip long, technically could be local network hostname, but someone needs to be hit on the head for that one");
                }
                else
                    return new Uri(uri);
            }
    
    0 讨论(0)
  • 2020-12-08 09:34

    If you just want to add the scheme, without validating the URL, the fastest/easiest way is to use string lookups, eg:

    string url = "mydomain.com";
    if (!url.StartsWith("http://", StringComparison.OrdinalIgnoreCase)) url = "http://" + url;
    

    A better approach would be to use Uri to also validate the URL using the TryCreate method:

    string url = "mydomain.com";
    Uri uri;
    if ((Uri.TryCreate(url, UriKind.Absolute, out uri) || Uri.TryCreate("http://" + url, UriKind.Absolute, out uri)) &&
        (uri.Scheme == Uri.UriSchemeHttp || uri.Scheme == Uri.UriSchemeHttps))
    {
        // Use validated URI here
    }
    

    As @JanDavidNarkiewicz pointed out in the comments, validating the Scheme is necessary to guard against invalid schemes when a port is specified without scheme, e.g. mydomain.com:80.

    0 讨论(0)
  • 2020-12-08 09:46

    You could also use UriBuilder:

    public static Uri GetUri(this string s)
    {
        return new UriBuilder(s).Uri;
    }
    

    Remarks from MSDN:

    This constructor initializes a new instance of the UriBuilder class with the Fragment, Host, Path, Port, Query, Scheme, and Uri properties set as specified in uri.

    If uri does not specify a scheme, the scheme defaults to "http:".

    0 讨论(0)
  • 2020-12-08 09:48

    Interestingly, although Uri and UriBuilder completely mangle any url without a scheme, WebProxy does it right.

    So just call:

    new WebProxy(proxy.ProxyServer).Address
    
    0 讨论(0)
  • 2020-12-08 09:52

    My solution was for protocall-less urls to make sure they have protocal was regex :

    Regex.Replace(s, @"^\/\/", "http://");
    
    0 讨论(0)
提交回复
热议问题