URL‑кодирование пробелов: %20 vs +

Сеансы гадания часто передаются в виде параметров URL‑ссылки: https://example․com/fortune?session=Таро%20на%20любовь․
Неправильное кодирование пробелов может привести к тому, что сервер не поймёт запрос, а пользователь получит ошибку 404 или неверный результат․ В этой статье мы разберём, какие правила диктуют использование %20 и +**, где они применимы, и как правильно генерировать такие ссылки в популярных языках программирования;


Что такое URL‑кодирование?

URL‑кодирование (иногда называют percent‑encoding) — это способ представления в URL символов, которые имеют специальное значение или недопустимы в чистом виде․ Каждый такой символ заменяется на последовательность % + два шестнадцатеричных знака, соответствующих его байтовому коду в UTF‑8․

Пример:

  • Пробел → %20
  • Запятая → %2C
  • Кириллица «г» → %D0%B3

Пробелы в URL: %20 vs +

Контекст Кодировка пробела Почему так
Путь (path) и фрагмент (fragment) %20 В соответствии с RFC 3986 пробел в пути считается недопустимым символом и должен быть заменён на %20․
Строка запроса (query string) в форме application/x-www-form-urlencoded +
Общий query string, сформированный вручную (не в контексте формы) Обычно %20, но допускается + при соблюдении правила application/x-www-form-urlencoded Если сервер ожидает application/x-www-form-urlencoded, то + будет корректно интерпретирован как пробел․

Где следует использовать +?

Символ + применяется только в теле запроса (body) и в строке запроса, если они кодируются по правилам application/x-www-form-urlencoded․ Это типичный случай для:

  • HTML‑форм с методом POST, когда enctype="application/x-www-form-urlencoded"․
  • Библиотек, которые автоматически используют эту схему (например, urllib․parse․urlencode в Python)․

Пример формы:

<form action="/fortune" method="GET">
 <input name="session" value="Таро на любовь">
 <button type="submit">Запустить</button>
</form>

После отправки браузер сформирует URL:

https://example․com/fortune?session=Таро+на+любовь

Где следует использовать %20?

Если пробел находится в любой части URL, не относящейся к application/x-www-form-urlencoded, необходимо использовать %20:

  • В путях (path): https://example․com/fortune/Таро%20на%20любовь
  • В фрагментах (anchor): https://example․com/page#Таро%20на%20любовь
  • В URL‑ах, сформированных вручную, где сервер ожидает строгий RFC 3986․

Если в ссылке используется + в пути, сервер может воспринять его как обычный плюс, а не как пробел, что приведёт к ошибке․

Примеры: ссылки на сеансы гадания

Сеанс в параметре запроса (форма GET)

https://fortune․example․com/start?session=Таро%20на%20любовь

Если мы используем библиотеку urllib․parse․urlencode, получим:

session=Таро+на+любовь

Оба варианта работают, но + предпочтительнее, когда сервер обрабатывает параметры как application/x-www-form-urlencoded․

Сеанс в части пути

https://fortune․example․com/session/Таро%20на%20любовь

Здесь + будет ошибкой, потому что в пути он не имеет специального значения․

Сеанс в фрагменте (для клиентского скрипта)

https://fortune․example․com/#session=Таро%20на%20любовь

Фрагмент также подчиняется RFC 3986 → используем %20․

Как правильно генерировать ссылки в разных языках

Python (модуль urllib)

import urllib․parse

params = {'session': 'Таро на любовь'}
query = urllib․parse․urlencode(params) # → 'session=Таро+на+любовь'
url = f"https://fortune․example․com/start?{query}"
print(url)

path = urllib․parse․quote('Таро на любовь') # → 'Таро%20на%20любовь'
url_path = f"https://fortune․example․com/session/{path}"
print(url_path)

JavaScript (в браузере)

// Для query‑строки
const params = new URLSearchParams({session: 'Таро на любовь'});
const url = `https://fortune․example․com/start?${params․toString}`;
// URLSearchParams автоматически использует '+' для пробелов
console․log(url);

// Для пути
const path = encodeURIComponent('Таро на любовь'); // → 'Таро%20на%20любовь'
const urlPath = `https://fortune․example․com/session/${path}`;
console․log(urlPath);

PHP

 $session]); // → session=Таро+на+любовь
echo "https://fortune․example․com/start?$query";

// путь
$path = rawurlencode($session); // → Таро%20на%20любовь
echo "https://fortune․example․com/session/$path";
?>

Инструменты и проверка корректности URL

  • Онлайн‑декодеры/энкодеры – например, url-encode-decode․com․
  • curl – позволяет увидеть, как сервер воспринимает запрос:
    curl -v "https://example․com/start?session=Таро+на+любовь"
  • Браузерные консоли – в Chrome DevTools → Network → запрос → Query String Parameters․

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

  1. Можно ли использовать + в пути? Нет․ В пути + считаеться обычным символом «+» и не будет интерпретирован как пробел․
  2. Что делать, если сервер принимает оба варианта? Лучше придерживаться стандарта: + только в application/x-www-form-urlencoded, иначе %20․
  3. Почему некоторые старые ссылки используют %20 в query‑строке? До появления application/x-www-form-urlencoded единственным способом было %20․ Современные серверы обычно понимают оба варианта, но лучше использовать + для совместимости с формами․
  4. Как кодировать несколько пробелов подряд? Каждый пробел кодируется независимо: + + → ++ в query‑строке, %20%20 в пути․

Для корректной работы ссылок на сеансы гадания необходимо строго различать два контекста:

  • В строке запроса, сформированной как application/x-www-form-urlencoded – используйте + для пробелов․
  • Во всех остальных частях URL (путь, фрагмент, произвольный query‑string) – заменяйте пробелы на %20․

Соблюдая эти правила и применяя стандартные функции urlencode, quote, encodeURIComponent и их аналоги, вы избавитесь от большинства ошибок, связанных с неверным кодированием, и обеспечите надёжную работу вашего сервиса гадания․

Помните: правильное кодирование – это первый шаг к безопасному и предсказуемому взаимодействию между клиентом и сервером․