URL-кодирование Что уходит в укрытие и почему ваш API ломается без этого

Опубликовано
Кодирование URL: Что экранируется и почему ваша API-система не работает без этого 1
Реклама · УДАЛИТЬ?

Ваш запрос выглядел корректно. Конечная точка соответствовала, заголовки были правильными, и ответ пришёл с кодом 400 Bad Request. После двадцати минут внимательного изучения вы обнаруживаете проблему: электронная почта в строке запроса, содержащая символ — который сервер интерпретировал как пробел. Это действие URL-кодирования, и оно нарушает работу по сложным и трудно отлаживаемым способам. + Этот гайд описывает, что делает процентное кодирование, какие символы нужно кодировать в каких контекстах, ловушку, которую каждый сталкивается в JavaScript, и как использовать инструмент, такой как

для проверки своей работы. URL Encoder/Decoder Что делает URL-кодирование на самом деле

URL может содержать только подмножество символов ASCII. Все остальные — пробелы, международные символы, символы, имеющие особое значение в URL — должны быть преобразованы в безопасный формат перед передачей.

Процентное кодирование делает это, заменяя каждый небезопасный байт на символ процента, за которым следуют две шестнадцатеричные цифры. Пробел становится

, символ хеша становится %20, слэш становится %23. Название происходит из этого ведущего символа процента. %2FСпецификация (RFC 3986) определяет «незащищённые символы», которые не требуют кодирования: буквы (A–Z, a–z), цифры (0–9) и четыре символа:

. Все остальное либо является защищённым символом (используется для разделения структуры URL), либо должно быть закодировано. - _ . ~Символы, которые ломают API

Вот те, которые в реальности вызывают наибольшее разрушение:

Контексты, требующие кодирования

Символ Закодировано Все контексты Примечания
Космос %20 Также кодируется как в данных формы — см. ниже + Значения в строке запроса
& %26 Разделяет параметры запроса; должен быть закодирован внутри значения Разделяет параметры запроса; должен быть закодирован внутри значения
= %3D Разделяет параметры запроса; должен быть закодирован внутри значения Разделяет ключ от значения; кодируйте его внутри самого значения
+ %2B Разделяет параметры запроса; должен быть закодирован внутри значения для буквального плюса %2B Путь, строка запроса
# %23 Отмечает фрагмент; всё после него не передаётся на сервер Отмечает фрагмент; всё, что следует за ним, никогда не отправляется на сервер
? %3F Начинает строку запроса; кодируйте его в пути или в значениях Начинает строку запроса; кодируйте его в пути или в значениях
/ %2F Разделяет сегменты пути; кодируйте его внутри значения сегмента Электронные адреса в параметрах запроса должны быть закодированы так
@ %40 Разделяет параметры запроса; должен быть закодирован внутри значения Три контекста, разные правила

Часть URL, которую вы кодируете, определяет, что нужно закодировать.

Полный URL

— Когда у вас есть полный URL, который нужно передавать, вы хотите сохранить его структуру. Слэши, знаки вопроса и символы хеша остаются без изменений. Только символы, не входящие в разрешённый набор, подлежат кодировке. Значение строки запроса

— Здесь живут большинство ошибок API. Каждое значение в строке запроса должно быть закодировано так, чтобы символы, используемые для структурирования запроса ( ) не появлялись буквально в значении. Если имя пользователя — «John & Jane», строка запроса должна быть&, =, #, +(которая сервер интерпретирует как два отдельных параметра). name=John%20%26%20Jane, а не name=John & Jane Сегмент пути

— Сегмент пути — это часть между слэшами. Если в сегменте содержится слэш (например, имя файла с слэшем), он должен быть закодирован как . Некоторые серверы рассматривают %2Fв пути как потенциальную угрозу безопасности; знайте свой бэкенд перед использованием этого. %2F encodeURI против encodeURIComponent — ловушка в JavaScript

JavaScript предоставляет вам две встроенные функции кодирования, и использование неправильной из них — очень распространённая ошибка.

Правило: используйте

