So codieren Sie eine Zeichenfolge in Ruby per URL

135

Wie mag ich URI::encodeeinen String wie:

\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a

um es in einem Format wie:

%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A

gemäß RFC 1738?

Folgendes habe ich versucht:

irb(main):123:0> URI::encode "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
ArgumentError: invalid byte sequence in UTF-8
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `gsub'
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:219:in `escape'
    from /usr/local/lib/ruby/1.9.1/uri/common.rb:505:in `escape'
    from (irb):123
    from /usr/local/bin/irb:12:in `<main>'

Ebenfalls:

irb(main):126:0> CGI::escape "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
ArgumentError: invalid byte sequence in UTF-8
    from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `gsub'
    from /usr/local/lib/ruby/1.9.1/cgi/util.rb:7:in `escape'
    from (irb):126
    from /usr/local/bin/irb:12:in `<main>'

Ich habe mich im Internet umgesehen und keinen Weg gefunden, dies zu tun, obwohl ich fast sicher bin, dass ich dies neulich ohne Probleme getan habe.

HRÓÐÓLFR
quelle
1
Vielleicht nützlich, wenn Sie Ruby 1.9 verwenden: yehudakatz.com/2010/05/05/…
apneadiving

Antworten:

179
str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".force_encoding('ASCII-8BIT')
puts CGI.escape str


=> "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A"
kain
quelle
2
force_encoding('binary')könnte eine selbstdokumentierendere Wahl sein.
Mu ist zu kurz
63
Sie haben diese Methode abgelehnt und CGI.escapestattdessen * * verwendet. -> http://www.ruby-forum.com/topic/207489#903709 . Sie sollten auch in der Lage sein, URI.www_form_encode* URI.www_form_encode_component* zu verwenden, aber ich habe diese nie verwendet
J-Rou
2
Keine Notwendigkeit require 'open-uri'hier. Meinten Sie require 'uri'?
pje
1
@ J-Rou, CGI.escape kann die gesamte URL 'a=&!@&b=&$^'maskieren. Es werden keine selektiven Abfrageparameter maskiert. Wenn Sie beispielsweise an CGI.escape übergeben, wird das Ganze mit Abfragetrennzeichen maskiert, &sodass dies nur zum Abfragen von Werten verwendet werden kann. Ich schlage vor, addressablegem zu verwenden, es ist intellektueller, mit URLs zu arbeiten.
Alexander.Iljushkin
Ich musste auf Dateien auf dem Remote-Server zugreifen. Das Codieren mit CGI hat nicht funktioniert, aber URI.encode hat einwandfrei funktioniert.
Tashows
82

Heutzutage sollten Sie ERB::Util.url_encodeoder verwenden CGI.escape. Der Hauptunterschied zwischen ihnen ist der Umgang mit Räumen:

>> ERB::Util.url_encode("foo/bar? baz&")
=> "foo%2Fbar%3F%20baz%26"

>> CGI.escape("foo/bar? baz&")
=> "foo%2Fbar%3F+baz%26"

CGI.escapefolgt der CGI / HTML-Formularspezifikation und gibt Ihnen eine application/x-www-form-urlencodedZeichenfolge, für die Leerzeichen maskiert werden müssen +, während RFC 3986ERB::Util.url_encode folgt , für die sie codiert werden müssen .%20

Weitere Informationen finden Sie unter " Was ist der Unterschied zwischen URI.escape und CGI.escape? ".

Jenner La Fave
quelle
70
str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a"
require 'cgi'
CGI.escape(str)
# => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A"

Entnommen aus dem Kommentar von @ J-Rou

Jared Beck
quelle
11

Sie können Addressable::URIEdelstein dafür verwenden:

require 'addressable/uri'   
string = '\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a'
Addressable::URI.encode_component(string, Addressable::URI::CharacterClasses::QUERY)
# "%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a%5Cxbc%5Cxde%5Cxf1%5Cx23%5Cx45%5Cx67%5Cx89%5Cxab%5Cxcd%5Cxef%5Cx12%5Cx34%5Cx56%5Cx78%5Cx9a" 

Es verwendet ein moderneres Format, als es CGI.escapebeispielsweise den Speicherplatz ordnungsgemäß %20als +Zeichen und nicht als Zeichen codiert. Weitere Informationen finden Sie unter " Die Anwendung / x-www-form-urlencoded type " auf Wikipedia.

2.1.2 :008 > CGI.escape('Hello, this is me')
 => "Hello%2C+this+is+me" 
2.1.2 :009 > Addressable::URI.encode_component('Hello, this is me', Addressable::URI::CharacterClasses::QUERY)
 => "Hello,%20this%20is%20me" 
Alexey Shein
quelle
Kann auch so machen: CGI.escape('Hello, this is me').gsub("+", "%20") => Hello%2C%20this%20is%20me"wenn du keine Edelsteine ​​verwenden willst
Waschbär
5

Ich habe ein Juwel erstellt, um die URI-Codierung für die Verwendung in Ihrem Code sauberer zu gestalten. Es kümmert sich um die binäre Codierung für Sie.

Führen Sie aus gem install uri-handlerund verwenden Sie dann:

require 'uri-handler'

str = "\x12\x34\x56\x78\x9a\xbc\xde\xf1\x23\x45\x67\x89\xab\xcd\xef\x12\x34\x56\x78\x9a".to_uri
# => "%124Vx%9A%BC%DE%F1%23Eg%89%AB%CD%EF%124Vx%9A"

Es fügt die URI-Konvertierungsfunktion der String-Klasse hinzu. Sie können ihm auch ein Argument mit der optionalen Codierungszeichenfolge übergeben, die Sie verwenden möchten. Standardmäßig ist die Codierung "binär" eingestellt, wenn die direkte UTF-8-Codierung fehlschlägt.

Foomip
quelle
2

Code:

str = "http://localhost/with spaces and spaces"
encoded = URI::encode(str)
puts encoded

Ergebnis:

http://localhost/with%20spaces%20and%20spaces
Thiago Falcao
quelle
Wenn der empfangende Server alt ist, reagiert er möglicherweise nicht gut auf CGI.escape. Dies ist immer noch eine gültige Alternative.
cesartalves
2

Ich habe ursprünglich versucht, Sonderzeichen nur in einem Dateinamen und nicht im Pfad aus einer vollständigen URL-Zeichenfolge zu entfernen.

ERB::Util.url_encode hat für meinen Gebrauch nicht funktioniert:

helper.send(:url_encode, "http://example.com/?a=\11\15")
# => "http%3A%2F%2Fexample.com%2F%3Fa%3D%09%0D"

Basierend auf zwei Antworten in " Warum ist URI.escape () als veraltet markiert und wo ist diese REGEXP :: UNSAFE-Konstante? " Scheint es URI::RFC2396_Parser#escapebesser zu sein als zu verwenden URI::Escape#escape. Beide verhalten sich für mich jedoch gleich:

URI.escape("http://example.com/?a=\11\15")
# => "http://example.com/?a=%09%0D"
URI::Parser.new.escape("http://example.com/?a=\11\15")
# => "http://example.com/?a=%09%0D"
Kangkyu
quelle
2

Wenn Sie eine vollständige URL "verschlüsseln" möchten, ohne darüber nachdenken zu müssen, sie manuell in ihre verschiedenen Teile aufzuteilen, habe ich festgestellt, dass Folgendes auf die gleiche Weise funktioniert wie früher URI.encode:

URI.parse(my_url).to_s
Glenn 'Devalias'
quelle