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.


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"

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? ".


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


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" 

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.


2

Code:

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

Ergebnis:

http://localhost/with%20spaces%20and%20spaces

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"

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
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.