如果需要,将方案添加到 URL

发布于 2024-10-21 09:20:33 字数 383 浏览 1 评论 0原文

要从字符串创建 Uri,您可以这样做:

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

但问题是,如果字符串(如上面的字符串)不包含协议,您将收到异常:“Invalid URI: The format of the URI might尚未确定。

为了避免出现异常,您应该确保字符串包含一个协议,如下所示:

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

但是如果您将 url 作为输入,如果协议丢失,如何添加协议?
我的意思是除了一些 IndexOf/Substring 操作之外?

优雅而快速的东西?

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) doesn't contain the protocol you will get an exception: "Invalid URI: The format of the URI could not be determined."

To avoid the exception you should secure the string includes a protocol, like below:

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

But if you take the url as input, how can you add the protocol if it's missing?

I mean apart from some IndexOf/Substring manipulation?

Something elegant and fast?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

未央 2024-10-28 09:20:33

您还可以使用 UriBuilder< /code>

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

来自 MSDN 的评论:

此构造函数使用 uri 中指定的 Fragment、Host、Path、Port、Query、Scheme 和 Uri 属性集初始化 UriBuilder 类的新实例。

如果 uri 未指定方案,则方案默认为“http:”。

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:".

血之狂魔 2024-10-28 09:20:33

如果您只想添加方案,而不验证 URL,最快/最简单的方法是使用字符串查找,例如:

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

更好的方法是使用 Uri 还使用 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

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.

眸中客 2024-10-28 09:20:33

我的解决方案是针对无协议调用的网址,以确保它们的协议是正则表达式:

Regex.Replace(s, @"^\/\/", "http://");

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

Regex.Replace(s, @"^\/\/", "http://");
只为一人 2024-10-28 09:20:33

有趣的是,虽然 UriUriBuilder 在没有方案的情况下完全破坏了任何 url,但 WebProxy 却做得对。

所以只需调用:

new WebProxy(proxy.ProxyServer).Address

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

So just call:

new WebProxy(proxy.ProxyServer).Address
倾`听者〃 2024-10-28 09:20:33

接受的答案结果是 http 而不是 https。我找到了这个答案并以此为基础,

namespace UrlHelper
{
    using System;

    public class UrlExtensions
    {
        public static Uri AddHttpsPrefixToString(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return null;
            }

            Uri uri;
            try
            {
                uri = new UriBuilder(url) {
                    Scheme = Uri.UriSchemeHttps,
                    Port = -1 // default port for scheme
                }.Uri;
            }
            catch
            {
                Console.WriteLine($"UrlExtensions.AddHttpsPrefixToString: Could not parse {url}");
                return null;
            }

            return uri;
        }
    }
}

像这样使用它:

var termsStringOrNull = UrlExtensions.AddHttpsPrefixToString("example.com")?.ToString()

The accepted answer results in http and not https. I've found this answer and built up on it

namespace UrlHelper
{
    using System;

    public class UrlExtensions
    {
        public static Uri AddHttpsPrefixToString(string url)
        {
            if (string.IsNullOrWhiteSpace(url))
            {
                return null;
            }

            Uri uri;
            try
            {
                uri = new UriBuilder(url) {
                    Scheme = Uri.UriSchemeHttps,
                    Port = -1 // default port for scheme
                }.Uri;
            }
            catch
            {
                Console.WriteLine(
quot;UrlExtensions.AddHttpsPrefixToString: Could not parse {url}");
                return null;
            }

            return uri;
        }
    }
}

Use it like this:

var termsStringOrNull = UrlExtensions.AddHttpsPrefixToString("example.com")?.ToString()
她比我温柔 2024-10-28 09:20:33

我们有一些特定的情况,其中有遗留津贴来输入诸如以下内容:
本地主机: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);
        }

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);
        }
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文