Блог ClockTools

URL-инструменты

Кодирование пробелов в URL: %20 или плюс?

В компоненте URI пробел превращается в %20, а в плюс — только при сериализации в формате формы.

Автор , разработчик и издатель | | Проверено в соответствии с редакционной политикой ClockTools

Иллюстрация ClockTools: кодирование пробелов в URL
Оглавление

Пробел в данных URL обычно превращается в %20, но сериализация запроса в формате формы представляет его как +. Оба варианта могут быть верными. Выбор зависит от получателя: отдельный компонент URI кодируйте процентным способом, а плюс используйте только там, где ожидаются данные application/x-www-form-urlencoded.

Кодировщик URL ClockTools явно различает контексты с помощью профилей URI Component, Full URL и Form Data. Вставьте green tea, переключите профили и сравните результаты до изменения кода приложения.

Начните с целевой среды

Не спрашивайте: «Какой символ всегда означает пробел?» Спросите, какой парсер получит значение.

Для сегмента пути, значения фрагмента или значения отдельного запроса надежным представлением является процентное кодирование. Байт UTF-8 символа пробела является шестнадцатеричным. 20, поэтому его тройка с процентным кодированием равна %20.

Для данных HTML-форм соглашение о сериализации использует + для пробела, а буквальный плюс кодирует как %2B. Стандарт URL WHATWG определяет это поведение form-urlencoded отдельно от общего разбора URL.

Синтаксис URI в RFC 3986 определяет процентно-кодированный октет как % и две следующие шестнадцатеричные цифры. Он также различает зарезервированные разделители и незарезервированные символы данных. Поэтому кодирование значения отличается от кодирования целого адреса.

Схема выбора: пробел преобразуется в %20 для компонента URI или в плюс при сериализации формы
Схема выбора: пробел преобразуется в %20 для компонента URI или в плюс при сериализации формы

Таблица выбора между %20 и плюсом

Целевая средаПредставление пробелаПример для green teaПочему
Сегмент пути%20/topics/green%20teaПробел является данными одного сегмента пути
Значение запроса, закодированное как компонент%20?q=green%20teaКодирование компонента отделяет значение от разделителей
Запрос или тело запроса в кодировке формы+q=green+teaСериализатор формы заменяет пробел плюсом
Полное отображение URL-адреса%20 там, где требуется сериализовать буквальный пробелhttps://example.com/green%20tea?q=hot%20cupСтруктурный :, /, ?, =и & оставаться разделителями
Буквальный плюс внутри данных формы%2Bq=C%2B%2BВ этом профиле незакодированный плюс декодируется как пробел

Последняя строка предотвращает частую ошибку. Если нужное значение — C++, передача C++ через декодер формы может дать C . Перед разбором формы кодируйте каждый буквальный плюс как %2B.

Четыре воспроизводимых теста ClockTools

Мы выполнили четыре небольших ввода через текущую реализацию инструмента. Его профиль компонента URI использует JavaScript. encodeURIComponent. Данные формы применяют ту же кодировку компонента, а затем заменяют %20 с +. Полный URL-адрес использует encodeURI, который сохраняет структуру URL.

ВводПрофильНаблюдаемый результатИнтерпретация
green teaURI-компонентgreen%20teaОдин компонент с процентно-кодированным пробелом
green teaДанные формыgreen+teaПравило пробела для форм
C++Данные формыC%2B%2BБуквальные знаки плюс защищены
https://example.com/a b?q=x yПолный URL-адресhttps://example.com/a%20b?q=x%20yРазделители URL-адресов остаются структурными

Это детерминированные преобразования, а не свидетельство позиций в поиске. Их можно воспроизвести локально в браузере. Страница сразу обновляет результат, показывает процентное экранирование и число байтов; отправлять ввод на сервер не требуется.

Используйте URL-декодер для обратной проверки. Декодируйте green%20tea в профиле компонента, а green+tea — в Form Data. Если плюс появляется вне профиля формы, декодер предупреждает о неоднозначном смысле.

Что защищает кодирование компонентов?

В URL-адресе в качестве грамматики используются пунктуация. В строке запроса & может начать другой параметр и = отделяет имя от значения. # начинается фрагмент. ? начинает запрос. Если один из этих символов принадлежит пользовательским данным, оставление его необработанным может изменить структуру.

Рассмотрим значение timer & alarm. Кодирование компонентов производит timer%20%26%20alarm. Амперсанд становится %26, поэтому парсер получает одно значение вместо интерпретации alarm в качестве нового параметра.

Кодирование — это представление, а не проверка или шифрование. Перенаправление с процентным кодированием все равно может указывать на неутвержденный хост после декодирования. Закодированный сценарий по-прежнему является ненадежным вводом. Проверьте разрешенные схемы, хосты, имена параметров и бизнес-правила после анализа. Избегайте размещения паролей, токенов или других секретных данных в URL-адресах, поскольку адреса могут появляться в истории, журналах, аналитике, снимках экрана и данных реферера.

Когда вам нужно сравнить строку запроса «до» и «после», Проверка текстовых различий делает каждый измененный escape видимым. Это более надежно, чем сканирование длинного URL-адреса обратного вызова на предмет отсутствия одного из них. %25.

Почему двойное кодирование создает %2520?

