Нормализация возможно закодированных строк URI в Java

Используя Java, я хочу удалить идентификатор фрагмента и выполнить простую нормализацию (например, строчные схемы, хосты) разнообразного набора URI. Входные и выходные URI должны быть эквивалентными в общем смысле HTTP.

Как правило, это должно быть просто. Однако для таких URI, как http://blah.org/A_%28Secret%29.xml#blah , процент которых кодирует (Секрет) , поведение java. util.URI усложняет жизнь.

Метод нормализации должен вернуть http://blah.org/A_%28Secret%29.xml , поскольку URI http://blah.org/A_%28Secret%29.xml и http://blah.org/A_ (Secret) .xml не эквивалентны в интерпретации [§2.2; RFC3968 ]

Итак, у нас есть два следующих метода нормализации:

URI u = new URI("http://blah.org/A_%28Secret%29.xml#blah");
System.out.println(u);
        // prints "http://blah.org/A_%28Secret%29.xml#blah"

String path1 = u.getPath();      //gives "A_(Secret).xml"
String path2 = u.getRawPath();   //gives "A_%28Secret%29.xml"


//NORMALISE METHOD 1
URI norm1 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(), 
                      u.getHost().toLowerCase(), u.getPort(), path1, 
                      u.getQuery(), null);
System.out.println(norm1);
// prints "http://blah.org/A_(Secret).xml"

//NORMALISE METHOD 2
URI norm2 = new URI(u.getScheme().toLowerCase(), u.getUserInfo(),
                      u.getHost().toLowerCase(), u.getPort(), path2, 
                      u.getQuery(), null);
System.out.println(norm2);
// prints "http://blah.org/A_%2528Secret%2529.xml"

Как мы видим, URI анализируется и перестраивается без идентификатора фрагмента.

Однако для метода 1 u.getPath () возвращает незакодированный URI, который изменяет окончательный URI.

Для метода 2 u.getRawPath () возвращает исходный путь, но при передаче в конструктор URI Java решает добавить двойное кодирование.

Это похоже на китайскую ловушку для пальцев.

Итак, два основных вопроса:

  • Почему java.util.URI чувствует необходимость играть с кодировкой?
  • Как можно реализовать этот метод нормализации без возни с исходным процентным кодированием?

(Я бы предпочел не реализовывать нетривиальные методы синтаксического анализа / конкатенации java.util.URI .)


РЕДАКТИРОВАТЬ: Вот дополнительная информация из URI javadoc .

  • Конструктор с одним аргументом требует, чтобы любые недопустимые символы в его аргументе были заключены в кавычки, а сохраняет все экранированные октеты и другие присутствующие символы.

  • конструкторы с несколькими аргументами цитируют недопустимые символы в соответствии с требованиями компонентов, в которых они появляются. Эти конструкторы всегда цитируют символ процента ('%'). Все остальные символы сохраняются.

  • Методы getRawUserInfo, getRawPath , getRawQuery, getRawFragment, getRawAuthority и getRawSchemeSpecificPart возвращают значения своих соответствующих компонентов в необработанном виде, без интерпретации каких-либо экранированных октетов . Строки, возвращаемые этими методами, могут содержать как экранированные октеты, так и другие символы, и не будут содержать никаких недопустимых символов.

  • Методы getUserInfo, getPath , getQuery, getFragment, getAuthority и getSchemeSpecificPart декодируют любые экранированные октеты в их соответствующих компонентах. Строки, возвращаемые этими методами, могут содержать как другие символы, так и недопустимые символы, и не будут содержать никаких экранированных октетов.

  • Метод toString возвращает строку URI со всеми необходимыми кавычками, но может содержать другие символы.

  • Метод toASCIIString возвращает полностью закодированную строку URI в кавычках, не содержащую других символов.

Таким образом, я не могу использовать конструктор с несколькими аргументами, если кодировка URL-адреса не изменится внутри класса URI . Тьфу!

7
задан Steve Kuo 23 February 2012 в 21:11
поделиться