URI.escape और CGI.escape में क्या अंतर है?


147

बीच क्या अंतर है URI.escapeऔर CGI.escapeऔर जो एक मैं इस्तेमाल करना चाहिए?

जवाबों:


124

कुछ छोटे अंतर थे, लेकिन महत्वपूर्ण बिंदु यह है कि रूबी 1.9.2 URI.escapeमें पदावनत किया गया है ... इसलिए उपयोग CGI::escapeया ERB :: Util.url_encode

रुचि रखने वालों के लिए रूबी-कोर पर एक लंबी चर्चा है जिसमें WEBrick :: HTTPUtils.escape और WEBrick :: HTTPUtils.escape_form का भी उल्लेख है ।


11
भ्रम को जोड़ने के लिए - मैंने बस stackoverflow.com/questions/4967608/… पर एक टिप्पणी देखी, जहाँ किसी ने उल्लेख किया था कि cgi से रिक्त स्थान के लिए% 20 के बजाय '+' का उपयोग होता है, और यह 'युक्ति' के खिलाफ है ...
लुईस सैयर्स

18
एक विकल्प है ERB::Util.url_encodeकि %20 रिक्त स्थान के लिए ठीक से उपयोग करता है
riffraff

1
@ अर्नेस्ट: देखें: github.com/ruby/ruby/commit/… (उत्तर अपडेट किया गया)
मार्क-आंद्रे लाफ्यून

4
ruby-doc.org/stdlib-2.0.0/libdoc/uri/rdoc/URI/Escape.html । रूबी 2.0.0 में URI.escape मॉड्यूल है। इसे अपदस्थ क्यों किया गया?
user938363

1
@ user938363 यदि आप शो स्रोत पर क्लिक करते हैं तो आप देखेंगे कि यह अभी भी पदावनत के रूप में चिह्नित है।
1

229

एक कुल्हाड़ी और एक तलवार के बीच क्या अंतर है और मुझे कौन सा उपयोग करना चाहिए? वैसे यह इस बात पर निर्भर करता है कि आपको क्या करना है।

URI.escapeएक स्ट्रिंग (URL) को एनकोड करना चाहिए था, इसलिए इसे " प्रतिशत-एन्कोडिंग " कहा जाता है ।

CGI::escapeसीजीआई युक्ति से आ रहा है , जो बताता है कि वेब सर्वर और एप्लिकेशन के बीच डेटा को कैसे इनकोड / डिकोड किया जाना चाहिए।

अब, मान लीजिए कि आपको अपने ऐप में URI से बचने की आवश्यकता है। यह अधिक विशिष्ट उपयोग का मामला है। उसके लिए, रूबी समुदाय URI.escapeवर्षों तक इस्तेमाल किया । इसके साथ समस्या URI.escapeयह थी कि यह RFC-3896 युक्ति को संभाल नहीं सका।

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 अप्रचलित के रूप में चिह्नित किया गया था:

इसके अलावा वर्तमान URI.encode सरल gsub है। लेकिन मुझे लगता है कि इसे यूआरआई को घटकों में विभाजित करना चाहिए, फिर प्रत्येक घटकों से बचना चाहिए, और अंत में उनसे जुड़ना चाहिए।

इसलिए वर्तमान URI.encode को हानिकारक और पदावनत माना जाता है। इसे हटा दिया जाएगा या व्यवहार में भारी बदलाव किया जाएगा।

इस समय प्रतिस्थापन क्या है?

जैसा कि मैंने ऊपर कहा, वर्तमान URI.encode कल्पना के स्तर पर गलत है। इसलिए हम सटीक प्रतिस्थापन प्रदान नहीं करेंगे। इसके उपयोग के मामले में प्रतिस्थापन अलग-अलग होगा।

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

दुर्भाग्य से डॉक्स में इसके बारे में एक भी शब्द नहीं है, इसके बारे में जानने का एकमात्र तरीका स्रोत की जांच करना है, या स्क्रिप्ट को वर्बोस लेवल में चेतावनी के साथ चलाना है ( -wW2) (या कुछ google-fu का उपयोग करें)।

कुछ नेCGI::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::escapeकेवल क्वेरी पैरामीटर के लिए उपयोग किया जाना चाहिए, लेकिन परिणाम, फिर से, कल्पना के खिलाफ होगा। वास्तव में सबसे आम उपयोग-मामला फॉर्म डेटा से बच रहा है, जैसे कि application/x-www-form-urlencodedPOST अनुरोध भेजते समय ।

