URI - getHost返回null。为什么?

时间:2014-09-23 10:51:47

标签: java

为什么第一个返回null,而第二个返回mail.yahoo.com

这不奇怪吗?如果没有,这种行为背后的逻辑是什么?

下划线是罪魁祸首吗?为什么?

public static void main(String[] args) throws Exception {
    java.net.URI uri = new java.net.URI("http://broken_arrow.huntingtonhelps.com");
    String host = uri.getHost();
    System.out.println("Host = [" + host + "].");

    uri = new java.net.URI("http://mail.yahoo.com");
    host = uri.getHost();
    System.out.println("Host = [" + host + "].");
}

5 个答案:

答案 0 :(得分:9)

正如@hsz的评论所提到的那样,它是bug

但是,让我们调试并查看URI类的源代码。问题出在方法内:

private int parseHostname(int start, int n)

解析第一个URI在第if ((p < n) && !at(p, n, ':')) fail("Illegal character in hostname", p);

失败

这是因为_符号未在扫描块内预见,它只允许使用字母,数字和-符号(L_ALPHANUMH_ALPHANUM,{{1} }和L_DASH)。

是的,这在H_DASH中尚未解决。

答案 1 :(得分:3)

这是因为基础uri的下划线。 只需删除下划线即可查看它。它正在工作。

如下所示:

public static void main(String[] args) throws Exception {
java.net.URI uri = new java.net.URI("http://brokenarrow.huntingtonhelps.com");
String host = uri.getHost();
System.out.println("Host = [" + host + "].");

uri = new java.net.URI("http://mail.yahoo.com");
host = uri.getHost();
System.out.println("Host = [" + host + "].");

}

答案 2 :(得分:1)

我不认为它是Java中的一个错误,我认为Java正在根据规范正确解析主机名,这里对规范有很好的解释:http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names和这里:{{ 3}}

特别是主机名不得包含下划线。

答案 3 :(得分:1)

如前所述,这是一个已知的JVM错误。 虽然,如果要对此类主机执行HTTP请求,您仍可以尝试使用变通方法。 主要思想是建立基于IP的请求,而不是基于错误的&#39;主机名。但在这种情况下你还需要添加&#34; Host&#34;请求的标头,带有正确的(原始)主机名。

1:从网址剪切主机名(这是一个粗略的例子,你可以使用更聪明的方式):

int n = url.indexOf("://");  
if (n > 0) { n += 3; } else { n = 0; }  
int m = url.indexOf(":", n);
int k = url.indexOf("/", n);  
if (-1 == m) { m = k; }  
String hostHeader;  
if (k > -1) {  
  hostHeader = url.substring(n, k);  
} else {  
  hostHeader = url.substring(n);  
}
String hostname;  
if (m > -1) {  
  hostname = url.substring(n, m);  
} else {  
  hostname = url.substring(n);  
}  

2:获取主机名的IP:

String IP = InetAddress.getByName(hostname).getHostAddress();

3:根据IP构建新的URL:

String newURL = url.substring(0, n) + IP + url.substring(m);

4:现在使用HTTP库为新URL(伪代码)准备请求:

HttpRequest req = ApacheHTTP.get(newUrl);

5:现在你应该添加&#34; Host&#34;带有正确(原始)主机名的标头:

req.addHeader("Host", hostHeader);

6:现在你可以做请求(伪代码):

String resp = req.getResponse().asString();

答案 4 :(得分:0)

考虑使用:new java.net.URL("http://broken_arrow.huntingtonhelps.com").getHost()代替。它具有替代解析实现。如果您有URI myUri实例,请致电myUri.toURL().getHost()

我在OpenJDK 1.8中遇到了这个URI问题,它在URL上正常工作。