URI.escape ve CGI.escape arasındaki fark nedir?


150

Arasındaki fark nedir URI.escapeve CGI.escapeve hangisinin kullanmalıyım?

Yanıtlar:


125

Orada bazı küçük farklılıklar vardı, ama önemli bir nokta olduğunu URI.escapeedilmiştir kaldırılmış böylece kullanmak ... Ruby 1.9.2'de CGI::escapeveya ERB :: Util.url_encode .

WEBrick :: HTTPUtils.escape ve WEBrick :: HTTPUtils.escape_form'dan bahseden ilgilenenler için ruby-core üzerine uzun bir tartışma var .


11
Sadece kafa karışıklığını eklemek için - stackoverflow.com/questions/4967608/… üzerinde bir yorum gördüm, burada birisi cgi kaçışının boşluklar için% 20 yerine '+' kullandığını ve bunun 'spesifikasyona' aykırı olduğunu söyledi ...
Louis Sayers

19
boşluklar için ERB::Util.url_encodeuygun şekilde kullanılan bir alternatif kullanmaktır%20
riffraff

1
@Ernest: Bakınız: github.com/ruby/ruby/commit/… (cevap güncellendi)
Marc-André Lafortune

4
ruby-doc.org/stdlib-2.0.0/libdoc/uri/rdoc/URI/Escape.html . Ruby 2.0.0'da URI.escape modülü bulunmaktadır. Neden kullanımdan kaldırıldı?
user938363

1
@ user938363 oradaki şov kaynağına tıklarsanız, hala kullanımdan kaldırıldı olarak işaretlendiğini göreceksiniz.
2014

233

Balta ile kılıç arasındaki fark nedir ve hangisini kullanmalıyım? Peki bağlıdır yapmanız gereken ne.

URI.escape" Yüzde kodlama " olarak adlandırılan bir dizeyi (URL) kodlaması gerekiyordu .

CGI::escapeverilerin web sunucusu ile uygulama arasında nasıl kodlanması / kodunun çözülmesi gerektiğini açıklayan CGI spesifikasyonundan gelmektedir .

Şimdi, uygulamanızda bir URI'den kaçmanız gerektiğini varsayalım. Daha spesifik bir kullanım durumudur. Bunun için Ruby topluluğu URI.escapeyıllarca kullandı . Sorun URI.escape, RFC-3896 spesifikasyonunu işleyememesiydi.

URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog' 
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog"

URI.escape eski olarak işaretlendi:

Ayrıca mevcut URI.encode basit bir gsub'dur. Ancak bir URI'yi bileşenlere ayırması, ardından her bileşenden kaçması ve sonunda onlara katılması gerektiğini düşünüyorum.

Dolayısıyla, mevcut URI.encode zararlı kabul edilir ve kullanımdan kaldırılmıştır. Bu kaldırılacak veya davranışı büyük ölçüde değiştirecektir.

Şu anda değişiklik nedir?

Yukarıda söylediğim gibi, mevcut URI.encode spesifikasyon seviyesinde yanlış. Bu yüzden tam olarak değiştirmeyi sağlamayacağız. Değiştirme, kullanım durumuna göre değişecektir.

https://bugs.ruby-lang.org/issues/4167

Ne yazık ki dokümanlarda bununla ilgili tek bir kelime yok, bunu bilmenin tek yolu kaynağı kontrol etmek veya komut dosyasını ayrıntılı düzeyde ( -wW2) uyarılarla çalıştırmak (veya biraz google-fu kullanmak).

Bazıları , bir URI'nin tamamından kaçamadığınız için sorgu parametreleri için kullanmayı önerdiCGI::Escape :

CGI::escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http%3A%2F%2Fgoogle.com%2Ffoo%3Fbar%3Dat%23anchor%26title%3DMy+Blog+%26+Your+Blog"

CGI::escapeyalnızca sorgu parametreleri için kullanılmalıdır, ancak sonuçlar yine spesifikasyona aykırı olacaktır. Aslında en yaygın kullanım durumu, application/x-www-form-urlencodedPOST isteği gönderirken olduğu gibi form verilerinden kaçmaktır.

Ayrıca WEBrick::HTTPUtils.escapeçok fazla gelişme olmadığı da belirtildi (yine bu sadece basit gsub, yani IMO, daha da kötü bir seçenek URI.escape):

WEBrick::HTTPUtils.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at%23anchor&title=My%20Blog%20&%20Your%20Blog" 

Spesifikasyona en yakın olan Adreslenebilir mücevher gibi görünüyor :

