परसेंट एन्कोडिंग क्या है? (RFC 3986 सरल भाषा में समझें)
परसेंट एन्कोडिंग RFC 3986 में परिभाषित एक तंत्र है, जिसमें URI के विशेष अक्षरों को एक परसेंट चिह्न (%) और उसके बाद दो हेक्साडेसिमल अंकों से बदलकर एन्कोड किया जाता है। यह सुनिश्चित करता है कि URL में केवल वैध ASCII अक्षर हों, जिन्हें इंटरनेट पर सुरक्षित रूप से भेजा जा सके।
परसेंट एन्कोडिंग क्या है?
परसेंट एन्कोडिंग, जिसे URL एन्कोडिंग भी कहा जाता है, किसी URI (Uniform Resource Identifier) में उन अक्षरों को दर्शाने का मानक तरीका है जिनकी अनुमति नहीं है या जिनका कोई विशेष अर्थ होता है। यह प्रत्येक ऐसे अक्षर को, जिसे एन्कोड करने की आवश्यकता है, एक परसेंट चिह्न (%) और उसके बाद उस अक्षर के बाइट मान को दर्शाने वाले दो हेक्साडेसिमल अंकों से बदलकर काम करता है।
उदाहरण के लिए, स्पेस अक्षर (बाइट मान 0x20) को %20 के रूप में एन्कोड किया जाता है। एट साइन @ (बाइट मान 0x40) को %40 के रूप में एन्कोड किया जाता है। यह तंत्र सुनिश्चित करता है कि कोई भी डेटा URI सिंटैक्स से टकराए बिना सुरक्षित रूप से किसी URI में शामिल किया जा सके।
"परसेंट एन्कोडिंग" शब्द परसेंट अक्षर के एस्केप प्रीफ़िक्स के रूप में उपयोग से आया है। इसका औपचारिक विनिर्देश RFC 3986 में परिभाषित है, जिसे जनवरी 2005 में Internet Engineering Task Force (IETF) द्वारा प्रकाशित किया गया था और जिसके लेखक Tim Berners-Lee, Roy Fielding और Larry Masinter हैं।
परसेंट एन्कोडिंग कैसे काम करती है
एन्कोडिंग प्रक्रिया इन चरणों का पालन करती है: सबसे पहले, अक्षर को किसी कैरेक्टर एन्कोडिंग (आधुनिक वेब पर लगभग हमेशा UTF-8) का उपयोग करके उसके बाइट रूप में बदला जाता है। फिर, प्रत्येक बाइट को एक परसेंट चिह्न और उसके बाद दो हेक्साडेसिमल अंकों के रूप में दर्शाया जाता है (परंपरा के अनुसार बड़े अक्षरों A-F का उपयोग करते हुए, हालांकि डिकोडर्स को छोटे अक्षर भी स्वीकार करने चाहिए)।
// स्पेस अक्षर की चरण-दर-चरण एन्कोडिंग
// अक्षर: ' ' (स्पेस)
// ASCII/UTF-8 बाइट मान: 0x20 (दशमलव 32)
// परसेंट-एन्कोडेड: %20
// मल्टी-बाइट अक्षर की चरण-दर-चरण एन्कोडिंग: acute वाला e
// अक्षर: acute वाला e (U+00E9)
// UTF-8 बाइट्स: 0xC3 0xA9
// परसेंट-एन्कोडेड: %C3%A9
// 3-बाइट अक्षर की चरण-दर-चरण एन्कोडिंग
// अक्षर: CJK ideograph (U+4E2D)
// UTF-8 बाइट्स: 0xE4 0xB8 0xAD
// परसेंट-एन्कोडेड: %E4%B8%AD
हेक्साडेसिमल अंक हमेशा जोड़ों में आने चाहिए। अकेला परसेंट चिह्न या ऐसा परसेंट चिह्न जिसके बाद गैर-हेक्साडेसिमल अक्षर हों, अमान्य है और डिकोडिंग त्रुटि का कारण बनेगा। यह JavaScript में "URI malformed" त्रुटि का एक आम कारण है।
परसेंट एन्कोडिंग हमेशा प्रतिवर्ती (reversible) होती है। डिकोडर परसेंट चिह्न को पढ़ता है, अगले दो अक्षरों को हेक्साडेसिमल बाइट मान के रूप में लेता है, और उसे वापस मूल अक्षर में बदल देता है। मल्टी-बाइट UTF-8 अक्षरों के लिए, क्रमागत एन्कोडेड बाइट्स को मिलाकर एक साथ डिकोड किया जाता है।
किन अक्षरों को एन्कोड करना आवश्यक है?
सभी अक्षरों को परसेंट एन्कोडिंग की आवश्यकता नहीं होती। RFC 3986 दो श्रेणियां परिभाषित करता है: unreserved अक्षर जिन्हें कभी एन्कोडिंग की आवश्यकता नहीं होती, और reserved अक्षर जिन्हें तब एन्कोड करना आवश्यक होता है जब उनका उपयोग उनके आरक्षित उद्देश्य के लिए नहीं किया जा रहा हो। अन्य सभी अक्षरों (स्पेस, गैर-ASCII अक्षर और कंट्रोल अक्षर सहित) को हमेशा एन्कोड करना आवश्यक होता है।
जिन अक्षरों को एन्कोडिंग की आवश्यकता नहीं होती (unreserved): बड़े अक्षर (A-Z), छोटे अक्षर (a-z), अंक (0-9), हाइफ़न (-), पूर्ण विराम (.), अंडरस्कोर (_), और टिल्ड (~)। ये 66 अक्षर बिना एन्कोडिंग के किसी URI में कहीं भी आ सकते हैं।
जिन अक्षरों को कभी-कभी एन्कोडिंग की आवश्यकता होती है (reserved): : / ? # [ ] @ ! $ & ' ( ) * + , ; =। इन अक्षरों का URI में विशेष सिंटैक्टिक अर्थ होता है। इन्हें केवल तब एन्कोडिंग की आवश्यकता होती है जब इनका उपयोग डिलिमिटर के बजाय डेटा के रूप में किया जाता है।
जिन अक्षरों को हमेशा एन्कोडिंग की आवश्यकता होती है: स्पेस, गैर-ASCII अक्षर (127 से ऊपर का कोई भी अक्षर), कंट्रोल अक्षर (0-31 और 127), और < > { } | \ ^ ` " जैसे असुरक्षित अक्षर।
RFC 3986 में Reserved बनाम Unreserved अक्षर
reserved और unreserved अक्षरों के बीच का अंतर यह समझने के लिए मौलिक है कि URI कैसे काम करते हैं। reserved अक्षर डिलिमिटर के रूप में कार्य करते हैं जो किसी URI की संरचना को परिभाषित करते हैं। उदाहरण के लिए, :// स्कीम को अथॉरिटी से अलग करता है, / पाथ सेगमेंट्स को अलग करता है, ? क्वेरी स्ट्रिंग शुरू करता है, और # फ़्रैगमेंट शुरू करता है।
| श्रेणी | अक्षर | कब एन्कोड करें |
|---|---|---|
| Unreserved | A-Z a-z 0-9 - . _ ~ |
कभी नहीं |
| सामान्य डिलिमिटर | : / ? # [ ] @ |
जब डेटा के रूप में उपयोग हों, डिलिमिटर के रूप में नहीं |
| सब-डिलिमिटर | ! $ & ' ( ) * + , ; = |
जब इन्हें अर्थ प्रदान करने वाले कंपोनेंट्स में डेटा के रूप में उपयोग किया जाए |
| अन्य सभी अक्षर | स्पेस, गैर-ASCII, कंट्रोल अक्षर, आदि। | हमेशा |
RFC 3986 का एक महत्वपूर्ण सिद्धांत यह है कि जो URI केवल इस बात में भिन्न हों कि कोई reserved अक्षर परसेंट-एन्कोडेड है या शाब्दिक रूप में मौजूद है, वे समतुल्य नहीं होते। उदाहरण के लिए, /path/to और /path%2Fto अलग-अलग URI हैं, भले ही %2F डिकोड होकर / बनता हो। पहले में दो पाथ सेगमेंट हैं; दूसरे में एक पाथ सेगमेंट है जिसमें एक शाब्दिक स्लैश शामिल है।
परसेंट एन्कोडिंग बनाम URL एन्कोडिंग: क्या ये एक ही हैं?
"परसेंट एन्कोडिंग" और "URL एन्कोडिंग" को अक्सर एक-दूसरे के स्थान पर इस्तेमाल किया जाता है, और अधिकांश संदर्भों में इनका अर्थ एक ही होता है। हालांकि, इनमें एक सूक्ष्म ऐतिहासिक अंतर है। "URL एन्कोडिंग" कभी-कभी HTML फ़ॉर्म्स द्वारा उपयोग किए जाने वाले पुराने application/x-www-form-urlencoded फ़ॉर्मेट को संदर्भित कर सकता है, जो स्पेस को %20 के बजाय + के रूप में एन्कोड करता है।
application/x-www-form-urlencoded फ़ॉर्मेट को HTML विनिर्देश में परिभाषित किया गया था और यह RFC 3986 से पहले का है। इसके नियम थोड़े अलग हैं: स्पेस + बन जाते हैं, और जिन अक्षरों को एन्कोड नहीं किया जाता उनका समूह थोड़ा अलग होता है। "URL एन्कोडिंग" शब्द का आधुनिक उपयोग लगभग हमेशा RFC 3986 परसेंट एन्कोडिंग को संदर्भित करता है, जहां स्पेस %20 होते हैं।
व्यवहार में, आपको सभी URI संदर्भों (पाथ सेगमेंट, REST API में क्वेरी पैरामीटर, फ़्रैगमेंट आइडेंटिफ़ायर) के लिए RFC 3986 परसेंट एन्कोडिंग का उपयोग करना चाहिए। application/x-www-form-urlencoded फ़ॉर्मेट का उपयोग केवल HTML फ़ॉर्म सबमिशन से निपटते समय या जब कोई विशिष्ट API इसकी मांग करे, तभी करें।
// RFC 3986 परसेंट एन्कोडिंग (URI के लिए अनुशंसित)
encodeURIComponent('hello world') // "hello%20world"
// application/x-www-form-urlencoded (HTML फ़ॉर्म्स)
new URLSearchParams({q: 'hello world'}).toString() // "q=hello+world"
// Python समतुल्य
from urllib.parse import quote, quote_plus
quote('hello world', safe='') # "hello%20world"
quote_plus('hello world') # "hello+world"