Для чего нужно процентное кодирование
URL — это маленькая, строгая грамматика. У горстки символов есть структурное значение: / разделяет сегменты пути, ? начинает запрос, & разделяет параметры, # отмечает фрагмент, : и @ играют роли в полномочии. Что же происходит, когда один из этих символов должен появиться как обычные данные, например поисковый запрос, буквально содержащий &, или сегмент пути с пробелом? Вы не можете поместить его сырым, потому что парсер URL прочитал бы его как структуру и сломался бы. Процентное кодирование, определённое в RFC 3986 и часто называемое URL-кодированием, — это механизм экранирования, который это решает: он переписывает небезопасный символ как %, за которым следуют две шестнадцатеричные цифры его байтового значения.
Пробел становится %20, косая черта становится %2F, амперсанд становится %26. Текст a b/c кодируется как a%20b%2Fc. Декодировщик обращает это: каждый %XX снова становится байтом XX, и исходный символ возвращается.
Незарезервированный набор: то, что остаётся неизменным
Процентное кодирование не трогает всё. RFC 3986 определяет небольшой незарезервированный набор символов, которые всегда безопасно оставить буквально в URL и которые никогда не должны экранироваться:
- буквы
A-Zиa-z - цифры
0-9 - четыре знака
-,.,_и~
Всё остальное, включая зарезервированные структурные символы и всё за пределами ASCII, кодируется процентами, когда появляется как данные. Байты выше 127 обрабатываются путём сначала кодирования текста как UTF-8, а затем процентного кодирования каждого результирующего байта, поэтому одна буква с диакритическим знаком или эмодзи превращается в серию из нескольких пар %XX, по одной на байт UTF-8.
Почему %XX — это две шестнадцатеричные цифры
% — это маркер экранирования; два символа после него — это байт в шестнадцатеричном виде, в точности шестнадцатеричное кодирование байта. Это и есть вся причина, по которой корректное экранирование — это всегда % плюс две шестнадцатеричные цифры и ничего больше. %, за которым следует что-то иное, чем две шестнадцатеричные цифры, как %2G, или одинокий % в конце строки, повреждён, и аккуратный декодировщик сообщает об этом вместо того, чтобы гадать.
Чем оно отличается от Base64
Заманчиво свалить процентное кодирование в одну кучу с Base64, но они отвечают на разные вопросы. Base64 берёт произвольные двоичные данные и делает их полностью безопасными для текстового канала, раздувая каждый ввод примерно на треть. Процентное кодирование оставляет уже безопасное большинство текста нетронутым и экранирует лишь те немногие символы, которые создали бы проблемы. Для обычного текста, состоящего в основном из букв и цифр, процентное кодирование гораздо компактнее и остаётся читаемым человеком; для сырых двоичных данных, где почти каждый байт пришлось бы экранировать, оно ужасно неэффективно, и Base64, или его URL-безопасный вариант, — правильный инструмент.
Короче говоря: процентное кодирование — это избирательное экранирование для текста, идущего в URL; Base64 — это полное перекодирование для байт, идущих куда угодно, где принимается только текст.
Попробуйте
Выберите Percent в инструменте codec, чтобы закодировать текст процентами или декодировать строку %XX обратно, всё в вашем браузере. Он кодирует не-ASCII-содержимое как байты UTF-8, отмечает повреждённое экранирование и сообщает, когда декодированный результат является двоичным, а не читаемым текстом.