代码之家  ›  专栏  ›  技术社区  ›  mpen

如何使uri.host引发UriFormatException?

  •  0
  • mpen  · 技术社区  · 14 年前
    foreach (var node in root.Find("a[href]"))
    {
        var href = node.Attributes["href"].Value;
        Uri uri;
        try
        {
            uri = new Uri(item.Value.Uri, href);
        }
        catch(UriFormatException)
        {
            continue;
        }
        // *snip*
        try
        {
            if (_imageHosts.IsMatch(uri.Host)) // <--- problematic line
                priority--;
        }catch(UriFormatException)
        {
            MessageBox.Show(uri.OriginalString); // <--- gets displayed when I expected it wouldn't
            continue;
        }
        // *snip*
    }
    

    消息框显示的地址如下

    mailto:webmaster[@]什么主机?网站管理员

    这显然是畸形的,但我不明白为什么它没有被 第一 挡块?

    MSDN says 它只能扔一个 InvalidOperationException . 这是相当有问题的,因为这意味着我的应用程序可以在任何时候爆炸!

    [ [剪辑] ]

    3 回复  |  直到 14 年前
        1
  •  8
  •   Nick Martyshchenko    14 年前

    首先,我想说,使用异常检查有效性是不好的,因为您可以使用 Uri.TryCreate 方法。因此,您可以重写代码,而不依赖于哪个异常可以被抛出和捕获。

    所以最好把你的

    Uri uri;
    try
    {
        uri = new Uri(item.Value.Uri, href);
    }
    catch(UriFormatException)
    {
        continue;
    }
    

    Uri uri;
    if (!Uri.TryCreate(item.Value.Uri, href, out uri)) continue;
    

    但这并不是全部支票。

    至于你的问题,答案相对简单。假设格式不正确是错误的:

    mailto:webmaster[@]什么主机?网站管理员

    乌里群岛 Uniform Resource Identifier 所以它 basic syntax

    方案名称:层次部分[?查询[片段]

    显然对您的输入有效。您将以资源的URI和“mailto:”方案结束。

    当您尝试访问主机属性时,您假定资源是HTTP,但默认情况下使用的“mailto”方案分析器无法解析主机组件的原始字符串,因此引发异常。

    因此,要正确编写支票,您必须稍微修改代码:

    Uri uri;
    if (!Uri.TryCreate(item.Value.Uri, href, out uri)) continue;
    
    if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps) continue;
    

    阅读一些关于 UriParser


    此处更新基于@mark注释。

    我很肯定,当我试图获取absoluteuri属性时,它也抛出了一个异常..为什么会失败?

    您不能通过方案检查,因为它将是“mailto”。所以这里是快速测试:

            var baseUri = new Uri("http://localhost");
            const string href = "mailto: webmaster [ @ ] somehost ?webmaster";
    
            Uri uri;
            if (!Uri.TryCreate(baseUri,href, out uri)) 
            {
                Console.WriteLine("Can't create");
                return;
            }
    
            if (uri.Scheme != Uri.UriSchemeHttp && uri.Scheme != Uri.UriSchemeHttps)
            {
                Console.WriteLine("Wrong scheme");
                return;
            }
    
            Console.WriteLine("Testing uri: {0}", uri);
    

    它以“错误的计划”结束。也许我不明白你的意思?

    当您将href更改为:

            const string href = "http: webmaster [ @ ] somehost ?webmaster";
    

    它正确传递,自动将URI转义到:

    http://localhost/%20webmaster%20%5B%20@%20%5D%20somehost%20?webmaster

    此外,所有的URI组件都将对您可用。

    我在第一部分试图解释的主要问题如下:

    在我看来你对任何 统一资源标识符 作为基于HTTP的URL,但这是错误的。 mailto:webmaster@somehost.tst gopher://gopher.hprc.utoronto.ca/ myreshandler://something@somewhere 还可以成功分析的有效URI。看一看 Official IANA-registered schemes

    所以

    应为URI构造函数行为,并且该行为正确。

    它尝试验证传入的URI known schemes :

    • UriSchemeFile - 指定URI是指向文件的指针。
    • UriSchemeFtp - 指定通过文件传输协议(FTP)访问URI。
    • UriSchemeGopher - 指定通过gopher协议访问URI。
    • UriSchemeHttp - 指定通过超文本传输协议(HTTP)访问URI
    • UriSchemeHttps - 指定通过安全超文本传输协议(HTTPS)访问URI。
    • UriSchemeMailto - 指定URI是电子邮件地址,并通过简单网络邮件协议(SNMP)访问。
    • UriSchemeNews - 指定URI是Internet新闻组,并通过网络新闻传输协议(NNTP)访问。
    • UriSchemeNntp - 指定URI是Internet新闻组,并通过网络新闻传输协议(NNTP)访问。

    当方案未知时使用基本的URI解析器(请参见 URI scheme generic syntax )


    基本地 Uri.TryCreate() 例如,方案检查足以获取可以传递到.NET httpwebrequest的链接。你不需要真正检查它们的格式是否正确。如果链接不好(格式不正确或不存在),你只需要在请求时得到相应的httperror。

    例如:

    http://www.google.com/search?q=cheesy POF

    它通过我的检查,变成:

    http://www.google.com/search?q=cheesy%20poof

    您不需要检查它的格式是否正确。只需进行基本检查并尝试请求。希望它有帮助。


    另外,字符串mailto:webmaster[@]somehost?网站管理员格式不正确。我的字面意思是,那根绳子,里面有愚蠢的[]和所有的东西

    这个字符串是 畸形的 意思是不是 成形良好的 (因为包含排除字符 RFC 2396 )但它仍然可以被认为是 有效的 由于URI方案的通用语法是一致的(还要检查它在使用HTTP创建时是如何转义的:)。

        2
  •  1
  •   Matthew Ferreira    14 年前

    如果你深入挖掘 Uri.Host 属性(real deep),它最终可以调用静态函数 GetException 哪些回报 UriFormatException 对象用于无效URI的不同条件。打印出完整的 UriFormat异常 您正在获取并将其与 Uri.GetException . 你可能会从中得到更多的细节。

        3
  •  1
  •   mpen    14 年前

    根据尼克的回答:

    private static readonly string[] SupportedSchmes = { Uri.UriSchemeHttp, Uri.UriSchemeHttps, Uri.UriSchemeFtp, Uri.UriSchemeFile };
    
    private static bool TryCreateUri(string uriString, out Uri result)
    {
        return Uri.TryCreate(uriString, UriKind.Absolute, out result) && SupportedSchmes.Contains(result.Scheme);
    }
    
    private static bool TryCreateUri(Uri baseAddress, string relativeAddress, out Uri result)
    {
        return Uri.TryCreate(baseAddress, relativeAddress, out result) && SupportedSchmes.Contains(result.Scheme);
    }