// encodeURI — encodes a full URL
// Preserves: : / ? # [ ] @ ! $ & ' ( ) * + , ; =
encodeURI("https://example.com/search?q=hello world&lang=en")
// → "https://example.com/search?q=hello%20world&lang=en"
// Note: & and = are NOT encoded — the query structure is preserved

// encodeURIComponent — encodes a single value
// Encodes everything except: A-Z a-z 0-9 - _ . ! ~ * ' ( )
encodeURIComponent("hello world&lang=en")
// → "hello%20world%26lang%3Den"
// Note: & and = ARE encoded — safe to use as a query value

// The bug: using encodeURI on a value
encodeURI("hello world&lang=en")
// → "hello%20world&lang=en"  ← & survives! Server sees two parameters.

// The correct approach for building query strings
const name = "John & Jane"
const email = "john+jane@example.com"
const url = `https://api.example.com/users?name=${encodeURIComponent(name)}&email=${encodeURIComponent(email)}`
// → "https://api.example.com/users?name=John%20%26%20Jane&email=john%2Bjane%40example.com"

на отдельных значениях перед вставкой их в URL. Используйте encodeURIComponent только тогда, когда у вас есть полный URL и вы хотите очистить его без разрушения его структуры. encodeURI Символ плюс: кодирование формы против процентного кодирования

Когда HTML-форма подаёт данные с

, браузеры кодируют данные с помощью method="GET". В этом формате пробелы становятся application/x-www-form-urlencoded. Многие серверные фреймворки (PHP, Django, Rails) автоматически декодируют + вместо %20как пробел в строке запроса. + Это создаёт проблему, когда значение действительно содержит символ плюс — например, номер телефона

. Если вы передаёте его как +44 7700 900000, сервер декодирует ведущий плюс как пробел и получает +44.... Решение — закодировать буквальный плюс как 44..., который сохраняется в обоих схемах декодирования. %2BДля современной работы с API, используйте

для пробелов (то, что %20 производит), а не полагайтесь на encodeURIComponent Двойное кодирование: когда кодирование идёт не так +.

Двойное кодирование происходит, когда вы кодируете что-то, что уже было закодировано. Символ процента в

сам по себе кодируется в %20 — сервер декодирует %2520 как буквальный процент, что даёт строку %25 вместо пробела. %20 Это обычно проявляется в следующих случаях:

Вы храните URL в базе данных и кодируете его снова перед использованием

  • Фреймворк или библиотека кодирует значения, которые вы уже вручную закодировали
  • Вы создаёте URL, содержащий другой URL как параметр
  • Чтобы избежать этого: кодируйте только один раз, в момент, когда вы составляете URL. Если вы не уверены, закодировано ли значение, сначала декодируйте его (с помощью

), а затем перекодируйте его правильно. decodeURIComponentОтладка кодирования URL в DevTools

Когда запрос API ведёт себя непредсказуемо, откройте DevTools (F12), перейдите на вкладку Network и нажмите на неудачный запрос. В разделе Headers найдите URL запроса — браузер показывает его в его исходной форме после кодирования. В разделе Payload вы можете увидеть параметры запроса, декодированные обратно к их исходным значениям, что позволяет легко определить, был ли амперсанд интерпретирован как разделитель или передан как буквальный символ.

Для ручного тестирования онлайн-инструмент для кодирования и декодирования URL позволяет вставить строку и увидеть, как выглядит закодированная форма — полезно для проверки значений перед вставкой в запрос. Инструмент

IO Tools URL Encoder/Decoder обрабатывает оба направления и показывает результат сразу. Кодирование URL: Что уходит в укрытие и почему ваш API ломается без этого 2

Хотите убрать рекламу? Откажитесь от рекламы сегодня

Установите наши расширения

Добавьте инструменты ввода-вывода в свой любимый браузер для мгновенного доступа и более быстрого поиска

в Расширение Chrome в Расширение края в Расширение Firefox в Расширение Opera

Табло результатов прибыло!

Табло результатов — это интересный способ следить за вашими играми, все данные хранятся в вашем браузере. Скоро появятся новые функции!

Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?
Реклама · УДАЛИТЬ?

новости с техническими моментами

Примите участие

Помогите нам продолжать предоставлять ценные бесплатные инструменты

Купи мне кофе
Реклама · УДАЛИТЬ?