Инструменты разработчика · Кодер и декодер URL
URIError: URI искажен — почему decodeURIComponent выдает ошибку и как это исправить
· Как это работает
URL-кодировка javascript обработка ошибок
decodeURIComponent выдает ошибку, если за знаком процента не следуют две шестнадцатеричные цифры или если декодированные байты недействительны UTF-8. В этом посте показаны входные данные, которые его запускают, и способы защитного декодирования.
Сбой знака процента — почему скидка 100% нарушает decodeURIComponent
В форме вводится код скидки «100% off». JavaScript передает это в decodeURIComponent в декодере URL. Функция выдает URIError: URI неправильного формата. За знаком процента не следуют две шестнадцатеричные цифры. Это полностью нарушает правила процентного кодирования. decodeURIComponent ожидает, что каждый % будет начинать триплет, например %20 или %C3. Одинокий % — это синтаксическая ошибка, которая немедленно останавливает выполнение и выдает ошибку.
Безопасное обнаружение этой ошибки полностью предотвращает сбой приложения. URL-адреса поступают из пользовательского ввода, перенаправлений, QR-кодов и электронных писем. Опечатки случаются часто. Отчет о сбое с URIError подскажет вам, где можно быстро разобраться. Защитное декодирование обеспечивает работу приложений, а журналы ошибок становятся полезными для отладки.
Два вида сбоев — неверные escape-коды в шестнадцатеричном формате и недопустимые последовательности байтов UTF-8.
decodeURIComponent выдает ровно две ситуации. Во-первых: неверная escape-последовательность. Процент, за которым не следуют две шестнадцатеричные цифры (0-9, A–F, a–f). Примеры: %ZZ, %2, %2g. Второе: действительный триплет, например %E9, декодирует недопустимые UTF-8 байты. Во-первых, это ошибка формата. Второе – смысловая ошибка. И выбрасывайте, и немедленно прекращайте выполнение.
UTF-8 имеет строгие правила относительно последовательностей байтов. Байты 0x80–0xFF встречаются только в многобайтовых последовательностях. Одиночный %E9 не может быть действительным сам по себе UTF-8. Этот потерянный байт вызывает ошибку. Ошибки формата очевидны. Семантические ошибки неуловимы, но столь же реальны. В обоих случаях требуется обработка try/catch в рабочем коде.
Устаревшее однобайтовое кодирование — когда выдается только %E9, но %C3%A9 сохраняется.
Путаница проистекает из истории веб-стандартов. На старых страницах использовалась латиница 1 вместо UTF-8. На латыни 1, %E9 обозначает é. Современные браузеры используют исключительно UTF-8. UTF-8 кодирует é как %C3%A9. Современные декодеры ожидают UTF-8 и отвергают %E9 как некорректный. Это правильное поведение. Ошибка сигнализирует о проблеме с исходными данными.
Современный консенсус: UTF-8 повсюду. Стандарт URL определяет UTF-8. Все современные браузеры используют UTF-8. Если вы столкнулись с %E9 в старых системах, уловите ошибку и вернитесь к необработанной строке. Не декодируйте как Latin-1 в современном коде. Выясните, откуда взялись данные.
Три входа, три сообщения об ошибках — чем отличаются движки на одной и той же сломанной струне
Браузерные движки последовательно отвергают неверный ввод, а ошибки в словах — по-разному. Chrome сообщает «URI искажен». Firefox сообщает о «неверной последовательности URI». Отчеты Safari «не могут преобразовать неопределенное значение в объект». Все три двигателя отвергают одинаковый входной сигнал. Точная формулировка сообщения не стандартизирована для разных движков или версий. Никогда не полагайтесь на текст ошибки в качестве руководства по логике кода.
Никогда не сопоставляйте строку с сообщением об ошибке для принятия программных решений. Всегда перехватывайте URIError по типу. Функция decodeUrl оборачивает decodeURIComponent и предоставляет согласованный код INVALID_PERCENT_ENCODING. Это называет точную проблемную позицию. Он работает во всех средах выполнения, поскольку не зависит от вариаций формулировок движка. Этот подход более надежен и ремонтопригоден.
Безопасное чтение исключения — проверка /catch, и резервные шаблоны
Самый простой защитный шаблон: оберните decodeURIComponent в try/catch.. Если он выдает ошибку, используйте необработанную строку или символ замены. Это предотвращает сбой неправильного ввода. Для значений запроса покажите форму в кодировке URL. Для текста, обращенного к пользователю, вставьте заменяющий символ. Это предохраняет неверные входные данные от поломки приложений и обеспечивает стабильность.
Предварительная проверка с помощью регулярных выражений для обеспечения скорости и безопасности. Перед декодированием убедитесь, что входные данные содержат только допустимые триплеты %XX. Шаблон /%[0-9A-Fa-f]{2}/g перехватывает допустимые escape-последовательности; все несовпадающее является недействительным. Ошибки формата быстро терпят неудачу из-за очевидного мусора. UTF-8 ошибки по-прежнему требуют попытки /catch. В совокупности это обеспечивает комплексную защиту от ошибок.
Тихие сбои скрывают ошибки — почему слепое декодирование так же рискованно, как и нарушение кодирования
Тонкий риск: декодер не выбрасывает, а молча выдает неправильный текст. Старый код, использующий устаревший unescape, оставляет в памяти недействительный UTF-8. Текст выглядит нормально на экране, пока не достигнет систем, строго проверяющих UTF-8. Современный код выбрасывает, а не повреждает молча. Исключение более понятно и безопасно, чем скрытое повреждение данных, распространяющееся вниз по течению.
Предположим, что пользовательский ввод неверен. Всегда завершайте вызовы. Зарегистрируйте ошибки с исходным вводом для отладки. Никогда не предполагайте, что каждый % действителен. Опечатки и усечение приводят к неполным переходам. Рассматривайте их как ошибки данных, а не логические ошибки. Защитный код корректно выдерживает неверные входные данные и обеспечивает надежность систем.
Что пропускают настоящие инструменты: поведение серверной платформы и восстановление ошибок
Серверные платформы более снисходительно относятся к неправильному кодированию, чем браузеры. Ruby, Python и PHP предлагают конфигурацию для обработки недопустимых escape-символов в URL-адресах. Некоторые символы замены заменяются автоматически. Другие сбрасывают байты молча. Некоторые исключения вызывают такие, как JavaScript. Фактическое поведение зависит от платформы и параметров конфигурации, выбранных разработчиками.
В этой статье рассматривается только поведение браузера JavaScript. Если значения поступают из API-интерфейсов сервера, сервер уже декодировал или пропустил ошибки перед отправкой. Серверы могут быть более снисходительными, чем клиенты. При написании контрактов API укажите, являются ли значения необработанными или предварительно декодированными. Строки запроса URL должны поступать в процентном кодировании; JSON может быть предварительно декодирован.
Проверяйте заранее — используйте кодировщик и декодер URL для первой проверки подозрительных строк.
Прежде чем передавать подозрительные URL-адреса в decodeURIComponent, вставьте их в кодировщик и декодер URL. Инструмент показывает точную кодировку, обнаруживает неверные escape-символы и объясняет ошибки, не приводя к сбою вашего приложения. Протестируйте с %ZZ, %E9 и 100%, чтобы увидеть различные сбои и их точные сообщения об ошибках. Это занимает секунды и укрепляет уверенность.
Проверяйте заранее, корректно выявляйте ошибки и регистрируйте, что сломалось. Защитный декодер и инструмент тестирования обеспечивают работоспособность и возможность отладки приложений. Кодер и декодер URL превращает «URI искаженный» в полезную информацию, которую вы можете использовать немедленно. Примените этот шаблон к своим собственным декодерам, чтобы обеспечить устойчивость и удобство обслуживания в производственных средах.