[英]URI - getHost returns null. Why?
為什么第一個返回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 + "].");
}
正如@hsz的評論中提到的那樣,它已知錯誤 。
但是,讓我們調試並查看URI
類的內部源代碼。 問題出在方法內:
private int parseHostname(int start, int n)
:
if ((p < n) && !at(p, n, ':')) fail("Illegal character in hostname", p);
解析第一個URI在行if ((p < n) && !at(p, n, ':')) fail("Illegal character in hostname", p);
這是因為在掃描塊內沒有預見_
符號,它只允許使用alphas,digits和-
symbol( L_ALPHANUM
, H_ALPHANUM
, L_DASH
和H_DASH
)。
是的,這在Java 7
尚未修復。
這是因為基礎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 + "].");
}
我不認為這是Java中的錯誤,我認為Java正在根據規范正確解析主機名,這里有很好的解釋規范: http : //en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names ,這里: http://www.netregister.biz/faqit.htm#1
特別是主機名不得包含下划線。
如前所述,這是一個已知的JVM錯誤。 雖然,如果要對此類主機執行HTTP請求,您仍可以嘗試使用變通方法。 主要思想是構建基於IP的請求,而不是基於“錯誤”的主機名。 但在這種情況下,您還需要使用正確的(原始)主機名向請求添加“主機”標頭。
1:從URL中剪切主機名(這是一個粗略的例子,你可以使用更聰明的方式):
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:現在您應該使用正確的(原始)主機名添加“Host”標頭:
req.addHeader("Host", hostHeader);
6:現在你可以做請求(偽代碼):
String resp = req.getResponse().asString();
考慮使用: new java.net.URL("http://broken_arrow.huntingtonhelps.com").getHost()
代替。 它具有替代解析實現。 如果你有一個URI myUri
實例,那么調用myUri.toURL().getHost()
。
我在OpenJDK 1.8中遇到了這個URI
問題,它在URL
運行良好。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.