Двойное кодирование происходит, когда уже закодированный текст обрабатывается как необработанные данные и кодируется снова.

Начните с одного пробела:

space -> %20

Кодировать %20 как новый компонент. Знак процента становится %25, а цифры остаются буквальными:

%20 -> %2520

Одно декодирование меняется %2520 вернуться к %20. Второе декодирование меняется %20 в пространство. Если ваше приложение ожидает один проход декодирования, но получает значение с двойным кодированием, пользователь может увидеть %20 вместо пустого.

Исправление состоит в том, чтобы не выполнять повторное декодирование, пока текст не станет правильным. Повторное декодирование может изменить намеренно закодированные разделители и создать проблемы безопасности. Определите границу владения: ровно один слой должен кодировать компонент, и ровно один соответствующий слой должен его декодировать.

Порядок отладки несоответствий пробелов

Используйте этот путь, когда одна система отправляет %20 и еще один дисплей +, %2520или буквальный пробел.

  1. Захватите необработанное значение до того, как какой-либо анализатор платформы изменит его.
  2. Определите, является ли поле сегментом пути, компонентом запроса, полным URL-адресом или телом формы.
  3. Запишите ожидаемое декодированное значение, включая буквальные знаки плюс.
  4. Воспроизведите тот же ввод в соответствующем профиле ClockTools.
  5. Декодируйте один раз с помощью принимающего профиля.
  6. Сравните результат с ожидаемым значением.
  7. Найдите в потоке приложения второй кодер или декодер, если %25 появляется неожиданно.
СимптомПервая проверкаВероятная причина
green+tea остается с плюсомПрофиль декодераДекодер компонента не заменяет плюс пробелом
C++ становится C Кодировка отправителяБуквальные плюсы не были закодированы как %2B
%20 виден пользователюЧисло декодированийЗакодированные данные никогда не декодировались или ранее подвергались двойному кодированию.
%2520 появляется в запросеЧисло кодированийЗнак процента от %20 был закодирован снова
Запрос разбивается после амперсандаГраница компонентаАмперсанд данных остался необработанным

Этот путь отладки намеренно узок. Он отделяет контекст данных от догадок, и каждый шаг имеет видимые входные и выходные данные.

Когда следует кодировать полный URL-адрес?

Используйте профиль «Полный URL-адрес» только в том случае, если вы хотите, чтобы адрес оставался адресом. Он сохраняет структурные знаки пунктуации, такие как двоеточие схемы, косая черта, вопросительный знак, знак равенства, амперсанд и маркер фрагмента, при кодировании таких символов, как пробелы.

Используйте URI Component, если полный URL вложен в другой параметр. Например, адрес обратного вызова в redirect= является данными внешнего URL. Кодирование вложенного адреса как одного компонента не дает его ? и & попасть во внешний запрос.

Не прогоняйте адрес через разные профили в надежде получить универсально безопасную строку. Явно задайте границу:

outer URL structure + encodeURIComponent(inner callback URL)

Принимающее приложение должно проанализировать внешний URL-адрес, извлечь компонент обратного вызова, один раз декодировать его, проанализировать полученный внутренний URL-адрес и проверить место назначения. Кодирование сохраняет синтаксис нетронутым; проверка решает, разрешен ли пункт назначения.

Часто задаваемые вопросы

Должен ли пробел URL-адреса быть %20 или знаком плюса?

Используйте %20 для пробела внутри общего компонента URI. Используйте +, если принимающий рабочий процесс явно ожидает сериализации application/x-www-form-urlencoded.

Почему знак плюс декодируется как пробел?

Синтаксические анализаторы в стиле формы отображают + в пробел как часть соглашения о кодировке формы. Декодер общего компонента не должен применять эту замену.

Как закодировать буквальный знак плюс в данных формы?

Закодируйте плюс как %2B. Иначе декодер формы может принять незакодированный плюс за пробел.

Что означает %2520?

%2520 обычно указывает на двойное кодирование. Знак процента в существующем escape-коде %20 стал %25, поэтому одно декодирование возвращает %20, а второе декодирование возвращает пробел.

Должен ли я кодировать весь URL-адрес с помощью encodeURIComponent?

Не тогда, когда его схема, косые черты, разделители запроса и маркер фрагмента должны оставаться структурными. Используйте компонентную кодировку, когда весь URL-адрес вложен как данные в другое значение.

Обеспечивает ли кодирование URL-адресов безопасность ненадежного ввода?

Нет. Кодирование сохраняет границы синтаксиса, но получатель все равно должен проверять схемы, хосты, перенаправления, значения параметров, разрешения и другие бизнес-правила после анализа.

Об авторе

Винешваран Виджаякумар

Основатель, разработчик и издатель ClockTools | Менеджер по цифровому маркетингу | Индия

Винешваран — инженер с многолетним техническим опытом, включая работу менеджером по цифровому маркетингу в Дубае. Его работа объединяет анализ данных, поисковую оптимизацию, оптимизацию конверсии, создание контента и визуальных материалов, а также прикладной искусственный интеллект и машинное обучение. В ClockTools он использует этот междисциплинарный опыт для создания специализированных браузерных инструментов и практических руководств с опорой на источники.

Профиль в LinkedIn