Ответ 1
Правильно ли предположить, что все, что не является безоговорочным, может/должно быть закодировано в процентах?
Нет. RFC 3986 говорит следующее:
"При нормальных обстоятельствах единственный раз, когда октеты внутри URI кодируются в процентах, происходит во время создания URI из его составных частей. Это когда реализация определяет, какой из зарезервированных символов должен использоваться в качестве подкомпонента разделители и которые можно безопасно использовать в качестве данных".
Подразумевается, что вы решаете, какой из разделителей (т.е. символов <delimiter>
) необходимо закодировать в зависимости от контекста. Те, которые не требуют кодирования, не должны кодироваться.
Например, вы не должны процитировать /
в процентах, если он появляется в компоненте пути, но вы должны преобразовать его в процентах, когда он появляется в запросе или фрагменте.
Итак, на самом деле символ ;
(который является членом <reserved>
) не должен автоматически кодироваться процентом. И действительно, классы java URL и URI не будут этого делать, см. URI (...) javadoc, в частности шаг 7), как обрабатывается компонент <path>
.
Это подкрепляется этим параграфом:
"Цель зарезервированных символов - предоставить набор разделительных символов, которые можно отличить от других данных в URI. URI, которые отличаются заменой зарезервированного символа соответствующим октетом с процентным кодированием, не эквивалентны. кодирование зарезервированного символа или декодирование октета с процентным кодированием, который соответствует зарезервированному символу, изменяет способ интерпретации URI большинством приложений. Таким образом, символы в зарезервированном наборе защищены от нормализации и поэтому безопасны для использования по схеме специфические и специфичные для производителя алгоритмы для разделения подкомпонентов данных в URI."
Таким образом, это говорит о том, что URL-адрес, содержащий процентный код ;
, не совпадает с URL-адресом, который содержит raw ;
. И последнее предложение подразумевает, что они НЕ должны быть закодированы или декодированы автоматически.
Что оставляет нас с вопросом - почему вы хотите, чтобы ;
был закодирован в процентах?
Скажем, у вас есть CMS, где люди могут создавать произвольные страницы с произвольными путями. Позже мне нужно генерировать ссылки href на все страницы, например, в компоненте карты сайта. Поэтому мне нужен алгоритм, чтобы узнать, какие символы нужно убежать. Точка с запятой должна обрабатываться буквально в этом случае и должна бежать.
Извините, но не следует, что точка с запятой должна быть экранирована.
Что касается спецификации URL/URI, то ;
не имеет особого значения. Это может иметь особый смысл для конкретного веб-сервера/веб-сайта, но в целом (т.е. Без специального знания сайта) вы не можете этого знать.
-
Если
;
имеет особый смысл в определенном URI, то, если вы процентов-убегаете, то вы нарушаете это значение. Например, если сайт использует;
, чтобы добавить токен сеанса к пути, тогда процентное кодирование остановит его от распознавания токена сеанса... -
Если
;
- это просто символ данных, предоставляемый некоторым клиентом, то, если вы его кодируете, вы потенциально меняете значение URI. Неважно, зависит ли это от того, что делает сервер; то есть, является ли декодирование или нет частью логики приложения.
Это означает, что знание "правильной вещи" требует глубокого знания того, что означает URI для конечного пользователя и/или сайта. Это потребует применения усовершенствованной технологии чтения разума. Моя рекомендация заключалась в том, чтобы заставить CMS решить эту проблему, соответствующим образом преодолевая любые разделители, пути URI до, которые он поставляет в ваше программное обеспечение. Алгоритм обязательно будет специфичным для платформы CMS и доставки контента. Он/они будут отвечать на запросы на документы, идентифицированные по URL-адресам, и им нужно будет знать, как их интерпретировать.
(Поддержка произвольных людей, использующих произвольные пути, немного сумасшедшая. Должны быть некоторые ограничения. Например, даже Windows не позволяет использовать символ разделителя файлов в компоненте имени файла. Таким образом, вам придется иметь некоторые границы где-то. Это просто вопрос, где они должны быть.)