Открыть сервис

Процентное кодирование

Процентное кодирование (также URL-кодирование, Percent-encoding) — это механизм представления информации в унифицированном указателе ресурса (URL) и других универсальных идентификаторах ресурсов (URI) путём замены символов, недопустимых или имеющих специальное значение в синтаксисе URI, на последовательность символов, начинающуюся со знака процента (%), за которым следуют две шестнадцатеричные цифры, соответствующие числовому коду символа в определённой кодировке (обычно ASCII или UTF-8).

История и стандартизация

Необходимость в кодировании возникла с развитием Всемирной паутины и протокола HTTP. Первоначальные спецификации URI, определённые в RFC 1738 (1994 год) и RFC 2396 (1998 год), устанавливали, что URL может содержать только ограниченный набор символов из таблицы ASCII: буквы латинского алфавита (A–Z, a–z), цифры (0–9) и несколько специальных символов, таких как дефис (-), подчёркивание (_), точка (.) и тильда (~). Все остальные символы, включая пробелы, кириллицу, иероглифы и знаки препинания (например, «?», «#», «&», «=»), должны были быть закодированы.

Основополагающим стандартом, описывающим процентное кодирование, является RFC 3986 (2005 год), который заменил предыдущие спецификации. В этом документе определены правила кодирования, набор зарезервированных и незарезервированных символов, а также алгоритмы для работы с URI. Позднее, с распространением интернационализированных доменных имён (IDN) и необходимостью поддержки не-ASCII символов, стандарт был расширен для использования кодировки UTF-8, которая стала обязательной для веб-адресов в большинстве современных браузеров и серверов.

Принцип работы

Процентное кодирование преобразует байтовое представление символа в строку вида %XX, где XX — двузначное шестнадцатеричное число (от 00 до FF). Для символов, входящих в базовый набор ASCII (коды от 0 до 127), кодирование выполняется напрямую. Например, пробел (код 32 или 0x20) кодируется как %20. Символ «#» (код 35 или 0x23) кодируется как %23.

Для символов, не входящих в ASCII (например, буквы кириллицы или иероглифы), сначала выполняется их кодирование в многобайтовую последовательность UTF-8, а затем каждый байт этой последовательности кодируется отдельно. Например, буква «А» (кириллическая заглавная) в кодировке UTF-8 представляется двумя байтами: 0xD0 и 0x90. Соответственно, её процентное представление будет %D0%90.

Зарезервированные и незарезервированные символы

Стандарт RFC 3986 делит символы на три категории:

  • Незарезервированные символы: Могут использоваться в URI без кодирования. К ним относятся:
  • Латинские буквы: A–Z, a–z
  • Цифры: 0–9
  • Специальные символы: - (дефис), . (точка), _ (подчёркивание), ~ (тильда)
  • Зарезервированные символы: Имеют специальное значение в синтаксисе URI (например, разделяют компоненты пути, обозначают запрос или фрагмент). Их следует кодировать, если они используются не по своему прямому назначению (например, как часть данных). К ним относятся:
  • : (двоеточие) — разделяет схему и иерархическую часть
  • / (слеш) — разделяет сегменты пути
  • ? (вопрос) — начинает строку запроса
  • # (решётка) — начинает идентификатор фрагмента
  • & (амперсанд) — разделяет параметры запроса
  • = (равно) — разделяет ключ и значение в параметрах запроса
  • @ (собака) — обозначает информацию об аутентификации
  • $, +, ,, ; — имеют специальное значение в некоторых подкомпонентах
  • Другие символы: Все прочие символы (пробелы, кириллица, иероглифы, управляющие символы с кодами 00–1F и 7F) должны быть обязательно закодированы.

Применение

Процентное кодирование используется во всех аспектах работы с веб-адресами и передачей данных через HTTP.

Передача данных в URL-адресах

Наиболее распространённое применение — формирование строки запроса (query string) в URL. Параметры, передаваемые после знака ?, часто содержат пробелы, кириллицу или символы, которые могут быть неверно интерпретированы. Например, поисковый запрос «книга по истории» в URL будет выглядеть как ?q=%D0%BA%D0%BD%D0%B8%D0%B3%D0%B0+%D0%BF%D0%BE+%D0%B8%D1%81%D1%82%D0%BE%D1%80%D0%B8%D0%B8 (где пробел часто кодируется как + или %20).

Кодирование имён файлов и путей

В веб-серверах и файловых системах имена файлов, содержащие не-ASCII символы или пробелы, также кодируются для корректного отображения в адресной строке браузера. Например, файл «Отчёт.docx» будет представлен как %D0%9E%D1%82%D1%87%D1%91%D1%82.docx.

Формы и отправка данных

При отправке HTML-форм методом GET все данные формы автоматически кодируются браузером в строку запроса URL. При отправке методом POST данные могут кодироваться в теле запроса, но тип кодирования (application/x-www-form-urlencoded) также использует процентное кодирование для всех не-ASCII и специальных символов.

REST API и веб-сервисы

Большинство современных веб-API (REST, SOAP) требуют, чтобы все параметры в URL были корректно закодированы. Неправильное кодирование может привести к ошибкам парсинга запроса на стороне сервера, некорректной обработке данных или даже к уязвимостям, таким как инъекции в URL.

Примеры кодирования

Исходный символКод ASCII/UnicodeШестнадцатеричный код (UTF-8)Процентное представление
Пробел0x200x20%20 (или +)
# (решётка)0x230x23%23
& (амперсанд)0x260x26%26
? (вопрос)0x3F0x3F%3F
= (равно)0x3D0x3D%3D
А (кириллица)0x04100xD0 0x90%D0%90
Я (кириллица)0x042F0xD0 0xAF%D0%AF
(евро)0x20AC0xE2 0x82 0xAC%E2%82%AC

Особенности и исключения

  • Символ «+»: В контексте строки запроса (после ?) пробел может кодироваться не только как %20, но и как символ +. Это исторически сложившаяся практика, восходящая к кодированию данных форм (application/x-www-form-urlencoded). В других частях URI (путь, хост) пробел кодируется только как %20.
  • Двойное кодирование: Ошибка, при которой уже закодированная строка кодируется повторно. Например, %20 (пробел) может быть ошибочно закодирован как %2520 (где %25 — это код самого символа %). Это приводит к некорректной обработке данных.
  • Кодирование в JavaScript: Функции encodeURI() и encodeURIComponent() в JavaScript предназначены для кодирования URI. Первая кодирует весь URI, оставляя зарезервированные символы (например, :, /, ?) нетронутыми. Вторая кодирует все символы, включая зарезервированные, и используется для кодирования отдельных компонентов (например, значений параметров).
  • Кодирование на стороне сервера: Большинство серверных языков (PHP, Python, Java, C#) имеют встроенные функции для декодирования (urldecode, urllib.parse.unquote) и кодирования (urlencode, urllib.parse.quote) строк в формат процентного кодирования.

Критика и ограничения

Основным недостатком процентного кодирования является значительное увеличение длины URL при кодировании многобайтовых символов. Например, один символ кириллицы (2 байта в UTF-8) превращается в 6 символов (%D0%90). Для иероглифов (3 байта) длина увеличивается в 9 раз. Это может приводить к превышению лимитов длины URL, установленных некоторыми веб-серверами и прокси-серверами (обычно 2048 или 8192 символа). Кроме того, человекочитаемость URL полностью теряется — адрес превращается в набор символов %, что усложняет его ручной ввод, запоминание и передачу.

Источники

  1. RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax (2005 год).
  2. RFC 1738 — Uniform Resource Locators (URL) (1994 год, устаревший).
  3. RFC 2396 — Uniform Resource Identifiers (URI): Generic Syntax (1998 год, устаревший).
  4. «URL Encoding» — документация W3C (World Wide Web Consortium).
  5. «Percent-encoding» — спецификация WHATWG (Web Hypertext Application Technology Working Group).

BFOmetr — база данных и аналитика по компаниям России.

На главную BFOmetr →