Ответы:
Были некоторые небольшие различия, но важным моментом является то, что URI.escape
они устарели в Ruby 1.9.2 ... так что используйте CGI::escape
или ERB :: Util.url_encode .
Существует интересное обсуждение ruby-core для тех, кто интересуется, в котором также упоминаются WEBrick :: HTTPUtils.escape и WEBrick :: HTTPUtils.escape_form .
ERB::Util.url_encode
которое правильно использует %20
для пробелов
Какая разница между топором и мечом, и какой мне следует использовать? Ну, это зависит от того, что вам нужно сделать.
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 неверен на уровне спецификации. Поэтому мы не будем предоставлять точную замену. Замена зависит от варианта использования.
К сожалению, в документации нет ни единого слова об этом, единственный способ узнать об этом - проверить исходный код или запустить скрипт с предупреждениями в подробном уровне ( -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"
Наиболее близким к спецификации является адресуемый камень:
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
если вам нужна только форма escapeAddressable
качестве одного из ваших драгоценных камней, вы можете сначала проанализировать URL, fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Addressable:URL
, вы можете затем вызвать все методы экземпляра для него, возможно, один из них даст вам желаемые результаты: rubydoc.info/gems/addressable/Addressable/URI
URI.escape принимает второй параметр, который позволяет пометить, что небезопасно. Смотрите APIDock:
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 делает его действительным для браузеров.
Это термин моего непрофессионала, и не стесняйтесь их исправлять.
Разница в том, что URI.escape не работает ...
CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"
URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"
CGI.escape предназначен для экранирования значения URL в строке запроса. Все символы, которые не попадают в ALPHA, DIGIT, '_', '-', '.' и '' набор символов экранирован.
Но это сделало бы URL неверным, так как URL должен иметь '/', ':', '?', '[', '&', '=' И ';'. Возможно больше, что я не могу думать о макушке.
URI.escape оставляет эти символы URL в покое и пытается найти ключи строки запроса и значения, которые необходимо экранировать. Однако это действительно не может зависеть, так как значения могут иметь всевозможные символы, предотвращающие легкий выход. По сути, уже слишком поздно. Но если URL-адрес может быть простым (без '&' и '=' и т. Д. В значениях), эта функция может использоваться для экранирования, возможно, нечитаемых или недопустимых символов.
В общем, всегда используйте CGI.escape для отдельных ключей и значений, прежде чем объединять их с «&» и добавлять их после «?».
CGI.escape не работал с API OpenProject. Он закодировал [] ,: а не +. Я взломал это вместе, что, кажется, работает до сих пор для API OpenProject. Но я уверен, что в нем отсутствуют некоторые .gsub. Вероятно, он почти такой же плохой, как URI.escape, но он не даст вам устаревших ошибок.
class XXX
def self.encode(path)
path, query = path.split("?", 2)
return path if query.nil?
query = CGI.escape(query).gsub("%3A", ":").gsub("%3D","=").gsub("%5B","[").gsub("%5D","]").gsub("%2C",",").gsub("+","%20")
return [path,query].join("?")
end
end
XXX.encode("http://test.com/some/path?query=[box: \"cart\"]")
URI.encode("http://test.com/some/path?query=[box: \"cart\"]")
Оба вывода:
=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "