Экранирование спецсимволов в URL для API Гадалка

Веб‑сервис «Гадалка» (или любой другой API, принимающий параметры в URL) часто использует строку запроса (query string) для передачи данных. Если в эти параметры попадают специальные символы, они могут нарушить синтаксис URL, привести к ошибкам парсинга или, что ещё хуже, стать причиной уязвимостей (SQL‑инъекции, XSS и т.п.). Поэтому правильное экранирование — обязательный шаг при формировании запросов.

Почему экранирование так важно?

  • Синтаксическая корректность. Спецсимволы (пробел, «&», «=», «?», «#», «%» и др.) имеют особое значение в URL.
  • Безопасность. Неэкранированные данные могут быть интерпретированы сервером как часть кода.
  • Совместимость. Разные браузеры и серверные фреймворки по‑разному обрабатывают некорректные запросы.

Какие символы считаются «специальными»?

Согласно RFC 3986, в URL необходимо экранировать:

  1. Пробел () → %20 (или + в application/x-www-form-urlencoded).
  2. Символы резервации: ! * ' ( ) ; : @ & = + $ , / ? # [ ].
  3. Не ASCII‑символы (кириллица, китайские иероглифы и т.д.) → их UTF‑8‑байты, закодированные в %XX.

Основные способы экранирования

3.1 URL‑энкодинг (percent‑encoding)

Самый универсальный метод – преобразовать каждый «опасный» символ в его шестнадцатеричное представление, предварённое знаком «%». В большинстве языков есть готовые функции:

Язык Функция Пример
PHP urlencode / rawurlencode urlencode('привет мир') → %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82+%D0%BC%D0%B8%D1%80
JavaScript encodeURIComponent encodeURIComponent('привет мир') → %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80
Python urllib.parse.quote quote('привет мир') → %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82%20%D0%BC%D0%B8%D1%80
Java URLEncoder.encode URLEncoder.encode("привет мир", "UTF-8") → %D0%BF%D1%80%D0%B8%D0%B2%D0%B5%D1%82+%D0%BC%D0%B8%D1%80

3.2 Экранирование в контексте SQL

Если «гадалка» сохраняет запросы в базе данных, необходимо дополнительно защищаться от SQL‑инъекций. Лучший способ – использовать подготовленные запросы (prepared statements). Если это невозможно, применяйте функции экранирования, предоставляемые драйвером:

  • PHP: mysqli_real_escape_string или PDO‑плейсхолдеры.
  • Python (psycopg2, MySQLdb): параметризованные запросы через %s и передачу параметров отдельным аргументом.
  • Node.js (mysql2): connection.escape или параметры в массиве.

Если ответ от «гадалки» выводится в браузер, убедитесь, что любые пользовательские данные проходят через HTML‑энкодинг:

  • JavaScript: создание текстового узла document.createTextNode вместо вставки строки в innerHTML.

Пошаговый пример формирования запроса к API «Гадалка»

4.1 Сценарий

Пользователь вводит вопрос и своё имя. Нужно отправить GET‑запрос:

https://api.gadalki.ru/predict?name=ИМЯ&question=ВОПРОС

4.2 Реализация на PHP

<?php
$name = $_GET['name'] ?? '';
$question = $_GET['question'] ?? '';

/* 1️⃣ Экранируем для URL /
$encName = urlencode($name); // или rawurlencode
$encQuestion = urlencode($question);

/ 2️⃣ Формируем полный URL /
$url = "https://api.gadalki.ru/predict?name={$encName}&question={$encQuestion}";

/ 3️⃣ Выполняем запрос (cURL) /
$ch = curl_init($url);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
$response = curl_exec($ch);
curl_close($ch);
echo '<pre>' . htmlspecialchars($response, ENT_QUOTES, 'UTF-8') . '</pre>';
?>

4.3 Реализация на JavaScript (fetch)

const name = prompt('Введите ваше имя:');
const question = prompt('Задайте вопрос:');
/* Экранируем параметры */
const params = new URLSearchParams({
 name: name,
 question: question
});
fetch(`https://api.gadalki.ru/predict?${params.toString}`)
 .then(r => r.text)
 .then(text => {
 // безопасный вывод в DOM
 const pre = document.createElement('pre');
 pre.textContent = text; // textContent автоматически экранирует
 document.body.appendChild(pre);
 })
 .catch(err => console.error('Ошибка:', err));

Лучшие практики

  • Всегда используйте готовые функции. Ручное составление %XX приводит к ошибкам.
  • Не смешивайте кодировки. Приводите все строки к UTF‑8 до экранирования.
  • Применяйте параметризованные запросы при работе с базами данных.
  • Проверяйте длину и тип входных данных. Ограничения снижают риск атак.
  • Тестируйте. Используйте инструменты вроде Postman или curl с различными спецсимволами.
  • Логи и мониторинг. Записывайте запросы, но без чувствительных данных.

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

6.1 Что делать, если сервер «Гадалки» требует application/x-www-form-urlencoded?

Тогда вместо encodeURIComponent используйте URLSearchParams (JS) или http_build_query (PHP). Эти функции автоматически заменяют пробелы на «+» и кодируют остальные символы.

6.2 Как обрабатывать символ «+» в запросе?

В контексте URL‑энкодинга «+» обычно представляет пробел. Если вам нужен именно знак «+», его следует экранировать как %2B.

6.3 Можно ли полностью избавиться от экранирования, используя только POST‑запрос?

POST‑запросы передают данные в теле, но если тело формируется в формате application/x-www-form-urlencoded или multipart/form-data, всё равно требуется кодировать специальные символы. Лучшее решение – использовать application/json и отправлять JSON‑объект, где специальные символы не требуют URL‑энкодинга.

Помните: правильное экранирование – ваш первый щит против большинства веб‑угроз.