← Назад до блогу

Помилки кодування URL-адреси, які розробники все ще допускають (і виправляють)

Інструменти розробника29 березня 2026·7 хвилин читання
URL encoding debugging

Помилки кодування URL-адреси незначні, постійні та часто виявляються під час виробництва. Неправильне %20, амперсанд із подвійним кодуванням або переплутане + проти пробілу може порушувати виклики API, пошкоджувати дані відстеження та створювати вразливі місця в безпеці. Давайте виправимо найпоширеніші.

Перевірте своє кодування за допомогою нашого інструменту URL Encoder/Decoder — вставте будь-який рядок і миттєво перегляньте закодований результат.

encodeURI проти encodeURIComponent

JavaScript має дві вбудовані функції кодування, і використання неправильної є джерелом помилок №1:

ФункціяКодуєЗберігаєВикористовувати для
encodeURIПробіли, не ASCII: / ? # [ ] @ ! $ & ' ( ) * + , ; =Кодування повної URL
encodeURIComponentУсе вище + : / ? # @ ! $ & ' ( ) * + , ; =Тільки - _ . ~ та буквено-цифровіКодування значення параметра запиту
// НЕПРАВИЛЬНО — encodeURI зберігає & у значеннях запиту
const url = 'https://api.example.com/search?q=' + encodeURI('том і джеррі');
// Результат: https://api.example.com/search?q=tom%20&%20jerry
// & зберігається — тепер він виглядає як окремий параметр! // ПРАВИЛЬНО
const url = 'https://api.example.com/search?q=' + encodeURIComponent('том і джеррі');
// Результат: https://api.example.com/search?q=tom%20%26%20jerry

Емпіричне правило: Використовуйте encodeURIComponent для окремих значень. Використовуйте encodeURI, лише якщо у вас є повна URL-адреса, для якої потрібні лише символи, відмінні від ASCII.

Помилки подвійного кодування

Подвійне кодування відбувається, коли вже закодований рядок кодується знову:

const name = 'привіт, світ';
const encoded = encodeURIComponent(name); // привіт%20світе
const подвоєний = encodeURIComponent(закодований); // привіт%2520світе
// %25 - це кодування самого %!

Це зазвичай відбувається, коли:

  • Фреймворк автоматично кодує параметри запиту, і ви також їх попередньо кодуєте
  • URL-адреса кодується перед збереженням, а потім знову кодується під час отримання
  • Проміжне програмне забезпечення обробляє URL-адресу на кількох рівнях, до кожного з яких додається кодування

Виявлення

Шукайте %25 в URL-адресах — це майже завжди ознака подвійного кодування. Послідовність %2520 (пробіл із подвійним кодуванням) є класичним сигналом.

+ проти %20 Confusion

У надсиланні форм HTML (application/x-www-form-urlencoded) пробіли стають +. У стандартному процентному кодуванні (RFC 3986) пробіли стають %20.

Це важливо, оскільки:

  • decodeURIComponentnot декодує + назад у космос — залишає його як літерал +
  • Бекенд-фреймворки можуть або не можуть автоматично декодувати + залежно від аналізатора
  • Якщо ваш API очікує %20, але отримує +, пошук за запитом "red+car" повертає результати для "red+car" (з літеральним плюсом) замість "red car"
// Безпечне декодування, яке обробляє як +, так і %20
функція safeDecodeParam(значення) { return decodeURIComponent(value.replace(/\+/g, '%20'));
}

UTF-8 Edge Cases

Не-ASCII-символи, як-от é, ü, 日本語, і смайли мають бути у відсотковому кодуванні як їхній байт UTF-8 послідовності:

encodeURIComponent('café') // кафе%C3%A9
encodeURIComponent('日本語') // %E6%97%A5%E6%9C%AC%E8%AA%9E
encodeURIComponent('🔒') // %F0%9F%94%92

Проблеми виникають, коли:

  • Сервер очікує Latin-1, але отримує UTF-8 (mojibake — спотворені символи)
  • Стовпці бази даних не налаштовані на UTF-8, багатобайтові символи мовчки скорочуються
  • Файли журналу інтерпретують закодовані рядки з неправильним набором символів

Пасткові камені URL-адреси перенаправлення та зворотного виклику

Зворотні виклики OAuth і URL-адреси перенаправлення особливо схильні до помилок кодування:

// Створення перенаправлення OAuth
const redirectUri = 'https://myapp.com/callback?source=oauth';
const authUrl = `https://provider.com/auth?redirect_uri=${encodeURIComponent(redirectUri)}`;
// Правильно: вся URL-адреса зворотного виклику (включно з власною?) кодується як одне значення параметра

Поширені помилки:

  • Зовсім не кодується redirect_uri? у зворотному виклику розділяє батьківську URL-адресу
  • Часткове кодування redirect_uri — кодування шляху, але не запиту
  • Кодування повної URL-адреси авторизації замість лише значення параметра

Ці помилки часто створюють уразливості відкритого перенаправлення, які зловмисники використовують для фішингу.

Контрольний список налагодження

Якщо URL-адреса не працює належним чином, перевірте це в такому порядку:

  1. Шукайте %25 — вказує на подвійне кодування
  2. Перевірка + проти %20 — чи послідовно обробляються пробіли?
  3. Перегляньте необроблений запит — скористайтеся вкладкою DevTools у веб-переглядачі «Мережа», щоб побачити фактичну надіслану закодовану URL-адресу
  4. Тестуйте зі спеціальними символами — спробуйте & = ? # / у значеннях, щоб перевірити, чи вони порушують структуру URL
  5. Check Content-Type — сервер аналізує як application/x-www-form-urlencoded або application/json?
  6. Перевірте декодування на сервері — реєструйте необроблені та розкодовані значення на стороні сервера

Безпечні допоміжні функції

// Безпечне створення рядка запиту
функція buildQueryString(params) { повернути Object.entries(params) .map(([ключ, значення]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}` ) .join('&');
} // Використовуйте URLSearchParams (сучасні браузери + Node.js)
const params = new URLSearchParams({ q: 'tom & jerry', page: '1' });
const url = `https://api.example.com/search?${params}`;
// Правильно: автоматично обробляє кодування

Найкраща практика: Використовуйте конструктор URLSearchParams або URL замість об’єднання рядків вручну. Вони правильно обробляють кодування за замовчуванням.

FAQ

Чому + стає пробілом?

Це успадковане кодування форми HTML (application/x-www-form-urlencoded), де пробіли кодуються як +. У стандартному процентному кодуванні (RFC 3986) пробілами є %20. Конвенція + застосовується лише до рядків запиту в надсиланні форми, а не до сегментів шляху чи інших частин URL.

Як правильно закодувати вкладені URL-адреси?

Використовуйте encodeURIComponent для внутрішньої URL-адреси, перш ніж розмістити його в параметрі запиту зовнішньої URL-адреси. Це кодує символи на зразок :/?, які інакше сприймалися б як частина зовнішньої структури URL-адреси.

Чому підписи порушуються після кодування URL-адреси?

Підписи обчислюються за точними послідовностями байтів. Якщо ви підписуєте рядок перед кодуванням (або після декодування), але перевіряєте його в закодованій формі (або навпаки), байти відрізняються, і підпис не вдається. Завжди нормалізуйте кодування перед підписанням.

Пов’язані інструменти та статті