Правильный способ проверить равенство URL - PullRequest
19 голосов
/ 22 сентября 2010

У меня есть следующий сценарий:

URL u1 = new URL("http://www.yahoo.com/");
URL u2 = new URL("http://www.yahoo.com");

if (u1.equals(u2)) {
    System.out.println("yes");
}
if (u1.toURI().equals(u2.toURI())) {
    System.out.println("uri equality");
}
if (u1.toExternalForm().equals(u2.toExternalForm())) {
    System.out.println("external form equality");
}
if (u1.toURI().normalize().equals(u2.toURI().normalize())) {
    System.out.println("uri normalized equality");
}

Ни одна из этих проверок не выполнена. Отличается только путь: u1 имеет путь "/", а u2 имеет путь "". Эти URL-адреса указывают на один и тот же ресурс, и есть ли способ проверить такую ​​вещь, не открывая соединение? Я неправильно понимаю что-то фундаментальное в URL?

РЕДАКТИРОВАТЬ Я должен сказать, что желательна не хакерская проверка. Разумно ли говорить, что пустой путь == /? Я надеялся не иметь такой код

Ответы [ 3 ]

26 голосов
/ 22 сентября 2010

с 2007 года JavaOne:

Вторая головоломка, под названием «Больше радостей наборов», позволяет пользователю создавать ключи HashMap, состоящие из нескольких объектов URL. Опять же, большинство зрителей не смогли угадать правильный ответ.

Важная вещь, которую слушатели узнали здесь, это то, что метод equals () объекта URL, по сути, не работает . В этом случае два объекта URL равны, если они разрешают один и тот же IP-адрес и порт, а не только если они имеют одинаковые строки. Однако Блох и Пью указывают на еще более серьезную ахиллесову пяту: поведение равенства различается в зависимости от того, подключены ли вы к сети, где виртуальные адреса могут разрешаться на одном и том же хосте, или если вы не в сети, где разрешение является операцией блокировки. Итак, что касается извлеченных уроков, они рекомендуют:

Не использовать URL; используйте URI вместо . URI не пытается сравнивать адреса или порты. Кроме того, не используйте URL как элемент Set или ключ карты.
Для разработчиков API метод equals () не должен зависеть от среды. Например, в этом случае равенство не должно меняться, если компьютер подключен к Интернету, а не автономно.


Из URI равно документации:

Чтобы два иерархических URI считались равными, их пути должны быть равны , а их запросы должны быть либо неопределенными, либо равными.

В вашем случае два пути различны. один "/" другой "".


Согласно URI RFC §6.2.3:

Реализации может использовать правила схемы, при дальнейшей обработке стоимость, чтобы уменьшить вероятность ложных негативов. Например, потому что схема "http" использует компонент полномочий, имеет порт по умолчанию "80", и определяет пустой путь, чтобы быть эквивалентным «/», следующие четыре URI эквивалентны:

 http://example.com
 http://example.com/
 http://example.com:/
 http://example.com:80/

Похоже, что эта реализация не использует правила, специфичные для схемы.


Ресурсы:

2 голосов
/ 22 сентября 2010

Строго говоря, они не равны. необязательный конечный слеш (/) является обычным, но не обязательным. Вы можете отобразить разные страницы для

http://www.yahoo.com/foo/

и для

http://www.yahoo.com/foo

Это даже возможно для того, что вы указали, я думаю, что заголовок HTTP может пропустить этот слеш.

0 голосов
/ 27 августа 2015

Вы всегда можете сравнить относительные URL-адреса с помощью метода Path.equals

ех.

Paths.get("/user/login").equals(Paths.get("/user/login/")))

производить верно

Вы также можете использовать методы beginWith / EndWithWith

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...