Как исправить ошибки "URI Malformed" в JavaScript
Разбираемся, как диагностировать и устранить распространённую ошибку "URIError: URI malformed" в JavaScript с помощью практических решений.
Что означает ошибка URIError: URI Malformed
Ошибка URIError: URI malformed возникает в JavaScript, когда вы пытаетесь декодировать строку, содержащую недопустимые percent-encoded последовательности. Эта ошибка выбрасывается функциями decodeURI() или decodeURIComponent(), когда они встречают некорректно закодированный символ.
Распространённые причины
1. Одиночные знаки процента
Знак процента (%), за которым не следуют ровно две шестнадцатеричные цифры, недопустим. Например, %, %G или %2 (неполная последовательность) — все они приведут к этой ошибке.
// Эти вызовы выбросят URIError
decodeURIComponent('%'); // Одиночный %
decodeURIComponent('%2'); // Неполная последовательность
decodeURIComponent('%GH'); // Недопустимые шестнадцатеричные цифры
decodeURIComponent('100%'); // % в конце без шестнадцатеричных цифр
2. Недопустимые UTF-8 последовательности
Когда percent-encoded байты не образуют корректную последовательность символов UTF-8, декодер не может преобразовать их в строку. Это может произойти, если данные повреждены или были закодированы с использованием другой кодировки символов.
3. Двойное кодирование
Двойное кодирование происходит, когда уже закодированная строка кодируется повторно. Например, %20 (закодированный пробел) превращается в %2520. При попытке декодировать исходную строку последовательности могут оказаться недопустимыми.
Как это исправить
Решение 1. Используйте try-catch
function safeDecode(str) {
try {
return decodeURIComponent(str);
} catch (e) {
// Возвращаем исходную строку, если декодирование не удалось
console.warn('Failed to decode:', str, e.message);
return str;
}
}
Решение 2. Проверяйте перед декодированием
function isValidEncodedURI(str) {
try {
decodeURIComponent(str);
return true;
} catch {
return false;
}
}
function fixMalformedURI(str) {
// Заменяем одиночный % на %25 (закодированный процент)
return str.replace(/%(?![0-9A-Fa-f]{2})/g, '%25');
}
Решение 3. Предотвращайте двойное кодирование
function smartEncode(str) {
// Сначала пробуем декодировать — если получилось, строка
// уже закодирована
try {
const decoded = decodeURIComponent(str);
// Если декодирование изменило строку, значит она была закодирована
if (decoded !== str) {
return str; // Уже закодирована, возвращаем как есть
}
} catch {
// Строка не является корректно закодированной, кодируем её
}
return encodeURIComponent(str);
}
Рекомендации по предотвращению ошибок
- Всегда используйте try-catch при декодировании URL, полученных от пользователя или из внешних источников
- Проверяйте URL перед их обработкой
- Будьте осторожны, чтобы не закодировать значения дважды
- По возможности используйте API URL и URLSearchParams — они обрабатывают кодирование корректно
- Очищайте значения строки запроса перед кодированием
- Логируйте некорректные URL для отладки