В чем разница между URI.escape и CGI.escape? - PullRequest
135 голосов
/ 13 мая 2010

В чем разница между URI.escape и CGI.escape и какую мне использовать?

Ответы [ 6 ]

208 голосов
/ 25 октября 2012

Какая разница между топором и мечом, и какой мне следует использовать? Ну, это зависит от того, что вам нужно сделать.

URI.escape должен был закодировать строку (URL) в так называемое " Процентное кодирование ".

CGI::escape взято из спецификации CGI , которая описывает, как данные должны кодироваться / декодироваться между веб-сервером и приложением.

Теперь, допустим, вам нужно экранировать URI в вашем приложении. Это более конкретный вариант использования. Для этого сообщество Ruby годами использовало URI.escape. Проблема с URI.escape заключалась в том, что он не мог обработать спецификацию RFC-3896.

URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog"

URI.escape помечен как устаревший:

Более того, текущий URI.encode - это простой gsub. Но я думаю, что это должно разделить URI на компоненты, затем экранировать каждый компонент и, наконец, присоединяйтесь к ним.

Таким образом, текущий URI.encode считается вредоносным и устаревшим. Это будет быть удаленным или радикально изменить поведение.

Какая замена в это время?

Как я уже говорил выше, текущий URI.encode неверен на уровне спецификации. Итак, мы не предоставит точную замену. Замена будет варьироваться в зависимости от его случай использования.

https://bugs.ruby -lang.org / вопросы / 4167

К сожалению, в документации нет ни единого слова об этом, единственный способ узнать об этом - проверить исходный код или запустить скрипт с предупреждениями на подробном уровне (-wW2) (или использовать какой-нибудь google-fu ).

Некоторые предложили использовать CGI::Escape для параметров запроса, потому что вы не смогли экранировать весь URI:

CGI::escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http%3A%2F%2Fgoogle.com%2Ffoo%3Fbar%3Dat%23anchor%26title%3DMy+Blog+%26+Your+Blog"

CGI::escape следует использовать только для параметров запроса, но результаты снова будут соответствовать спецификации. На самом деле наиболее распространенным вариантом использования является экранирование данных формы, например, при отправке application/x-www-form-urlencoded запроса POST.

Также упомянуто WEBrick::HTTPUtils.escape не так много улучшений (опять же, это просто gsub, что, IMO, даже хуже, чем URI.escape):

WEBrick::HTTPUtils.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog" 

Наиболее близким к спецификации является Addressable gem:

require 'addressable/uri'
Addressable::URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at#anchor&title=My%20Blog%20&%20Your%20Blog"

Обратите внимание, что в отличие от всех предыдущих опций Addressable не экранируется #, и это ожидаемое поведение. Вы хотите сохранить хэш # в пути URI, но не в запросе URI.

Единственная оставшаяся проблема заключается в том, что мы не экранировали параметры нашего запроса должным образом, что приводит нас к выводу: нам не следует использовать один метод для всего URI, поскольку не существует идеального решения (пока). Как видите, & не сбежал из "Моего блога и вашего блога". Нам нужно использовать другую форму экранирования для параметров запроса, где пользователи могут помещать в URL разные символы, которые имеют особое значение. Введите URL кодировать. URL-кодирование должно использоваться для каждого «подозрительного» значения запроса, аналогично тому, что делает ERB::Util.url_encode:

ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""

Это круто, но мы уже требовали Адрес:

uri = Addressable::URI.parse("http://www.go.com/foo")
# => #<Addressable::URI:0x186feb0 URI:http://www.go.com/foo>
uri.query_values = {title: "My Blog & Your Blog"}
uri.normalize.to_s
# => "http://www.go.com/foo?title=My%20Blog%20%26%20Your%20Blog"

Вывод:

  • Не использовать URI.escape или аналогичный
  • Используйте CGI::escape, если вам нужен только escape-код
  • Если вам нужно работать с URI, используйте Addressable, он предлагает кодировку URL, кодирование формы и нормализует URL.
  • Если это проект Rails, посмотрите " Как мне URL-экранировать строку в Rails? "
119 голосов
/ 14 мая 2010

Были небольшие отличия, но важно отметить, что URI.escape был устарел в Ruby 1.9.2 ... поэтому используйте CGI::escape или ERB :: Util.url_encode .

Существует долгое обсуждение по ядру ruby ​​ для тех, кто заинтересован, в котором также упоминаются WEBrick :: HTTPUtils.escape и WEBrick :: HTTPUtils.escape_form .

9 голосов
/ 13 мая 2010

URI.escape принимает второй параметр, который позволяет пометить, что небезопасно. Смотрите APIDock:

http://apidock.com/ruby/CGI/escape/class

http://apidock.com/ruby/URI/Escape/escape

6 голосов
/ 06 января 2012

CGI::escape подходит для экранирования текстового сегмента, поэтому его можно использовать в параметрах URL-запроса (строки после '?'). Например, если вы хотите, чтобы в URL был параметр, содержащий символы косой черты, вы CGI :: сначала экранируете эту строку, а затем вставляете ее в URL.

Однако в Rails вы, вероятно, не будете использовать его напрямую. Обычно вы используете hash.to_param, который будет использовать CGI::escape под капотом.


URI::escape хорош для экранирования URL, который не был экранирован правильно. Например, некоторые веб-сайты выводят неправильный / неэкранированный URL в своем теге привязки. Если ваша программа использует эти URL для получения большего количества ресурсов, OpenURI будет жаловаться на то, что URL недействительны. Вам нужно URI::escape сделать их действительными URL. Так что он используется для экранирования всей строки URI, чтобы сделать его правильным В моем слове URI :: unescape делает URL доступным для чтения человеком, а URI :: escape делает его действительным для браузеров.

Это термин моего непрофессионала, и не стесняйтесь их исправлять.

2 голосов
/ 02 ноября 2017

Разница в том, что URI.escape не работает ...

CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"

URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
0 голосов
/ 19 января 2019

CGI.escape предназначен для экранирования значения URL в строке запроса. Все символы, которые не попадают в ALPHA, DIGIT, '_', '-', '.' и набор символов '' экранирован.

Но это сделало бы URL неверным, так как URL должен иметь '/', ':', '?', '[', '&', '=' И ';'. Возможно, больше того, о чем я не могу думать с макушки головы.

URI.escape оставляет эти символы URL в покое и пытается найти ключи строки запроса и значения для экранирования. Однако это действительно не может зависеть, так как значения могут иметь всевозможные символы, предотвращающие легкий выход. По сути, уже слишком поздно. Но если URL-адрес может быть простым (без '&' и '=' и т. Д. В значениях), эта функция может использоваться для экранирования, возможно, нечитаемых или недопустимых символов.

В общем, всегда используйте CGI.escape для отдельных ключей и значений, прежде чем объединять их с '&' и добавлять их после '?'.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...