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!
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
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
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.
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"
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).
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"
Code:
str = "http://localhost/with spaces and spaces"
encoded = URI::encode(str)
puts encoded
Résultat:
http://localhost/with%20spaces%20and%20spaces
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