एक वाक्य में
URL एन्कोडिंग, जिसका official नाम परसेंट-एन्कोडिंग है, एक ऐसा प्रोसेस है जो उन characters को, जिनका URL में कोई खास मतलब होता है या जो अमान्य होते हैं, एक सेफ और universally-understood फॉर्मेट में बदल देता है, ताकि उन्हें बिना किसी confusion के भेजा जा सके।
यह कौन-सी समस्या हल करता है
वेब के शुरुआती दिनों के उस आदिकालीन सूप में, ज़िंदगी आसान थी। URLs—या ज़्यादा व्यापक रूप से, URIs (Uniform Resource Identifiers)—को किसी रिसोर्स का पता लगाने के लिए एक साफ-सुथरे, अनुमानित तरीके के रूप में डिज़ाइन किया गया था। इसके निर्माताओं, जिनमें सर टिम बर्नर्स-ली भी शामिल थे, ने इस सिस्टम को एक सीमित कैरेक्टर सेट: ASCII की नींव पर बनाया था।
यह बहुत अच्छा काम करता था, जब तक आपको केवल http://example.com/reports/April.html जैसे पते की ज़रूरत होती थी। लेकिन जब चीज़ें और जटिल हो जाती हैं तो क्या होता है?
एक URL की बनावट पर विचार करें। इसके हिस्से होते हैं: एक स्कीम (http:), एक होस्ट (example.com), एक पाथ (/search), और शायद एक क्वेरी स्ट्रिंग (?q=dogs&cats)। कुछ कैरेक्टर इस नाटक में स्ट्रक्चरल डायरेक्टर की भूमिका निभाते हैं। कोलन (:) स्कीम को अलग करता है। स्लैश (/) पाथ के हिस्सों को अलग करता है। प्रश्न चिह्न (?) क्वेरी पैरामीटर शुरू करता है। एम्परसैंड (&) एक पैरामीटर को दूसरे से अलग करता है।
समस्या यहीं से शुरू होती है। क्या होगा अगर आप "C++ & C#" की लिटरल स्ट्रिंग खोजना चाहते हैं? यदि आप इसे बस एक URL में डाल देते हैं, तो आपको मिलता है .../search?q=C++ & C#। एक वेब सर्वर इसे देखता है और पूरी तरह से कन्फ्यूज हो जाता है। उसे लगता है कि क्वेरी "C++ " के लिए है, और फिर उसे एक एम्परसैंड दिखता है और वह एक और की-वैल्यू जोड़ी की उम्मीद करता है, लेकिन उसे बस एक अकेला " C#" मिलता है। अराजकता फैल जाती है। আসল मतलब खो जाता है।
इसके अलावा, कुछ कैरेक्टर्स की तो अनुमति ही नहीं है। स्पेस एक क्लासिक सिरदर्द है। कब एक स्पेस फ़ाइल नाम का हिस्सा है, और कब यह सिर्फ एक टाइपो है जिसे ब्राउज़र को अनदेखा कर देना चाहिए? और उन कैरेक्टर्स का क्या जो मूल अंग्रेजी वर्णमाला से बाहर हैं? वेब ग्लोबल है! आप Résumé.pdf या 你好.html को ASCII के लिए डिज़ाइन किए गए URL में कैसे डालेंगे?
परसेंट-एन्कोडिंग इस पूरी तरह की समस्याओं को हल करता है। यह एक 'escape hatch' (बचने का रास्ता) प्रदान करता है, यह कहने का एक तरीका है, "ऐ, मिस्टर वेब सर्वर, अगला कैरेक्टर या कैरेक्टर्स स्ट्रक्चरल नहीं हैं। उनकी व्याख्या मत करो। वे लिटरल डेटा हैं।" यह वह यूनिवर्सल ट्रांसलेटर है जो यह सुनिश्चित करता है कि एक URL का मतलब ब्राजील के ब्राउज़र में वही हो जो बर्लिन के सर्वर पर होता है।
पर्दे के पीछे यह कैसे काम करता है
परसेंट-एन्कोडिंग के पीछे का "जादू" आश्चर्यजनक रूप से सीधा है। यह एक जादू की चाल से ज़्यादा एक सरल प्रतिस्थापन सिफर (substitution cipher) है जिसे हर कोई उपयोग करने के लिए सहमत हो गया है।
कैरेक्टर्स की कास्ट: रिज़र्व्ड बनाम अनरिज़र्व्ड
सबसे पहले, आपको यह जानना होगा कि कौन से कैरेक्टर ठीक हैं और कौन से समस्याग्रस्त हैं। वे कुछ समूहों में आते हैं।
| Character का प्रकार | Characters | कब एन्कोड करें |
|---|---|---|
| Unreserved | A-Z a-z 0-9 - _ . ~ |
कभी नहीं। ये URL की दुनिया के VIPs हैं। वे हमेशा सुरक्षित होते हैं। |
| Reserved | : / ? # [ ] @ ! $ & ' ( ) * + , ; = |
कभी-कभी। इनका विशेष स्ट्रक्चरल अर्थ होता है। यदि आप उन्हें उनके अर्थ के लिए उपयोग करना चाहते हैं (जैसे पाथ में /), तो आप एन्कोड नहीं करते। यदि आप उन्हें लिटरल डेटा के रूप में उपयोग करना चाहते हैं (जैसे सर्च क्वेरी में &), तो आपको ज़रूर एन्कोड करना होगा। |
| अन्य (Unsafe) | (स्पेस), `< > " % { } \ |
^` और सभी नॉन-ASCII कैरेक्टर |
यहाँ मुख्य बात कॉन्टेक्स्ट है। कैरेक्टर ? ठीक है अगर यह वह एक ? है जो पाथ को क्वेरी स्ट्रिंग से अलग करता है। लेकिन अगर आपको क्वेरी पैरामीटर की वैल्यू के अंदर एक लिटरल प्रश्न चिह्न की आवश्यकता है, तो आपको इसे एन्कोड करना होगा।
जादू की चाल: परसेंट + हेक्स
एन्कोडिंग प्रक्रिया एक सरल तीन-स्टेप का डांस है:
- एक कैरेक्टर चुनें जिसे आपको एन्कोड करना है। चलिए एम्परसैंड
&का उपयोग करते हैं। - एक मानक कैरेक्टर सेट का उपयोग करके उसकी बाइट वैल्यू का पता लगाएं। वेब के लिए, यह मानक UTF-8 है। UTF-8 (और इसके पूर्ववर्ती ASCII) में,
&कैरेक्टर को दशमलव संख्या38द्वारा दर्शाया जाता है। - उस संख्या को दो-अंकीय हेक्साडेसिमल में बदलें और शुरू में एक परसेंट का चिह्न (
%) लगा दें। दशमलव38हेक्साडेसिमल में26होता है।
तो, & बन जाता है %26।
आइए कुछ और कोशिश करें:
- एक स्पेस दशमलव
32है, जो हेक्स20है। एन्कोड किया हुआ:%20। - एक प्रश्न चिह्न (
?) दशमलव63है, जो हेक्स3Fहै। एन्कोड किया हुआ:%3F। - परसेंट का चिह्न (
%) खुद दशमलव37, हेक्स25है। तो एक लिटरल%को एन्कोड करने के लिए, आप%25लिखते हैं।
यह सिस्टम शानदार है क्योंकि परसेंट का चिह्न खुद एक अनरिज़र्व्ड कैरेक्टर नहीं है, इसलिए एक पार्सर जानता है कि जब भी वह % देखता है, तो उसे दो हेक्स अंकों की उम्मीद करनी चाहिए।
नॉन-इंग्लिश कैरेक्टर्स का क्या?
यह वह जगह है जहाँ UTF-8 बहुत ज़रूरी हो जाता है। A जैसा एक साधारण ASCII कैरेक्टर एक बाइट का होता है। लेकिन फ्रेंच é या चीनी 好 जैसे कैरेक्टर को UTF-8 में कई बाइट्स द्वारा दर्शाया जाता है। एन्कोडिंग प्रक्रिया वही रहती है, बस प्रत्येक बाइट के लिए दोहराई जाती है।
आइए é को लेते हैं:
- UTF-8 में,
éको दो बाइट्स द्वारा दर्शाया जाता है:C3औरA9(हेक्स में)। - प्रत्येक बाइट को अलग-अलग एन्कोड करें:
C3बन जाता है%C3।A9बन जाता है%A9।
- उन्हें मिलाएं:
éबन जाता है%C3%A9।
डिकोडिंग प्रक्रिया इसका ठीक उलटा है। एक ब्राउज़र या सर्वर %C3%A9 देखता है, दो बाइट्स C3 और A9 को पकड़ता है, उन्हें UTF-8 डिकोडर से गुजारता है, और सुंदर é कैरेक्टर वापस पाता है।
असल दुनिया की कहानियाँ
थ्योरी बहुत अच्छी है, लेकिन चलिए देखते हैं कि यह असल में कहाँ काम आती है।
गायब हो जाने वाली सर्च क्वेरी का मामला
एक जूनियर डेवलपर, माया, एक तकनीकी दस्तावेज़ीकरण साइट के लिए एक सर्च फीचर बना रही थी। यूज़र्स "C++", "promises & async/await", जैसी चीज़ें खोज सकते थे। उसने बस स्ट्रिंग्स को जोड़कर सर्च URL बनाया: site.com/search?q= + userInput।
सब गड़बड़ हो गया। promises & async/await की खोज ने URL .../search?q=promises & async/await उत्पन्न किया। सर्वर ने, हालांकि, केवल खोज शब्द को "promises " के रूप में रिपोर्ट किया। & को एक नए पैरामीटर, async/await के लिए एक सेपरेटर के रूप में समझा गया, जिसे खारिज कर दिया गया क्योंकि इसमें कोई की (key) नहीं थी। उसके खोज परिणाम पूरी तरह से गलत थे।
सबक: माया ने वेब डेवलपमेंट का एक सुनहरा नियम सीखा: URL के किसी भी हिस्से में डाले जा रहे किसी भी डायनामिक डेटा को हमेशा परसेंट-एन्कोड करें। जब उसने यूज़र इनपुट को एन्कोड करना शुरू किया, तो URL सही ढंग से .../search?q=promises%20%26%20async%2Fawait बन गया। अब सर्वर को पूरी, सही स्ट्रिंग मिली, और सर्च ने पूरी तरह से काम किया।
अंतर्राष्ट्रीय घटना
एक ऑनलाइन स्टोर ने एक जर्मन पार्टनर से एक नया प्रोडक्ट प्रदर्शित करने का फैसला किया: "Fußball"। मार्केटिंग टीम ने इसके लिए एक फ्रेंडली URL बनाया: store.com/products/Fußball। ऑफिस में उनके आधुनिक ब्राउज़रों पर, सब कुछ ठीक लग रहा था।
लेकिन लॉन्च का दिन एक गड़बड़झाला था। कस्टमर सपोर्ट टिकटों की बाढ़ आ गई। कुछ यूज़र्स को "404 Not Found" एरर मिल रहे थे। दूसरों को उनके ब्राउज़र बार में .../products/Fu%C3%9Fball जैसा URL दिख रहा था, जबकि कुछ को .../products/FuÃball दिख रहा था। सिस्टम पुराने और नए कॉम्पोनेंट्स का एक पैचवर्क था, और वे नॉन-ASCII कैरेक्टर ß (Eszett) को लगातार सही ढंग से हैंडल नहीं कर रहे थे। कुछ हिस्से इसे एन्कोड नहीं करते थे, कुछ इसे UTF-8 मानकर एन्कोड करते थे, और कुछ पुराने सिस्टम इसे एक अलग कैरेक्टर सेट मानकर डिकोड करते थे, जिसके परिणामस्वरूप मोजिबेक (mojibake) होता था।
सबक: URLs में नॉन-ASCII कैरेक्टर्स को "बस हैंडल" करने के लिए ब्राउज़रों और सर्वरों पर भरोसा करना असंगति (inconsistency) को न्योता देना है। सभी गैर-अनारक्षित (non-unreserved) characters को UTF-8 मानक का उपयोग करके सक्रिय और लगातार परसेंट-एन्कोड करना यह सुनिश्चित करता है कि आपके URLs मजबूत हैं और पूरे वेब इकोसिस्टम, पुराने और नए, में अनुमानित रूप से काम करते हैं।
डबल-एन्कोडिंग की गड़बड़ी
एक टीम एक सिंगल साइन-ऑन (SSO) सिस्टम बना रही थी। फ्लो इस तरह काम करता था: service-a.com यूज़र को sso.com/login पर रीडायरेक्ट करेगा, अपना खुद का URL एक पैरामीटर के रूप में पास करेगा ताकि यूज़र को लॉग इन करने के बाद वापस भेजा जा सके। रीडायरेक्ट URL ऐसा दिखता था: sso.com/login?redirect_uri=https://service-a.com/dashboard?param=1।
service-a.com पर डेवलपर स्मार्ट था और उसने redirect_uri वैल्यू को एन्कोड किया, जिससे यह बना: sso.com/login?redirect_uri=https%3A%2F%2Fservice-a.com%2Fdashboard%3Fparam%3D1।
हालांकि, वे जिस वेब फ्रेमवर्क का उपयोग कर रहे थे, उसमें एक मिडलवेयर लेयर थी, जो "सुरक्षा के लिए," स्वचालित रूप से सभी आउटगोइंग क्वेरी पैरामीटर्स को URL-एन्कोड कर देती थी। उसने पहले से एन्कोड की गई स्ट्रिंग को देखा और उसे फिर से एन्कोड कर दिया। %3A में % को %25 में बदल दिया गया, इसलिए %3A बन गया %253A। अंतिम URL डबल-एन्कोडिंग का एक उलझा हुआ कचरा था। जब यूज़र sso.com पर पहुँचा, तो उसने URL को एक बार डिकोड किया और उसे सिंगल-एन्कोडेड स्ट्रिंग मिली, जिसे वह रीडायरेक्ट के रूप में उपयोग नहीं कर सका, जिससे लॉगिन फ्लो पूरी तरह से टूट गया।
सबक: अपने पूरे टूलचेन (toolchain) से अवगत रहें। डेटा को बनाते समय एन्कोड करें, और सुनिश्चित करें कि आगे कोई अन्य सिस्टम उसे फिर से एन्कोड न करे। डबल-एन्कोडिंग एक आम, सिर खुजलाने वाला बग है जो एक वैध URL को बेकार कबाड़ में बदल देता है।
आम गलतियाँ और जाल
- पूरे URL को एन्कोड करना। ऐसा कभी न करें। यदि आप
https://example.comको परसेंट-एन्कोड करते हैं, तो आपको कुछ ऐसा मिलेगाhttps%3A%2F%2Fexample.com। यह अब एक वैध URL नहीं है; स्कीम और अथॉरिटी वाले हिस्से अब सिर्फ कैरेक्टर्स का एक अर्थहीन जंजाल हैं। आपको केवल उन अलग-अलग कॉम्पोनेंट्स को एन्कोड करना चाहिए जिनकी ज़रूरत है (जैसे क्वेरी पैरामीटर वैल्यू या विशिष्ट पाथ सेगमेंट)। - बिल्कुल भी एन्कोड न करना। यह सबसे आम पाप है। कच्चे यूज़र इनपुट या विशेष कैरेक्टर्स वाले डेटा को सीधे URL स्ट्रिंग में डालना सुरक्षा खामियों (जैसे क्रॉस-साइट स्क्रिप्टिंग) और टूटी हुई कार्यक्षमता को बुलावा देना है।
- कॉन्टेक्स्ट को भूल जाना।
&कैरेक्टर URL के पाथ में ठीक है, लेकिन क्वेरी स्ट्रिंग में यह एक रिज़र्व्ड सेपरेटर है। इसी तरह/के लिए भी। आपको रिज़र्व्ड कैरेक्टर्स को तब एन्कोड करने की आवश्यकता नहीं है जब वे अपने विशेष उद्देश्य के लिए उपयोग किए जा रहे हों। +और%20के बीच कन्फ्यूज होना।application/x-www-form-urlencodedकंटेंट टाइप में (जो HTML फॉर्म द्वारा उपयोग किया जाता है), स्पेस को अक्सर क्वेरी स्ट्रिंग में+चिह्न के रूप में एन्कोड किया जाता है। जबकि कई सर्वर इसे समझते हैं, स्पेस के लिए आधिकारिक परसेंट-एन्कोडिंग%20है।%20का उपयोग करना अस्पष्ट नहीं है और URL के सभी हिस्सों में सही ढंग से काम करता है, न कि केवल क्वेरी स्ट्रिंग में। जब भी शक हो,%20का ही इस्तेमाल करें।- एक पुराने कैरेक्टर सेट का उपयोग करना। वेब UTF-8 पर चलता है। यदि आप अपने डेटा को एक अलग कैरेक्टर सेट (जैसे ISO-8859-1) का उपयोग करके एन्कोड करते हैं, तो UTF-8 की उम्मीद करने वाला सर्वर बाइट्स की गलत व्याख्या करेगा और आपके डेटा को बिगाड़ देगा। हमेशा UTF-8 निर्दिष्ट करें और उपयोग करें।
यह आपकी नज़र में क्यों होना चाहिए
अगर आप ऐसा कोड लिखते हैं जो URL को छूता है, तो आपको परसेंट-एन्कोडिंग को समझने की ज़रूरत है। यह वैकल्पिक नहीं है। आपको इसके बारे में सोचना चाहिए जब भी आप:
- वेरिएबल्स या यूज़र इनपुट से एक URL बना रहे हों।
- URL में पैरामीटर्स के साथ एक API रिक्वेस्ट कर रहे हों।
- फ़ाइल नामों, यूज़र प्रोफाइल, या कंटेंट में अंतर्राष्ट्रीय कैरेक्टर्स को संभाल रहे हों जो URL में दिखाई दे सकते हैं।
- डेटा निकालने के लिए सर्वर-साइड पर URL को पार्स कर रहे हों।
- रीडायरेक्ट लिख रहे हों या अन्य सेवाओं को पैरामीटर के रूप में URL पास कर रहे हों।
संक्षेप में, परसेंट-एन्कोडिंग वेब प्लंबिंग का एक मौलिक हिस्सा है। इसे अनदेखा करने से बग्गी, असुरक्षित और अविश्वसनीय सॉफ्टवेयर बनता है। यह कैसे काम करता है यह जानना एक पेशेवर वेब डेवलपर की निशानी है।
और गहराई में जाएं
- RFC 3986: Uniform Resource Identifier (URI) के लिए मानक विनिर्देश। सेक्शन 2 कैरेक्टर सेट और परसेंट-एन्कोडिंग नियमों को परिभाषित करता है। यह सच्चाई का अंतिम स्रोत है।
- MDN Web Docs: encodeURIComponent(): जावास्क्रिप्ट डेवलपर्स के लिए एक व्यावहारिक गाइड, जो बताता है कि कौन सा फ़ंक्शन उपयोग करना है और क्यों। "See also" सेक्शन अन्य संबंधित एन्कोडिंग फ़ंक्शंस से लिंक करता है।
- Wikipedia: Percent-encoding: इस अवधारणा, इसके इतिहास और इसकी विभिन्न बारीकियों का एक व्यापक और बहुत पठनीय अवलोकन।
- W3C: Character encodings: एक उच्च-स्तरीय परिचय कि वेब पर कैरेक्टर एन्कोडिंग क्यों मायने रखती है, जिसमें UTF-8 कहानी का हीरो है।