require 'addressable/uri'
Addressable::URI.escape 'http://google.com/foo?bar=at#anchor&title=My Blog & Your Blog'
# => "http://google.com/foo?bar=at#anchor&title=My%20Blog%20&%20Your%20Blog"

Önceki tüm seçeneklerin aksine, Addressable'ın kaçmadığına #ve bunun beklenen davranış olduğuna dikkat edin. #karmayı URI yolunda tutmak, ancak URI sorgusunda tutmak istemezsiniz .

Geriye kalan tek sorun, sorgu parametrelerimizden düzgün bir şekilde kaçamadığımızdır, bu da bizi şu sonuca götürür: tüm URI için tek bir yöntem kullanmamalıyız, çünkü (şimdiye kadar) mükemmel bir çözüm yok. Gördüğünüz gibi &"Blogum ve Blogunuz" bölümünden kaçmadı. Sorgu parametreleri için, kullanıcıların URL'lere özel bir anlamı olan farklı karakterler koyabilecekleri farklı bir kaçış biçimi kullanmamız gerekir. URL kodlamasını girin. URL kodlaması, aşağıdakilere benzer şekilde her "şüpheli" sorgu değeri için kullanılmalıdır ERB::Util.url_encode:

ERB::Util.url_encode "My Blod & Your Blog"
# => "My%20Blod%20%26%20Your%20Blog""

Sorun değil, ancak Adreslenebilir'i zaten zorunlu tuttuk:

uri = Addressable::URI.parse("http://www.go.com/foo")
# => #<Addressable::URI:0x186feb0 URI:http://www.go.com/foo>
uri.query_values = {title: "My Blog & Your Blog"}
uri.normalize.to_s
# => "http://www.go.com/foo?title=My%20Blog%20%26%20Your%20Blog"

Sonuç:

  • URI.escapeVeya benzeri kullanmayın
  • CGI::escapeYalnızca form kaçışına ihtiyacınız varsa kullanın
  • URI'larla çalışmanız gerekiyorsa, Addressable'ı kullanın, URL kodlaması, form kodlaması sunar ve URL'leri normalleştirir.
  • Bu bir Rails projesiyse, " Rails'de bir dizenin URL çıkışını nasıl yaparım? "

Bilgi için çok teşekkürler. Kesinlikle bazı çapa testi uyarılarından kurtuldu. Tırmık ve çapa aşağıya bakıyor.
Douglas G. Allen

Harika bir açıklama @Ernest, ancak bununla ilgili sorun, oluşturmaya çalışmadığım (ve üzerinde kontrol sahibi olmadığım) harici URL'ler için çalışmamasıdır. örneğin, bir web sayfasından URL'leri okuyan ve ardından bu URL'lere erişmeye çalışan (erişimden önce kodlanması gereken) tarayıcılar.
amit_saxena

@amit_saxena Addressable, mücevherlerinizden birini karşılayabiliyorsanız , önce URL'yi ayrıştırabilirsiniz, fi rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
Ernest

İlginç! Ama yine, bunu kullanarak orijinal url'den bir parametre karması alamıyorum, daha sonra sizin tarif ettiğiniz gibi kodlayacağım. Benim durumumdaki akış şudur: Bazı beslemelerden harici url'ler alıyorum -> daha sonra bunu kodlamam gerekiyor -> içeriği getirmek için http istemcisine aktar. Şimdi, harici url'leri doğru şekilde kodlamazsam, Ruby tabanlı HTTP istemcileri geçersiz URI hataları ile başarısız oluyor.
amit_saxena

@amit_saxena ayrıştırma yöntemi, örneğini döndürür Addressable:URL, ardından tüm örnek yöntemlerini çağırabilirsiniz, belki bunlardan biri size istediğiniz sonuçları verir: rubydoc.info/gems/addressable/Addressable/URI
Ernest


6

CGI::escapemetin segmentinden çıkış yapmak için iyidir, böylece url sorgu parametrelerinde ('?' karakterinden sonraki dizeler) kullanılabilir. Örneğin, url'de eğik çizgi karakterleri içeren bir parametrenin olmasını istiyorsanız, önce bu dizeden CGI :: çıkış yaparsınız ve sonra onu url'ye eklersiniz.

Ancak Rails'de muhtemelen doğrudan kullanmayacaksınız. Genellikle kaputun altında hash.to_paramkullanacağınız kullanırsınız CGI::escape.


