URL/URI Java неправильно разрешает ссылки, начинающиеся с? (точка допроса)

Я пытаюсь определить относительную ссылку, которая начинается со знака вопроса ? используя Java URL или же URI классы.

Пример HTML:

<a href="?test=xyz">Test XYZ</a>

Примеры кода (из Scala REPL):

import java.net._

scala> new URL(new URL("http://abc.com.br/index.php?hello=world"), "?test=xyz").toExternalForm()
res30: String = http://abc.com.br/?test=xyz

scala> (new URI("http://abc.com.br/index.php?hello=world")).resolve("?test=xyz").toString
res31: java.net.URI = http://abc.com.br/?test=xyz

Проблема в том, что браузеры (протестированные в Chrome, Firefox и Safari) вместо этого выводят следующий URL: http://abc.com.br/index.php?hello=world, Это не отбрасывает путь "index.php". Он просто заменяет часть строки запроса.

И похоже, что браузеры просто следуют спецификации, как описано в /questions/20124848/dejstvitelno-li-ssyilka-href-tolko-s-parametrami-nachinaya-s-voprositelnogo-znaka/20124862#20124862.

Библиотека Jsoup допускает ту же "ошибку", когда мы используем element.absUrl("href") как это также зависит от Java URL разрешения.

Так что случилось с Java URL/URI разрешать относительные пути? Это неправильно / не полностью? Как заставить его вести себя так же, как реализация браузера?

1 ответ

Решение

Это будет работать просто отлично:

public static void main(String[] args) throws Exception {
    String base = "http://abc.com.br/index.php?hello=world";
    String relative = "?test=xyz";

    System.out.println(new URL(new URL(base), relative).toExternalForm());
    // http://abc.com.br/?test=xyz

    System.out.println((new URI(base)).resolve(relative).toString());
    // http://abc.com.br/?test=xyz

    System.out.println(org.apache.http.client.utils.URIUtils.resolve(new URI(base), relative).toString());
    // http://abc.com.br/index.php?test=xyz
}

URIUtils находятся в org.apache.httpcomponents:httpclient версии 4.0 или выше.

Другие вопросы по тегам