आँकड़ों और विज्ञापन के लिए कुकीज़
हम आँकड़ों और विज्ञापन के लिए कुकीज़ इस्तेमाल करते हैं, दोनों Google को जाती हैं। मना करने से आपको दिखने वाली किसी चीज़ में कोई फ़र्क़ नहीं पड़ता।निजता पेज पढ़ें
कोई स्ट्रिंग चिपकाइए और उसे URL में इस्तेमाल के लिए percent-escaped रूप में पाइए। जो एक फ़ैसला सचमुच मायने रखता है वह अंदाज़े से तय होने के बजाय आपके सामने विकल्प के रूप में रखा जाता है: आप किसी पते के भीतर जाने वाला मान encode कर रहे हैं, या पूरा पता जिसकी तिरछी लकीरें और प्रश्नचिह्न ढाँचा हैं और जिन्हें बचना है। जो इन दोनों को गड्डमड्ड कर देता है उसे ऐसी URL मिलती है जो ठीक दिखती है और कहीं और ले जाती है।
कहाँ चलता है
कुछ भी अपलोड नहीं होता, क्योंकि कोई फ़ाइल है ही नहीं — गणना इसी पन्ने में होती है।
न कतार, न खाता
यह उतनी ही तेज़ी से जवाब देता है जितनी आपकी मशीन देती है, और कभी नहीं पूछता कि आप कौन हैं।
जितनी बार चाहें
न कुछ गिना जाता है, न कोई सीमा है — दोबारा जवाब देने में हमारा कुछ ख़र्च नहीं होता।
URL हिस्सों से बनी होती है, और जो अक्षर उन हिस्सों को अलग करते हैं — `/`, `?`, `&`, `=`, `#` — वे उस भूमिका में होने पर ढाँचा हैं और बाक़ी जगह डेटा। पूरे पते को encode करते समय उन्हें छोड़ना ही पड़ता है वरना वह पता रह ही नहीं जाता; किसी अलग मान को encode करते समय उन्हें escape करना ही पड़ता है वरना मान वहीं ख़त्म होकर कुछ और शुरू हो जाता है।
यही ठीक-ठीक `encodeURI` और `encodeURIComponent` का फ़र्क़ है, और वेब पर टूटे हुए redirect पैरामीटरों की अधिकांश संख्या यहीं से आती है: कोई `?wapas=https://udaharan.example/a?b=c`, जहाँ दूसरा प्रश्नचिह्न कभी escape नहीं हुआ, इसलिए उसके बाद का सब कुछ बाहरी URL का हिस्सा बन जाता है। लिंक जाँच में चलता है, जहाँ मंज़िल के पास query string नहीं होती, और उत्पादन में विफल होता है, जहाँ होती है।
Percent की शृंखला एक `%` और उसके बाद दो hexadecimal अंक होती है, और वह एक बाइट बताती है। ASCII से बाहर के अक्षरों को कई शृंखलाएँ चाहिए, और देवनागरी को हमेशा तीन, क्योंकि UTF-8 उसे तीन बाइट में लिखता है: «क» `%E0%A4%95` है।
गिनती चौंकाती है: «नमस्ते» छह code point हैं, इसलिए 18 percent शृंखलाएँ, यानी 54 अक्षर। जिन जगहों पर URL की लंबाई की कोई सीमा टकराती है — पुराने proxy, कुछ लॉग-तंत्र, कुछ ईमेल क्लाइंट — वहाँ हिंदी खोज-शब्द वाला पता उतने ही अंग्रेज़ी शब्दों वाले पते से कई गुना लंबा हो जाता है, और यह वह बात है जो अंग्रेज़ी में जाँची गई सीमा कभी नहीं दिखाती।
`encodeURIComponent` विस्मयादिबोधक चिह्न, उर्ध्वल्पविराम, दोनों कोष्ठक और तारांकन को escape किए बिना छोड़ देता है। RFC 3986 इन्हें आरक्षित मानता है, इसलिए सख़्ती से मानक का पालन करने वाला encoder इन्हें escape करता है — और दोनों की असहमति ठीक इन पाँच अक्षरों पर होती है, जो साधारण टेक्स्ट में लगातार आते हैं।
फ़र्क़ तभी दिखता है जब बीच में कोई हस्ताक्षर हो। OAuth 1.0 और AWS Signature version 4 encode की गई स्ट्रिंग पर hash निकालते हैं, इसलिए बिना escape हुआ एक अकेला उर्ध्वल्पविराम hash बदल देता है और रिक्वेस्ट मना कर दी जाती है — ऐसी त्रुटि के साथ जो credentials की बात करती है और आपको ग़लत जगह ढूँढ़ने भेज देती है। यहाँ का सख़्त विकल्प पाँचों को escape करता है।
दोनों दिखते हैं और दोनों एक ही नियम से नहीं आते। `%20` percent encoding है और URL के किसी भी हिस्से में सही है। Plus का चिह्न `application/x-www-form-urlencoded` से आता है, यानी उस रूप से जिसमें HTML का फ़ॉर्म भेजता है, जहाँ स्पेस `+` लिखा जाता है — मौजूदा विनिर्देश से पुरानी परिपाटी, जो इसलिए बची हुई है कि फ़ॉर्म आज भी ऐसा ही करते हैं।
Path में `+` सचमुच plus होता है। Query string में लगभग हर सर्वर उसे स्पेस पढ़ता है, क्योंकि फ़ॉर्म वाली encoding ऐसा कहती है — इसलिए किसी query मान में असली plus को `%2B` लिखना पड़ता है, वरना वह ग़ायब हो जाता है। यह encoder `%20` बनाता है, जो दोनों जगहों में से किसी में भी दुविधा भरा नहीं है।
पहले से encode की गई स्ट्रिंग को दोबारा encode करने पर ख़ुद `%` escape हो जाता है, इसलिए `%20` `%2520` बन जाता है। इसमें शामिल किसी भी हिस्से के लिए यह त्रुटि नहीं है — यह «%20» टेक्स्ट का पूरी तरह वैध encoding है — और इसीलिए दोहरी encoding उस बिंदु तक बची रहती है जहाँ कोई उपयोक्ता किसी शीर्षक में `नमस्ते%20दुनिया` पढ़ता है।
संकेत यह है कि जहाँ `%` होना चाहिए वहाँ `%25` दिखे। ऐसा दिखे तो आपकी शृंखला में कहीं कोई चीज़ पहले से encode हुए मान को दोबारा encode कर रही है, आम तौर पर इसलिए कि कोई framework यह आपके लिए कर देता है और कोई template उसे दोहरा देता है। हल यह है कि दोनों में से एक जगह हटाई जाए, न कि आख़िर में दो बार decode कर दिया जाए।
अक्षर, अंक और चार चिह्न `-`, `_`, `.` और `~` को RFC 3986 «unreserved» कहता है और इन्हें कभी escape नहीं किया जाना चाहिए। जो encoder बिंदु की जगह `%2E` बनाता है वह ज़्यादा सख़्त नहीं है: वह ग़लत है, क्योंकि कुछ तंत्र उसे वापस सामान्य कर देते हैं और कुछ नहीं, और इस तरह दो URL जिन्हें एक ही होना चाहिए था अलग हो जाती हैं।
व्यवहार में: जब टेक्स्ट ज़्यादातर अक्षरों का हो और encode की गई स्ट्रिंग में बेहिसाब percent शृंखलाएँ दिखें, तो वह आम तौर पर ज़रूरत से ज़्यादा encode करने वाले औज़ार से आई होती है। यह तब तक निरापद है जब तक कोई उस पर हस्ताक्षर या cache key न निकाले — और तब यही वजह होती है कि दो तंत्रों की बात नहीं बनती।
JavaScript का पुराना `escape()` फलन देवनागरी के लिए percent शृंखलाएँ बनाता ही नहीं। वह `%u0915` जैसा कुछ बनाता है, यानी अक्षर का code point सीधे लिख देता है। यह रूप किसी भी URL मानक में नहीं है; इसे कोई सर्वर decode नहीं करता, और यह किसी लॉग में साबुत पड़ा रह जाता है।
यह अब भी दिखता है क्योंकि पुराने पन्नों का JavaScript बदला नहीं गया। अगर आपके किसी पैरामीटर में `%u` दिखे तो निदान पूरा हो चुका: वह मान `escape()` से निकला है और उसे `encodeURIComponent` से निकलना चाहिए। यह पन्ना हमेशा UTF-8 वाली percent शृंखलाएँ बनाता है, यानी हिंदी अक्षर के लिए तीन।
`#` के बाद की हर चीज़ ब्राउज़र में ही रह जाती है। वह किसी रिक्वेस्ट में नहीं दिखती, किसी सर्वर तक नहीं पहुँचती और किसी access log में दर्ज नहीं होती। यह HTTP का गुण है, कोई निजता-सुविधा नहीं, और यह दोनों तरफ़ काटता है।
यह काम का है क्योंकि fragment में रखा मान सर्वर तक नहीं जाता — ऐतिहासिक रूप से यही वजह थी कि OAuth के token वहीं सफ़र करते थे। यह असुविधाजनक है क्योंकि वह फिर भी ब्राउज़र के इतिहास में, कुछ स्क्रिप्टों की referrer-शृंखला में और साझा किए गए हर लिंक में रह जाता है। «सर्वर तक नहीं पहुँचता» का मतलब «निजी है» नहीं होता।
देवनागरी वाला डोमेन escape नहीं होता: वह Punycode में बदलता है। `भारत.example` `xn--h2brj9c.example` बन जाता है, और यही वह रूप है जो DNS में सचमुच मौजूद है, क्योंकि नाम-तंत्र सिर्फ़ ASCII जानता है।
जो encoder host को किसी मान की तरह बरतता है वह ऐसा पता बनाता है जिसे कोई DNS हल नहीं करता। इसीलिए यहाँ पूरे पते वाला तरीक़ा host को हाथ नहीं लगाता — और इसीलिए, अगर आप देवनागरी डोमेन वाली URL जोड़ रहे हैं, तो host का रूपांतरण अलग क़दम है, इस क्रिया का हिस्सा नहीं। भारत में `.भारत`, `.भारतम्` और दूसरी लिपियों वाले IDN चलन में हैं, इसलिए यह यहाँ अपवाद जितना दुर्लभ नहीं है।
जो encode होता है वह आम तौर पर किसी URL में जाकर बैठता है, और URL सर्वर के लॉग में, ब्राउज़र के इतिहास में और अगले क्लिक के referrer हेडर में रह जाती हैं। अगर मान में कोई ईमेल, कोई पहचान-संख्या या कोई निजी खोज-शब्द है, तो इस्तेमाल होते ही वह कई जगह पहुँच चुका होता है।
यह पन्ना जो हिस्सा हल करता है वह यह है कि encoding आपके डिवाइस पर होती है: वह मान हम तक नहीं पहुँचता। जो हिस्सा यह हल नहीं कर सकता वह कहने लायक़ है — निजी डेटा के अनजाने में दर्ज हो जाने की सबसे आम जगह URL का कोई पैरामीटर ही है।
अगर टेक्स्ट किसी पते के भीतर जाने वाला मान है तो पहला: वह ? & = / और # को escape करता है। अगर वह पूरा पता है तो दूसरा, जो उन्हें रहने देता है क्योंकि वहाँ वे ढाँचा हैं। तीसरा तभी चाहिए जब बीच में कोई हस्ताक्षर हो।
क्योंकि percent encoding बाइट ले जाती है और UTF-8 देवनागरी को तीन बाइट में लिखता है: «क» %E0%A4%95 है। इसीलिए हिंदी खोज-शब्द वाली URL अंग्रेज़ी वाली से कई गुना लंबी हो जाती है।
कि वह दो बार encode हो चुकी है: %20 दोबारा किसी encoder से गुज़रा और उसका % escape हो गया। हल यह है कि दो चरणों में से एक हटाया जाए, न कि आख़िर में दो बार decode किया जाए।
%20 URL के हर हिस्से में सही है। + का मतलब स्पेस सिर्फ़ query string में होता है, फ़ॉर्म वाली encoding की विरासत से; path में plus सचमुच plus है। यहाँ %20 बनता है, जो दुविधा भरा नहीं है।
नहीं। Encoding इसी पन्ने पर होती है। पर यह ध्यान रखिए कि URL इस्तेमाल हो जाने के बाद वह मान सर्वर के लॉग में, इतिहास में और referrer हेडर में रह जाता है।