Процентное кодирование
Процентное кодирование (также 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) | Процентное представление |
|---|---|---|---|
| Пробел | 0x20 | 0x20 | %20 (или +) |
# (решётка) | 0x23 | 0x23 | %23 |
& (амперсанд) | 0x26 | 0x26 | %26 |
? (вопрос) | 0x3F | 0x3F | %3F |
= (равно) | 0x3D | 0x3D | %3D |
А (кириллица) | 0x0410 | 0xD0 0x90 | %D0%90 |
Я (кириллица) | 0x042F | 0xD0 0xAF | %D0%AF |
€ (евро) | 0x20AC | 0xE2 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 полностью теряется — адрес превращается в набор символов %, что усложняет его ручной ввод, запоминание и передачу.
Источники
- RFC 3986 — Uniform Resource Identifier (URI): Generic Syntax (2005 год).
- RFC 1738 — Uniform Resource Locators (URL) (1994 год, устаревший).
- RFC 2396 — Uniform Resource Identifiers (URI): Generic Syntax (1998 год, устаревший).
- «URL Encoding» — документация W3C (World Wide Web Consortium).
- «Percent-encoding» — спецификация WHATWG (Web Hypertext Application Technology Working Group).
BFOmetr — база данных и аналитика по компаниям России.
На главную BFOmetr →