URL, Ruby'de bir dizeyi kodlar


135

Nasıl URI::encodebir dize gibi:

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

gibi bir biçimde almak için:

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

RFC 1738 uyarınca?

İşte denedim:

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

Ayrıca:

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

Her gün internete baktım ve bunu yapmanın bir yolunu bulamadım, ancak geçen gün bunu hiç sorunsuz bir şekilde yaptığımdan neredeyse eminim.


1
Ruby 1.9 kullanıyorsanız faydalı olabilir: yehudakatz.com/2010/05/05/…
apneadiving

Yanıtlar:


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')daha kendi kendini belgeleyen bir seçenek olabilir.
mu çok kısa

63
Bu yöntemi kullanımdan kaldırdılar, CGI.escapebunun yerine * * kullanın. -> http://www.ruby-forum.com/topic/207489#903709 . URI.www_form_encode* URI.www_form_encode_component* 'I da kullanabilmelisiniz , ama ben hiç kullanmadım
J-Rou

2
require 'open-uri'Burada gerek yok. Bunu mu demek istediniz require 'uri'?
pje

1
@ J-Rou, CGI.escape tüm URL'den kaçabilir, seçmeli olarak sorgu parametrelerinden 'a=&!@&b=&$^'kaçmaz , örneğin, CGI.escape'e geçerseniz sorgu ayırıcılarıyla her şeyden kaçar, &böylece bu sadece sorgu değerlerinde kullanılabilir. addressableGem kullanmanızı öneririm , URL'lerle daha entelektüel çalışmak.
Alexander.Iljushkin

Uzak sunucudaki dosyalara erişmem gerekiyordu. CGI ile kodlama işe yaramadı, ancak URI.encode işi gayet iyi yaptı.
1919'da

82

Günümüzde ERB::Util.url_encodeveya kullanmalısınız CGI.escape. Aralarındaki birincil fark, alanların kullanımıdır:

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

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

CGI.escapeCGI / HTML formları spesifikasyonunu izler ve size application/x-www-form-urlencodedboşlukların kaçmasını gerektiren bir dize +verirken ERB::Util.url_encode, RFC 3986'yı aşağıdaki gibi kodlanmasını gerektirir %20.

Daha fazla tartışma için bkz. " URI.escape ve CGI.escape arasındaki fark nedir? "


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"

@ J-Rou adlı kullanıcının yorumundan alındı


11

Bunun için Addressable::URIgem kullanabilirsiniz :

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" 

CGI.escapeÖrneğin, alanı işaret olarak %20değil, düzgün bir şekilde kodladığından daha modern bir format kullanır, daha fazla bilgiyi Wikipedia'da " application / x-www-form-urlencoded type " +da okuyabilirsiniz .

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" 

Ayrıca şunu da yapabilirsiniz: CGI.escape('Hello, this is me').gsub("+", "%20") => Hello%2C%20this%20is%20me"Herhangi bir mücevher kullanmak istemiyorsanız
Raccoon

5

Kodunuzda kullanmak için URI kodlama şeylerini daha temiz hale getirmek için bir mücevher oluşturdum. Sizin için ikili kodlama ile ilgilenir.

Çalıştır gem install uri-handler, sonra şunu kullan:

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"

String sınıfına URI dönüştürme işlevini ekler. Kullanmak istediğiniz isteğe bağlı kodlama dizesini içeren bir argüman da iletebilirsiniz. Düz UTF-8 kodlaması başarısız olursa, varsayılan olarak 'binary' kodlamasını ayarlar.


2

Kod:

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

Sonuç:

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

Alıcı sunucu eskiyse, CGI.escape'e iyi yanıt vermeyebilir. Bu hala geçerli bir alternatif.
cesartalves

2

Başlangıçta tam bir URL dizesinden değil, sadece bir dosya adında özel karakterler kaçmaya çalışıyordu.

ERB::Util.url_encode benim kullanım için işe yaramadı:

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

" Neden URI.escape () kullanılmıyor ve bu REGEXP :: UNSAFE sabiti nerede? " Sorusundaki iki cevaba dayanarak, URI::RFC2396_Parser#escapekullanmaktan daha iyidir URI::Escape#escape. Ancak, ikisi de bana aynı şekilde davranıyor:

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

Tam bir URL'yi manuel olarak farklı bölümlerine ayırmayı düşünmek zorunda kalmadan "kodlamak" istiyorsanız, aşağıdakileri kullandığım şekilde çalıştığını gördüm URI.encode:

URI.parse(my_url).to_s
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.