URI - getHost возвращает null. Зачем?
Почему первый возвращает 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 + "].");
}
Ответы
Ответ 1
Как уже упоминалось в комментариях @hsz, это известная ошибка.
Но, давайте отладим и заглянем внутрь источников класса 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
, L_DASH
и H_DASH
).
И да, это еще не исправлено в Java 7
.
Ответ 2
Это из-за подчеркивания в базовом 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 + "].");
}
Ответ 3
Я не думаю, что это ошибка в Java, я думаю, что Java правильно обрабатывает имена хостов в соответствии со спецификацией, есть хорошие объяснения спецификации здесь: http://en.wikipedia.org/wiki/Hostname#Restrictions_on_valid_host_names и здесь: http://www.netregister.biz/faqit.htm#1
В частности, имена хостов НЕ ДОЛЖНЫ содержать символы подчеркивания.
Ответ 4
Как уже упоминалось, это известная ошибка JVM.
Хотя, если вы хотите выполнить HTTP-запрос на такой хост, вы все равно можете попытаться использовать обходной путь.
Основная идея состоит в том, чтобы построить запрос, основанный на IP, а не на "неправильном" имени хоста. Но в этом случае вам также нужно добавить заголовок "Host" в запрос с правильным (оригинальным) именем хоста.
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: Создайте новый URL-адрес на основе IP:
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();
Ответ 5
Попробуйте использовать: new java.net.URL("http://broken_arrow.huntingtonhelps.com").getHost()
. Имеет альтернативную реализацию парсинга. Если у вас есть экземпляр URI myUri
, вызовите myUri.toURL().getHost()
.
Я столкнулся с этой проблемой URI
в OpenJDK 1.8, и он отлично работал с URL
.