URI::escapedüzgün bir şekilde çıkış yapılmamış bir url'den kaçmak için iyidir. Örneğin, bazı web siteleri bağlantı etiketlerinde yanlış / çıkış karaktersiz url verir. Programınız daha fazla kaynak almak için bu url'leri kullanırsa, OpenURI url'lerin geçersiz olduğundan şikayet eder. URI::escapeGeçerli bir url yapmak için bunlara ihtiyacınız var . Dolayısıyla, onu düzgün hale getirmek için tüm URI dizesinden kaçmak için kullanılır. Benim sözüme göre URI :: unescape, bir url'yi insan tarafından okunabilir hale getirir ve URI :: escape onu tarayıcılar için geçerli kılar.

Bunlar benim meslekten olmayanların terimidir ve bunları düzeltmekte özgürsünüz.


1

Aradaki fark, URI.escape'in çalışmamasıdır ...

CGI.escape"/en/test?asd=qwe"
=> "%2Fen%2Ftest%3Fasd%3Dqwe"

URI.escape"/en/test?asd=qwe"
=> "/en/test?asd=qwe"

2
Yanlış test senaryosunu seçtiniz .. / 'ler,?' Ler ve = 'ler geçerli bir URI'nin parçasıdır ve bu nedenle kaçılmaz. Özellikle sorgu dizesinde öncelenmesi gereken diğer karakterler olmalıdır.
Gerard ONeill

@GerardONeill URI.escape'in nasıl çalışmadığını ve güvenilmez olduğunu göstermek için test senaryosunu tam olarak seçtim. URI.escape'in yalnızca sorgu dizesinden kaçtığını mı öneriyorsunuz? Orada bir & kodlamak istersem bir parametre değerinin ne zaman biteceğini nasıl anlayabilirim? belki de bu yüzden modası geçmiş?
Radu Simionescu

1
Ben de tam olarak bunu söylüyorum. URI kaçışının URL'yi ayrıştırması, tek tek parametreler olduğunu düşündüğü şeyleri ayırması, bunlardan kaçması ve onları tekrar bir araya getirmesi gerekir. Bu bile dağınık olabilir. Ancak bunu yapmaz - sadece geri kalanından kaçarken bazı karakterlerden kaçmayı önler, bu da onu eksik yapar. Özellikle parametrelerinizin kafa karıştırıcı olmayacağını biliyorsanız, basit durumlar için kullanılabilir.
Gerard ONeill

1

CGI.escape, sorgu dizesindeki bir URL değerinden kaçmak içindir. ALPHA, DIGIT, '_', '-', 'içine girmeyen tüm karakterler.' ve '' karakter kümesinden kaçılır.

Ancak, bir url'de '/', ':', '?', '[', '&', '=' Ve ';' olması gerektiğinden, bu URL'yi yanlış yapar. Belki de kafamın tepesinde düşünemediğimden daha fazlası.

URI.escape, bu URL karakterlerini olduğu gibi bırakır ve çıkış yapılacak sorgu dizesi anahtarlarını ve değerlerini bulmaya çalışır. Bununla birlikte, değerler kolay bir kaçışı engelleyen her türlü karaktere sahip olabileceğinden, buna gerçekten güvenilemez. Temel olarak, artık çok geç. Ancak URL'nin basit olmasına bağlı olabiliyorsa (değerlerde '&' ve '=' vb. Yok), bu işlev belki okunamayan veya geçersiz karakterlerden kaçmak için kullanılabilir.

Genel olarak - CGI.escape'i her zaman ayrı anahtarlar ve değerler üzerinde '&' ile birleştirmeden ve '?' İşaretinden sonra eklemeden önce kullanın.


0

CGI.escape, OpenProject API ile çalışmadı. + 'Yı değil [] ,: kodladı. OpenProject API'si için şimdiye kadar işe yarayacak gibi görünen bunu birlikte hackledim. Ama eminim bazı .gsub'ları eksiktir. Muhtemelen URI.escape kadar kötüdür, ancak size eski hataları vermez.

class XXX
      def self.encode(path)
        path, query = path.split("?", 2)
        return path if query.nil?
        query = CGI.escape(query).gsub("%3A", ":").gsub("%3D","=").gsub("%5B","[").gsub("%5D","]").gsub("%2C",",").gsub("+","%20")
        return [path,query].join("?")
      end
end

XXX.encode("http://test.com/some/path?query=[box: \"cart\"]")
URI.encode("http://test.com/some/path?query=[box: \"cart\"]")

Her iki çıktı:

=> " http://test.com/some/path?query=[box:%20%22cart%22] "
=> " http://test.com/some/path?query=[box:%20 % 22cart% 22] "

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.