为什么第一个返回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 + "].");
}
答案 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_ALPHANUM
,H_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
上正常工作。