यह भी उल्लेख किया गया WEBrick::HTTPUtils.escapeहै कि इसमें बहुत सुधार नहीं हुआ है (फिर से यह सिर्फ एक सरल है gsub, जो है, IMO, इससे भी बुरा विकल्प 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" 

पता करने के लिए सबसे करीबी पता लगने योग्य मणि है:

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"

ध्यान दें, कि पिछले सभी विकल्पों के विपरीत, पता योग्य बच नहीं सकता है #, और यह अपेक्षित व्यवहार है। आप #हैश को URI पथ में रखना चाहते हैं, लेकिन URI क्वेरी में नहीं।

एकमात्र समस्या यह है कि हमने अपने क्वेरी मापदंडों को ठीक से नहीं छोड़ा, जो हमें निष्कर्ष पर लाता है: हमें पूरे यूआरआई के लिए एक भी विधि का उपयोग नहीं करना चाहिए, क्योंकि कोई भी सही समाधान नहीं है (अब तक)। जैसा कि आप देख रहे हैं कि &"मेरा ब्लॉग और आपका ब्लॉग" से बच नहीं गया था। हमें क्वेरी परम के लिए भागने के एक अलग रूप का उपयोग करने की आवश्यकता है, जहां उपयोगकर्ता अलग-अलग वर्ण रख सकते हैं जिनका URL में एक विशेष अर्थ है। URL एनकोड दर्ज करें। URL एन्कोड का उपयोग प्रत्येक "संदिग्ध" क्वेरी मान के लिए किया जाना चाहिए, जो ERB::Util.url_encodeजैसा करता है:

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

यह अच्छा है, लेकिन हमें पहले ही पता करने की आवश्यकता है:

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"

निष्कर्ष:

  • उपयोग URI.escapeया समान न करें
  • उपयोग करें CGI::escapeयदि आपको केवल फॉर्म एस्केप की आवश्यकता है
  • यदि आपको यूआरआई के साथ काम करने की आवश्यकता है, तो एड्रेसेबल का उपयोग करें, यह URL एन्कोडिंग प्रदान करता है, एन्कोडिंग बनाता है और URL को सामान्य करता है।
  • यदि यह एक रेल परियोजना है, तो यह देखें कि " मैं कैसे एक स्ट्रिंग में URL से बच सकता हूं? "

जानकारी के लिए बहुत शुक्रिया। यह यकीन है कि कुछ कुदाल परीक्षण चेतावनी से छुटकारा मिल गया। नीचे एक रेक और कुदाल दिखाई देती है।
डगलस जी। एलन

महान स्पष्टीकरण @Ernest, लेकिन इसके साथ समस्या यह है कि यह बाहरी URL के लिए काम नहीं करेगा जिसे मैं बनाने की कोशिश नहीं कर रहा हूं (और इसका कोई नियंत्रण नहीं है)। उदाहरण के लिए, क्रॉलर जो एक वेब पेज से URL पढ़ता है, और फिर उन URL तक पहुंचने की कोशिश करता है (जिन्हें एक्सेस करने से पहले इनकोड करना पड़ता है)।
amit_saxena

@amit_saxena यदि आप होने बर्दाश्त कर सकते हैं Addressableअपने जवाहरात के रूप में, तो आप URL पहले पार्स सकता है, इंटरनेट rubydoc.info/gems/addressable/Addressable/URI.heuristic_parse
अर्नेस्ट

दिलचस्प! लेकिन फिर, मैं मूल यूआरएल से इस का उपयोग करते हुए मापदंडों का हैश नहीं प्राप्त कर सकता हूं, जो कि मैं तब वर्णन करता हूं जैसा कि आप वर्णन करते हैं। मेरे मामले में प्रवाह यह है: मुझे कुछ फीड से बाहरी यूआरएल मिलते हैं -> जिसे मुझे फिर से एनकोड करना होगा -> कंटेंट लाने के लिए http क्लाइंट को पास करें। अब अगर मैं बाहरी यूआरएल को ठीक से एनकोड नहीं करता हूं, तो रूबी आधारित HTTP क्लाइंट अमान्य URI त्रुटियों के साथ विफल हो जाते हैं।
अमित_सक्सेना

@amit_saxena पार्स विधि का उदाहरण वापस आ जाएगा Addressable:URL, आप फिर उस पर सभी इंस्टेंस विधियों को कॉल कर सकते हैं, हो सकता है कि उनमें से कोई भी आपको वांछित परिणाम मिले: rubydoc.info/gems/addressable/Addressable/URI
अर्नेस्ट


6

CGI::escapeपाठ खंड से बचने के लिए अच्छा है, ताकि उन्हें url क्वेरी मापदंडों ('?' के बाद के तार) में उपयोग किया जा सके। उदाहरण के लिए यदि आप url में स्लैश कैरेक्टर वाले पैरामीटर को रखना चाहते हैं, तो आप CGI :: उस स्ट्रिंग को पहले छोड़ दें और फिर उसे url में डालें।

हालाँकि रेल में आप शायद इसका सीधा उपयोग नहीं करेंगे। आमतौर पर आप उपयोग करते हैं hash.to_param, जो CGI::escapeहुड के नीचे उपयोग करेगा ।


URI::escapeएक url से बचने के लिए अच्छा है जो ठीक से बच नहीं पाया था। उदाहरण के लिए कुछ वेबसाइटें अपने एंकर टैग में गलत / अनसैप्ड url आउटपुट करती हैं। यदि आपका प्रोग्राम अधिक संसाधन लाने के लिए इन यूआरएल का उपयोग करता है, तो OpenURI शिकायत करेगा कि यूआरएल अमान्य हैं। आपको URI::escapeइसे एक मान्य url बनाने के लिए आवश्यक है । इसलिए इसे उचित बनाने के लिए पूरे यूआरआई स्ट्रिंग से बचने के लिए इसका उपयोग किया जाता है। मेरे शब्द में URI :: unescape मानव द्वारा एक यूआरएल को पठनीय बनाता है, और URI :: एस्केप इसे ब्राउज़रों के लिए वैध बनाता है।

ये मेरे आम आदमी के शब्द हैं और उन को सही करने के लिए स्वतंत्र महसूस करते हैं।


1

अंतर यह है कि URI.escape काम नहीं कर रहा है ...

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

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

2
आपने गलत परीक्षण मामले को चुना .. 's'? 'S और =' सभी मान्य URI का हिस्सा हैं और इस तरह से बच नहीं गए हैं। अन्य वर्ण जिन्हें विशेष रूप से क्वेरी स्ट्रिंग में भाग जाने की आवश्यकता होती है।
गेरार्ड ओनली

@Gerardoneill मैंने URI.escape काम नहीं कर रहा है और अविश्वसनीय नहीं है, यह दिखाने के लिए परीक्षण मामले को ठीक से चुना। क्या आप सुझाव दे रहे हैं कि URI.escape केवल क्वेरी स्ट्रिंग से बच रहा है? यह कैसे बता सकता है कि जब मैं वहां a & encode करना चाहता हूं तो पैरामीटर मान समाप्त कैसे हो जाता है? शायद इसलिए यह अप्रचलित है?
रादु सिमियोनेस्कु

1
बिलकुल यही मैं कह रहा हूं। URI एस्केप को URL को पार्स करना है, जो अलग-अलग लगता है कि अलग-अलग पैरामीटर हैं, उन्हें छोड़ दें, और उन्हें वापस एक साथ रखें। यहां तक ​​कि गड़बड़ भी हो सकती है। लेकिन यह ऐसा नहीं करता है - यह केवल कुछ पात्रों को बचकर भागने से बचता है, जो इसे अधूरा बना देता है। इसका उपयोग सरल मामलों के लिए किया जा सकता है, खासकर यदि आप जानते हैं कि आपके पैरामीटर नहीं होंगे .. भ्रामक।
गेरार्ड ओनली

0

CGI.escape क्वेरी स्ट्रिंग में URL मान से बचने के लिए है। सभी वर्ण जो अल्फा, DIGIT, '_', '-', '' में नहीं आते हैं। और '' वर्ण सेट बच गए हैं।

लेकिन यह URL को गलत बना देगा, क्योंकि url के लिए '/', ':', ';', '[', '&', '=', और ';' का होना आवश्यक है। शायद इससे ज्यादा मैं अपने सिर के ऊपर से नहीं सोच सकता।

URI.escape उन URL वर्णों को अकेला छोड़ देता है, और भागने के लिए क्वेरी स्ट्रिंग कुंजियों और मानों को खोजने का प्रयास करता है। हालांकि यह वास्तव में पर निर्भर नहीं किया जा सकता है क्योंकि मूल्यों में सभी प्रकार के वर्ण हो सकते हैं जो एक आसान भागने से रोकते हैं। असल में, बहुत देर हो चुकी है। लेकिन यदि URL को सरल होने के लिए (मूल्यों में कोई '&' = 's') पर निर्भर किया जा सकता है, तो इस फ़ंक्शन का उपयोग शायद अपठनीय या अवैध वर्णों से बचने के लिए किया जा सकता है।

सामान्य तौर पर - हमेशा 'और' के साथ जुड़ने और '?' के बाद उन्हें जोड़ने से पहले व्यक्तिगत कुंजी और मूल्यों पर CGI.escape का उपयोग करें।


0

CGI.escape ने OpenProject API के साथ काम नहीं किया। इसने एनकोड किया [], और नहीं +। मैंने इसे एक साथ हैक किया जो ओपनप्रोजेक्ट के एपीआई के लिए अब तक काम करता है। लेकिन मुझे यकीन है कि यह कुछ गायब है। यह लगभग URI.escape के रूप में खराब होने की संभावना है, लेकिन यह आपको अप्रचलित त्रुटियों को नहीं देगा।

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\"]")

दोनों आउटपुट:

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

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.