Что делает percent-encoding
URL может содержать только ограниченный набор ASCII-символов, и некоторые из них (/, ?, &, =, #) имеют структурное значение. Любой другой байт записывается как знак процента и две hex-цифры: пробел — %20, & — %26, а байты UTF-8 буквы é — %C3%A9. Правила определяет RFC 3986.
Три режима, потому что контекст важен
| Режим | Экранирует | Сохраняет | Когда использовать |
|---|---|---|---|
| Компонент запроса | Всё, кроме A–Z a–z 0–9 - _ . ~ | Только незарезервированные символы | Вставка значения в параметр запроса или сегмент пути: ?q=…. То же, что encodeURIComponent. |
| Целый URL | Пробелы, не-ASCII, кавычки, < >… | : / ? # [ ] @ & = + $ , ; | Приведение в порядок полного URL без нарушения его структуры. То же, что encodeURI. |
| Данные формы | Как компонент, но пробел становится + | Тела HTML-форм (application/x-www-form-urlencoded) — то, что по умолчанию отправляет большинство HTTP-библиотек. |
Самая частая ошибка — применить кодирование целого URL к значению, содержащему & или =: сервер разделит параметр надвое. Кодируйте значения по правилам компонента и только потом соединяйте их.
Знаки плюс
В теле формы (и, по соглашению, в строке запроса) + означает пробел, поэтому при декодировании данных формы + нужно превращать в пробел, а буквальный плюс должен был быть отправлен как %2B. В пути + — просто плюс. Переключатель Декодировать + как пробел охватывает обе ситуации.
Двойное кодирование
Если вы видите в URL %2520, что-то закодировало уже закодированную строку: %20 был воспринят как текст, и его % стал %25. Декодируйте дважды, чтобы восстановить оригинал, а затем исправьте код, который кодировал дважды.
Вопросы
Что такое %20?
Пробел. 0x20 — ASCII-код пробела, поэтому percent-encoding записывает его как %20. В данных формы он может выглядеть как +.
В чём разница между encodeURI и encodeURIComponent?
encodeURIComponent экранирует каждый символ, который может быть структурным (включая /, ?, & и =), и предназначен для отдельных значений. encodeURI оставляет их нетронутыми, чтобы целый URL оставался URL. Используйте режим «Компонент запроса» для первого и «Целый URL» для второго.
Как кодируются неанглийские символы?
Как байты их формы UTF-8, каждый записанный как %XX. é — два байта (%C3%A9), 日 — три (%E6%97%A5). Старые системы иногда использовали Latin-1, что даёт %E9 для é; современные браузеры и API используют UTF-8.
Почему декодирование моей строки не удаётся?
Либо за % не следуют две hex-цифры (одиночный знак процента должен быть записан как %25), либо экранированные байты не образуют корректный UTF-8. Сообщение об ошибке уточняет, что именно.
Кодировать весь URL или только параметры?
Только параметры (и любой сегмент пути, содержащий пользовательский текст). Собирайте URL из уже закодированных частей, чтобы разделители оставались неэкранированными.