URL एनकोडर और डिकोडर

पर्सेंट-एनकोडिंग के तीनों रूप साथ-साथ, ताकि आप देख सकें कि कौन-सा चाहिए।

तीन नियम, और ग़लत नियम चुन लेना ही बग है

पर्सेंट-एन्कोडिंग किसी अक्षर की जगह % और उसके बाद उसके बाइट का हेक्स मान रख देती है। इतना तो आसान है। मुश्किल यह है कि कौन-से अक्षर बदले जाने चाहिए, इस पर तीन अलग राय हैं — और वे ठीक उन्हीं अक्षरों पर आपस में असहमत हैं जो मायने रखते हैं।

नियम/ ? & = # एस्केप करता हैस्पेस बनता हैकिसके लिए
encodeURIComponentहाँ%20URL के भीतर जाने वाला मान
encodeURIनहीं%20पूरे URL को साफ़ करना
फ़ॉर्म एन्कोडिंगहाँ+HTML फ़ॉर्म असल में जो भेजता है

यह टूल तीनों को एक साथ इसीलिए दिखाता है। उन्हें साथ-साथ पढ़ लेना, अमूर्त रूप से यह तय करने से तेज़ है कि आपका मतलब कौन-से से था।

यह किस ग़लती से बचाता है

मान लीजिए कोई खोज-मान है coffee & cake। कंपोनेंट के तौर पर एन्कोड करने पर वह coffee%20%26%20cake बन जाता है, और URL यह होता है:

/search?q=coffee%20%26%20cake

एक पैरामीटर, मान सही-सलामत। encodeURI से एन्कोड करने पर ऐम्परसैंड ज्यों का त्यों बचा रह जाता है:

/search?q=coffee%20&%20cake

अब सर्वर को दो पैरामीटर दिखते हैं — q का मान «coffee » है और एक दूसरा, ख़ाली पैरामीटर है जिसका नाम « cake» है। कहीं कोई त्रुटि नहीं। खोज बस चुपचाप ग़लत नतीजे लौटा देती है, और यही वह क़िस्म का बग है जो समीक्षा से बच निकलता है क्योंकि URL देखने में ठीक लगता है।

वह + जो जोड़ का चिह्न नहीं है

भ्रम का दूसरा भरोसेमंद स्रोत। फ़ॉर्म-एन्कोडेड डेटा में + का अर्थ स्पेस होता है, और असली जोड़-चिह्न को %2B लिखना पड़ता है। इसलिए फ़ॉर्म नियम से C%2B%2B डिकोड करने पर C++ मिलता है, पर C++ डिकोड करने पर C मिलता है — और दो स्पेस, और भाषा का नाम ग़ायब।

यह सबसे ज़्यादा फ़ोन नंबरों पर काटता है। +44 20 7946 0958 अगर किसी फ़ॉर्म से भेजा जाए और ग़लत नियम से डिकोड हो, तो वह 44 20 7946 0958 बन जाता है — देश का कोड चला जाता है, और कहीं कोई त्रुटि दर्ज नहीं होती।

हाथ से एन्कोड करने के बजाय क्या कीजिए

जावास्क्रिप्ट में क्वेरी स्ट्रिंग जोड़-जोड़कर बनाने के बजाय URLSearchParams से बनाइए। यह हर मान पर सही नियम लगाता है और दोहराई गई कुंजियाँ भी सँभाल लेता है:

const url = new URL('https://example.com/search');
url.searchParams.set('q', 'coffee & cake');
url.searchParams.set('page', '2');
// https://example.com/search?q=coffee+%26+cake&page=2

हर दूसरी भाषा में इसका समकक्ष मौजूद है, और उनमें से हर एक अक्षर-दर-अक्षर तय करने से ज़्यादा भरोसेमंद है। यह पेज उन मौक़ों के लिए है जब आप किसी का भेजा URL पढ़ रहे हों, या ऐसे URL की जाँच कर रहे हों जिसमें गड़बड़ हो चुकी है।

एन्कोड किया गया URL पढ़ना

कुछ अनुक्रम देखते ही पहचान लेने लायक़ हैं, क्योंकि वे लॉग में लगातार आते हैं:

अनुक्रमअक्षरयह क्यों मायने रखता है
%20स्पेसअब तक का सबसे आम
%2F/पाथ में एन्कोड की गई स्लैश अक्सर डायरेक्टरी ट्रैवर्सल की कोशिश होती है
%3A:रीडायरेक्ट पैरामीटर के भीतर एन्कोड किए URL में आम
%25%दोहरी एन्कोडिंग %2520 के रूप में दिखती है
%00नलक़रीब-क़रीब कभी जायज़ नहीं होता

