Добавить схему в URL, если это необходимо - PullRequest
61 голосов
/ 13 марта 2011

Чтобы создать Uri из строки, вы можете сделать это:

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

Но проблема в том, что если строка (как в приведенной выше) не содержит протокол, вы получите исключение: "Invalid URI: The format of the URI could not be determined."

Чтобы избежать исключения, вы должны защитить строку, включающую протокол, как показано ниже:

Uri u = new Uri("http://example.com");

Но если вы берете URL-адрес в качестве ввода, как вы можете добавить протокол, если он отсутствует?
Я имею в виду, кроме какой-то манипуляции IndexOf / Substring?

Что-нибудь элегантное и быстрое?

Ответы [ 4 ]

125 голосов
/ 13 марта 2011

Вы также можете использовать UriBuilder:

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

Замечания от MSDN:

Этот конструктор инициализирует новый экземпляр класса UriBuilder со свойствами Fragment, Host, Path, Port, Query, Scheme и Uri, установленными, как указано в uri.

Если uri не указывает схему, по умолчанию используется значение http:

7 голосов
/ 28 ноября 2014

Если вы просто хотите добавить схему без проверки URL-адреса, самый быстрый / простой способ - использовать поиск строк, например:

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

Лучшим подходом будет использование Uri, чтобы также проверить URL, используя метод TryCreate:

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
}

Как указал @JanDavidNarkiewicz в комментариях, проверка Scheme необходима для защитыпротив недопустимых схем, когда порт указан без схемы, например mydomain.com:80.

3 голосов
/ 07 февраля 2013

Мое решение было для URL без протоколов, чтобы убедиться, что у них есть протокол с регулярным выражением:

Regex.Replace(s, @"^\/\/", "http://");
0 голосов
/ 20 февраля 2019

У нас были некоторые конкретные случаи, когда существовало допущение для ввода таких вещей, как: localhost: 8800 или аналогичный. Что означает, что нам нужно было разобрать это. Мы создали немного более сложный метод ParseUri, который разделял возможность очень легко указывать URI, но также учитывал время, когда люди указывали нестандартную схему (а также хост в нотации IP-длины, потому что иногда люди так делают)

Так же, как и UriBuilder, по умолчанию будет использоваться схема http, если ни одна из них не указана. Это будет иметь проблемы, если указана базовая аутентификация и пароль состоит только из цифр. (Не стесняйтесь исправлять это сообщество)

        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);
        }
...