./未在URL中正确考虑

时间:2013-04-13 21:52:28

标签: java url normalization

我想解决一些网址。为此,我得到了结果:

  new URL(new URL(baseurl), link);

baseurl="http://www.site.com"link="./"

时,此方法似乎失败了

您将获得以下结果http://www.site.com/./,而不只是http://www.site.com/

我该如何解决这个问题?

4 个答案:

答案 0 :(得分:1)

也许这会有用吗?

new URI(baseUrl).resolve(link).toURL()

java.net.URI有一个解决方法,可能就是你要找的东西,而toURL则可以将它放到一个URL中。

修改

以下似乎对我有用..

import java.net.URL;


public class UrlTest {

    private static URL resolve(URL base, String link) throws Exception {
        if (base.getPath().isEmpty()) {
            link = "/" + link;
        }       
        URL u1 = base.toURI().resolve(link).normalize().toURL();
        return u1;
    }

    private static void resolveUrls(URL baseUrl) throws Exception {
        String link = "abcd";
        String link2 = "./";
        String link3 = "./foo";
        System.out.println(resolve(baseUrl, link));
        System.out.println(resolve(baseUrl, link2));
        System.out.println(resolve(baseUrl, link3));
    }

    public static void main(String[] args) throws Exception {   
        String baseUrlStr = "http://www.somesite.com";
        URL baseUrl = new URL(baseUrlStr);
        resolveUrls(baseUrl);
        baseUrl = new URL(baseUrlStr + "/index.html");
        resolveUrls(baseUrl);
        baseUrl = new URL(baseUrlStr + "/path/index.html");
        resolveUrls(baseUrl);
    }

}

答案 1 :(得分:1)

你可以试试这个

new URL(new URL(baseurl), link.replace("./"), "");

答案 2 :(得分:1)

使用URI.normalize()

import java.net.*;

class TestURL {

    public static void main(String[] args) throws Exception {
        String s = "http://www.site.com/./";
        URL url = new URL(s);
        System.out.println(url);
        URI uri = url.toURI();
        System.out.println(uri.normalize().toURL());
    }
}

输出

http://www.site.com/./
http://www.site.com/

答案 3 :(得分:1)

这是一个非常长的,虽然信息丰富,但在很大程度上无益的帖子,但最后确实有一个答案。

这是一个悲伤的故事。这显然很疯狂:

URI base = new URI("http", "example.org", null, null);
URI link = new URI(null, null, "index.html", null);
System.out.println(base.resolve(link));

应打印:

http://example.orgindex.html

而不是:

http://example.org/index.html

然而确实如此。为什么?因为java.net.URI ...

  

表示由RFC 2396定义的URI引用:统一资源标识符(URI):通用语法

忠诚地这样做。特别是resolve方法......

  

以符合RFC 2396 section 5.2

的方式构造新的分层URI

可悲的是,5.2节中指定的算法是错误的。具体来说,尽管它说......

  

路径组件永远不会被定义,尽管它可能是空的

它不能确保针对具有空路径的基URI解析相对URI的结果是有效的URI。问题在于步骤6,该步骤涉及将来自基础和相对URI的路径合并到将用于形成已解析URI的缓冲区中。第6步的前两个子步骤是:

  

a)基URI的路径组件的最后一段除了复制到缓冲区外。换句话说,排除最后一个(最右边)斜杠字符后的任何字符(如果有)。

     

b)引用的路径组件被附加到缓冲区字符串。

如果基URI具有空路径,则在子步骤a之后,缓冲区将为空。如果相对URI的路径不以/开头,那么在子步骤b之后,缓冲区将包含一个不以/开头的字符串。以下步骤处理点标准化,并且无需添加前导/。最后一步是:

  

h)剩余的缓冲区字符串是引用URI的新路径组件。

因此,已解析的URI有一个不以/开头的路径。然后,步骤7将其构建为已解析URI的最终字符串形式,而无需插入/的任何规定。因此,在没有前导/反对具有空路径的基URI的情况下解析相对URI会导致无意义。这是RFC 2396指定的内容,以及java.net.URI的内容。

糟糕!

这个故事并没有完全结束。 2005年1月,RFC 3986发布。这已废弃的RFC 2396,并在section 5.2中包含URI解析的新定义。这个定义完全以更严格(或至少看起来很严谨)的方式重写,并指定section 5.2.3中路径的合并,这是从正确的方向开始的:

  

如果基URI具有已定义的权限组件和空路径,则返回由与引用的路径连接的“/”组成的字符串

因此,如果更新Java以符合一个已有八年历史的RFC而不是一个十四岁的RFC,那么整个问题就会得到解决。这样做是bug 6791060所要求的,它于2009年开放,最后一次触及2010年。太阳,我很失望。

无论如何,有了这种理解,我们可以看到正确的解决方案是这样的:

public static URI fix(URI uri) {
    if (uri.getPath().isEmpty()) {
        try {
            return new URI(uri.getScheme(), uri.getAuthority(), "/", uri.getQuery(), uri.getFragment());
        }
        catch (URISyntaxException e) {
            AssertionError ae = new AssertionError("highly implausible error fixing URI " + uri);
            ae.initCause(e);
            throw ae;
        }
    }
    else {
        return uri;
    }
}

fix(new URI(baseurl)).resolve(link);