Сталкивались ли вы с одним из этих предупреждений в своем проекте 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 г.