%2520 ख़ास तौर पर जानने लायक़ है: यह वह %20 है जिसे दूसरी बार एन्कोड कर दिया गया। आम तौर पर इसका मतलब है कि कोई मान दो परतों से गुज़रा और दोनों ने उसे एन्कोड किया — और यह किसी रीडायरेक्ट शृंखला या ग़लत काम करते प्रॉक्सी की पहचान है।

संबंधित

टेक्स्ट एस्केप करने के बजाय बाइट एन्कोड करने के लिए Base64 अलग काम है। अगर डिकोड किया मान JSON निकले तो उसे फ़ॉर्मैटर पढ़ लेगा, और अगर वह कोई टोकन हो तो JWT डिकोडर

एन्कोडिंग से जुड़े सवाल

encodeURI और encodeURIComponent में क्या फ़र्क़ है?

encodeURIComponent उन अक्षरों को एस्केप करता है जिनका URL में ढाँचागत अर्थ होता है — / ? & = # : वग़ैरह — क्योंकि वह मानकर चलता है कि आप कोई ऐसा मान एन्कोड कर रहे हैं जो URL के भीतर बैठेगा। encodeURI उन्हें छेड़ता नहीं, क्योंकि वह मानता है कि आपने उसे पूरा URL थमाया है जिसे बस साफ़ करना है। क्वेरी पैरामीटर को encodeURI से एन्कोड करना आम ग़लती है: मान के अंदर का & बचा रह जाता है और चुपचाप आपके पैरामीटर के दो टुकड़े कर देता है।

स्पेस कभी %20 और कभी + क्यों होता है?

अपने-अपने संदर्भ में दोनों सही हैं। %20 स्पेस की आम पर्सेंट-एन्कोडिंग है और URL में कहीं भी चलती है। + वाली परिपाटी application/x-www-form-urlencoded से आती है, यानी उस फ़ॉर्मैट से जिसमें HTML फ़ॉर्म सबमिट होते हैं, जहाँ + का अर्थ स्पेस है और असली जोड़-चिह्न को %2B लिखना पड़ता है। तो पाथ में स्पेस %20 है और सबमिट किए गए फ़ॉर्म डेटा में स्पेस + है। ग़लत नियम से फ़ॉर्म डेटा डिकोड करने पर उपयोगकर्ता के टेक्स्ट का हर जोड़-चिह्न स्पेस बन जाता है।

मुझे «URI malformed» त्रुटि मिली। इसकी वजह क्या है?

ऐसा प्रतिशत चिह्न जिसके बाद दो हेक्साडेसिमल अंक न हों। आम तौर पर यह टेक्स्ट में पड़ा वह असली % होता है जिसे कभी एन्कोड ही नहीं किया गया — «50% off» जैसा कोई डिस्काउंट कोड ही काफ़ी है, क्योंकि %20 को एस्केप अनुक्रम पढ़ लिया जाता है और %off वैध नहीं है। असली प्रतिशत चिह्न को %25 लिखना पड़ता है। दूसरी वजह दोहरा डिकोडिंग है: एक बार एन्कोड की गई चीज़ को दो बार डिकोड करने पर आख़िरकार ऐसा % सामने आ जाता है जिसे बचा रहना था।

पूरा URL एन्कोड करूँ या सिर्फ़ मान?

लगभग हमेशा सिर्फ़ मान। URL को ढाँचे के हिसाब से बनाइए और हर पैरामीटर को डालते वक़्त एन्कोड कीजिए — जावास्क्रिप्ट में URLSearchParams यह आपके लिए करता है और हाथ से एन्कोड करने से ज़्यादा भरोसेमंद है। पूरा URL एन्कोड करना सिर्फ़ तभी समझ आता है जब आपको पहले से बिगड़ा हुआ URL थमा दिया गया हो और आप उसकी मरम्मत कर रहे हों।

क्या URL एन्कोड कर देने से वह सुरक्षित हो जाता है?

नहीं। पर्सेंट-एन्कोडिंग वाक्य-रचना का मामला है, सुरक्षा का नहीं — यह इतना पक्का करती है कि कोई मान URL में रखे जाने के बाद बचा रहे और URL का ढाँचा न बदले। URL किधर इशारा कर रहा है, इससे उसका कोई लेना-देना नहीं, और यह इंजेक्शन से बचाव भी नहीं है: URL के लिए सही ढंग से एन्कोड किया गया मान भी ख़तरनाक बना रहता है अगर उसे बाद में HTML या SQL में उनके अपने ज़रूरी एस्केपिंग के बिना डाल दिया जाए।

अंतिम समीक्षा । कुछ पुराना पड़ा हुआ मिला? हमें बताइए.