Сталкивались ли вы с одним из этих предупреждений в своем проекте Ruby 2.7.0?
warning: URI.escape is obsolete warning: URI.encode is obsolete
Узнай, как это исправить!
Немного истории
Ruby 2.7.0 показывает предупреждение при вызове URI.escape
или его псевдонима URI.encode
. Это может показаться новым устареванием, но факт в том, что эти методы были помечены как устаревшие уже ... более 10 лет назад! Если вам интересно, почему вы никогда раньше не сталкивались с предупреждением, вот ответ: раньше оно отображалось только в том случае, если вы запускали свой скрипт в подробном режиме, и это изменилось совсем недавно.
Так почему же URI.escape
вообще устарело?
Проблема с концепцией «экранирования URI» состоит в том, что URI состоит из многих компонентов (например, path
или query
), и мы не хотим таким же образом экранировать их. Например, в конце URI может появиться символ #
(когда он используется как то, что обычно называется привязкой, или, на языке URI - компонент fragment
), но когда тот же #
является частью ввода пользователя (например, в поисковом запросе), мы хотим его закодировать, чтобы обеспечить правильную интерпретацию. Точно так же, если значение строки запроса содержит другие зарезервированные символы, такие как =
или &
, мы действительно хотим их экранировать, чтобы они не интерпретировались неправильно как разделители, как если бы они использовались как зарезервированные символы.
URI.escape
полагается на простую gsub
операцию для всей строки и не делает различий между отдельными компонентами, что не учитывает сложности, подобные упомянутым выше.
Как это исправить?
Поскольку я не нашел существующего решения, которое при задании целой строки URI интерпретировало бы отдельные компоненты и самостоятельно применяло разные правила экранирования желаемым образом, я советую кодировать разные компоненты по отдельности. Наиболее распространенным (и наиболее чувствительным) вариантом использования, вероятно, является кодирование строки запроса в компоненте query
, поэтому я сосредоточусь на этом случае. И сам модуль Ruby URI
предоставляет два удобных метода, которые помогут нам в этом!
Процентное кодирование строки запроса
URI.encode_www_form_component(string, enc=nil)
Этот метод будет кодировать проценты каждого зарезервированного символа, оставляя неизменным только *, -, ., 0-9, A-Z, _, a-z
. Он также заменяет пробел на +
. Примеры:
Как видите, теперь мы можем безопасно создавать наши строки запроса со значениями, экранированными таким образом. Но если вам кажется, что это слишком большая ручная работа, есть удобный способ обработать весь запрос за вас. Представляем…
Немного другой интерфейс. Он принимает Enumerable
(обычно вложенный Array
или Hash
) и соответственно строит запрос. Он использует .encode_www_form_component
внутри, поэтому правила кодирования остаются прежними. Разница заключается в том, как вы ее используете. Примеры:
Довольно просто, не правда ли?
Проект Rails?
Hash#to_query
(также имеет псевдоним Hash.to_param
)
Rails расширяет класс Hash
этим удобным методом. Он вернет строку запроса в правильном формате с правильным кодированием значений там, где это необходимо.
(Обратите внимание, как он также сортирует ключи по алфавиту.)
Вы также можете передать этому методу необязательное пространство имен, которое будет заключать имена ключей в возвращаемую строку, в результате получится такой формат, как search[q]="how to speed up your CI?"
(но, очевидно, с процентной кодировкой):
Подводя итоги
Я надеюсь, что эта короткая статья прояснила любую путаницу, которая могла возникнуть у вас при кодировании ваших строк для использования в URI. Пожалуйста, дайте нам знать в комментариях, если вы используете какие-либо другие способы решения проблемы процентного кодирования в своих проектах Ruby / Rails!
И если ваш проект борется с медленными сборками CI, попробуйте Knapsack Pro, который может помочь вам решить эту проблему.
Первоначально опубликовано Шади Резеком на https://docs.knapsackpro.com 19 января 2020 г.