带下划线的 C# Uri

C# Uri with underscore

谁能解释为什么我在 C# (.NET Framework 4.8) 中得到下一个结果:

更新: 更多案例:

URI 提供了一种简单且可扩展的方式来标识资源,它只不过是一个标识符,因此它可以允许 URLs 不允许的某些字符,因为它们可以是名称,地点,或两者兼而有之。

URLS 是 URI 的一个子集,它们受限于它们可能包含的字符以及这些字符的组织方式。有关更多信息,我们可以参考 RFC。

A URI can be further classified as a locator, a name, or both. The term “Uniform Resource Locator” (URL) refers to the subset of URIs that, in addition to identifying a resource, provide a means of locating the resource by describing its primary access mechanism (e.g., its network “location”).

本质上,所有 URL 都是 URI,但并非所有 URI 都是 URL。 URLs 不仅会告诉您某物是什么,还会告诉您如何到达它。有一篇 good article on the difference of URIs and URLs 由 Daniel Miessler 撰写。

因此,您遇到的行为是准确的,因为它不知道您正在尝试创建一个合法的事实 URL,但不管您是否正在创建一个准确的 URI。

为了检测它是否有效 URL 使用下面来自 this question 的方法。

public static bool ValidHttpURL(string s, out Uri resultURI)
{
    if (!Regex.IsMatch(s, @"^https?:\/\/", RegexOptions.IgnoreCase))
        s = "http://" + s;

    if (Uri.TryCreate(s, UriKind.Absolute, out resultURI))
        return (resultURI.Scheme == Uri.UriSchemeHttp || 
                resultURI.Scheme == Uri.UriSchemeHttps);

    return false;
}

用法:

string[] inputs = new[] {
                          "https://www.google.com",
                          "http://www.google.com",
                          "www.google.com",
                          "google.com",
                          "javascript:alert('Hack me!')"
                        };
foreach (string s in inputs)
{
    Uri uriResult;
    bool result = ValidHttpURL(s, out uriResult);
    Console.WriteLine(result + "\t" + uriResult?.AbsoluteUri);
}

输出:

True    https://www.google.com/
True    http://www.google.com/
True    http://www.google.com/
True    http://google.com/
False

为什么 URL 中带有下划线的 return 与 Uri.TryCreate 不同?

使用 Uri.TryCreate 时,包含下划线的

Urls/Uris 总是 return false。这是由于 modification of the standard

This change required all rule names that formerly included underscore characters to be renamed with a dash instead.

使用 UriKind.RelativeOrAbsolute,系统会尝试检测传递给它的 URI 字符串的类型是 Ralative 还是 Absolute。如果 Uristring 以“http://”开头,那么系统会将其检测为绝对 Uri,而“http://_g._google._com”不是有效的 Uri,因此您会出错。所以对于每个选项,它是:

第一种情况:Uri.TryCreate("_g._google._com", UriKind.RelativeOrAbsolute, out _),在这个系统中将其作为相对 Url 并且它是一个有效的相对 Uri,因此你得到 true。

第二种情况:Uri.TryCreate("http://_g._google._com", UriKind.RelativeOrAbsolute, out _),在这种情况下,它以“http://”开头,因此它是绝对 Uri,但不是有效 Uri,因此你得到 false。

第三种情况:Uri.TryCreate("http://_g._google.com", UriKind.RelativeOrAbsolute, out _),与情况 2 相同,但在这种情况下它是一个有效的 Uri,因为它在 .com 之前缺少 _。这样你就得到了一个 true.