web-dev-qa-db-fra.com

Ruby chaîne d'encodage d'URL

Comment puis-je URI :: encoder une chaîne comme:

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

Pour l'obtenir dans un format comme:

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

(selon RFC 1738)

Voici ce que j'ai essayé:

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>'

Aussi,

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>'

J'ai tout regardé sur Internet et je n'ai pas trouvé (ou plus probablement raté) une façon de le faire, bien que je sois presque certain que l'autre jour je l'ai fait sans problème.

Merci!

126
HRÓÐÓLFR
require 'uri'
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 URI::encode(str)

UPDATE: voir le commentaire ci-dessous chaîne d'encodage Ruby url

167
kain
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"

Tiré du commentaire de @ J-Rou

70
Jared Beck

De nos jours, vous devriez utiliser ERB::Util.url_encode ou CGI.escape. La principale différence entre eux est leur traitement des espaces:

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

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

CGI.escape suit le spéc. Formulaires CGI/HTML et vous donne une chaîne application/x-www-form-urlencoded, ce qui nécessite l'échappement d'espaces vers +, alors que ERB::Util.url_encode suit - RFC 3986 , ce qui nécessite de les coder comme %20.

Voir cette réponse pour plus de discussion.

68
Jenner La Fave

Vous pouvez utiliser Addressable::URI gem pour cela:

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" 

Il utilise un format plus moderne que CGI.escape, par exemple, il code correctement l'espace en tant que %20 et non en tant que signe +, vous pouvez en lire plus dans article de Wikipédia

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" 
8
Alexey Shein

J'ai créé un bijou pour rendre le matériel de codage uri plus propre à utiliser dans votre code. Il s'occupe de l'encodage binaire pour vous (ajouté quelques exemples dans le code ci-dessus).

Exécutez gem install uri-handler.

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"

Il ajoute la fonctionnalité de conversion uri à la classe String. Vous pouvez également lui transmettre un argument avec la chaîne de codage facultative que vous souhaitez utiliser (définit par défaut le codage "binaire" si le codage direct UTF-8 échoue).

5
foomip

J'essayais à l'origine d'échapper aux caractères spéciaux sur le nom de fichier uniquement (pas sur le chemin) de la chaîne d'URL complète. ERB::Util.url_encode n'a pas fonctionné pour mon usage.

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

Sur la base de 2 réponses de différents SO question , il semble que URI::RFC2396_Parser#escape soit préférable à l'utilisation de URI::Escape#escape. Cependant, ils se comportent tous les deux de la même manière.

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
kangkyu

Code:

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

Résultat:

http://localhost/with%20spaces%20and%20spaces
0
Thiago Falcao

Si vous voulez "encoder" une URL complète sans avoir à penser à la scinder manuellement en plusieurs parties, j'ai constaté que les opérations suivantes fonctionnaient de la même manière que j'avais l'habitude d'utiliser URI.encode:

URI.parse(my_url).to_s
0
Glenn 'devalias'