Используя Java, я хочу удалить идентификатор фрагмента и выполнить простую нормализацию (например, схемы в нижнем регистре, хосты) разнообразного набора URI. URI ввода и вывода должны быть эквивалентны в общем смысле HTTP.
Как правило, это должно быть просто. Однако для таких URI, как http://blah.org/A_%28Secret%29.xml#blah
, процент которых кодирует (Secret)
, поведение 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, которая не содержит никаких других символов.
Таким образом, я не могу использовать конструктор с несколькими аргументами, если внутренняя кодировка класса URI
не запутана в кодировке URL. Тьфу!