- IPv6 zone वह नोटेशन है जो तब लक्ष्य interface को अलग पहचानने देता है जब कई interfaces एक ही
fe80:: link-local range का उपयोग करते हैं, जैसे fe80::4%eth0
- URL में IPv6 address को port और colon से अलग दिखाने के लिए
[fe80::4]:80 की तरह brackets में रखा जाता है, और zone जोड़ने पर bracket notation [fe80::4%eth0]:80 बन जाता है
- Go का
net/url ]:80 को %et नाम के गलत URL escape के रूप में समझकर invalid URL escape त्रुटि देता है
- RFC 6874 zone वाले IPv6 literal को
IPv6address "%25" ZoneID के रूप में परिभाषित करता है, इसलिए URL में % को %25 के रूप में percent-encode करना पड़ता है
- Anubis को IPv6 zone address की ओर इंगित करना हो तो यही नोटेशन इस्तेमाल करना पड़ेगा, और यह browser·nginx·Requests से जुड़े मुद्दों की तरह origin और library compatibility तक फैला हुआ एक edge case बना रहता है
IPv6 zone और URL व्याकरण का टकराव
- IPv6 के link-local address हर interface पर
fe80::whatever range में हो सकते हैं, इसलिए जब दो network interfaces हों तो fe80::4 destination को अलग पहचानने के लिए IPv6 scope/zone) का उपयोग करना पड़ता है
- zone value का format operating system के अनुसार अलग होता है; Linux में interface name और Windows में interface ID का उपयोग होता है
- उदाहरण में
eth0 Ethernet device का नाम है, और address इस तरह लिखा जाता है
fe80::4%eth0
- host और port आमतौर पर colon से अलग किए जाते हैं, लेकिन IPv6 addresses भी hex groups को अलग करने के लिए colon का उपयोग करते हैं, इसलिए port 80 वाले
fe80::4 को इस तरह brackets में लिखना पड़ता है
[fe80::4]:80
- zone जोड़ने पर format यह हो जाता है
[fe80::4%eth0]:80
- इसे सीधे URL hostname में डालकर
http://[fe80::4%eth0]:80 लिखने पर Go net/url %et को गलत URL escape मानकर विफल हो जाता है
panic: parse "http://[fe80::4%eth0]:80": invalid URL escape "%et"
मानक के अनुसार समाधान और बाकी समस्याएँ
- URL grammar के अनुसार अमान्य values के लिए percent-encoding का उपयोग करना चाहिए; URL में
%20 URL के लिए अमान्य ASCII space को encode करने का एक उदाहरण है
- IPv6 zone के
% को भी encode करना पड़ता है, इसलिए Go में http://[fe80::4%25eth0]:80 लिखने पर ही Hostname() का परिणाम fe80::4%eth0 आता है
- RFC 9844 user interface में IPv6 zone को संभालने के लिए दिशानिर्देश देता है, और RFC 6874 URL में zone सहित IPv6 literal का syntax इस तरह परिभाषित करता है
IP-literal = "[" ( IPv6address / IPv6addrz / IPvFuture ) "]"
ZoneID = 1*( unreserved / pct-encoded )
IPv6addrz = IPv6address "%25" ZoneID
- यही edge case nginx ticket, Requests issue, और HTTP link-local URI BCP draft में भी दिखाई देता है
- browsers अभी IPv6 zone को support नहीं करते, क्योंकि यह कई सूक्ष्म व्यवहारों में इस्तेमाल होने वाली “origin” की अवधारणा को तोड़ देता है; यह draft browser के उपयोग के लिए IPv6 का zone origin परिभाषित करने की कोशिश है
- Anubis को IPv6 zone address की ओर इंगित करना हो तो
% को percent-encode करना पड़ेगा, और Go standard library को fork न करने की नीति के तहत इस edge case की खराब UX को स्वीकार करना होगा
1 टिप्पणियां
Lobste.rs की रायें
TL;DR: कंप्यूटर एक गलती थेजैसी निष्कर्ष वाली बात नहाने का पानी फेंकते हुए बच्चे को भी फेंक देने जैसी नहीं लगती?सीधे-सीधे Trigun जैसे किसी anime खलनायक की तर्कशैली जैसी, कि इंसान भयानक अपराध कर सकते हैं, इसलिए सभी इंसानों को खत्म कर देना चाहिए
पता है यह मजाकिया अंदाज में कहा गया है, लेकिन दिलचस्प है, और मैं इसे अपनी अगली तैयार की जा रही प्रस्तुति के विषय के रूप में लेने वाला हूँ
फिर भी, मुख्य बात से सहमति है। ऐसी स्थिति अपने-आप में काफ़ी हास्यास्पद लगती है
लेकिन link-local IPv6 address को सही तरह handle न कर पाने के मामले बहुत दुर्लभ भी नहीं हैं
क्योंकि अब
%का URL के host हिस्से में सिर्फ़ उसी समय अलग मतलब होता है, जब host IPv6 address हो और[...]के अंदर होयह नहीं कि grammar पूरी तरह अस्पष्ट हो ही जाती है, लेकिन मुद्दा वह नहीं है। ऐसे exception case जितने बढ़ते हैं, URL parser के किसी खास exception को चूक जाने की संभावना उतनी बढ़ती है, और parsers के बीच के फ़र्क़ में गंदे bugs या security issues छिपकर घुस आना आसान हो जाता है
निजी तौर पर मैं URL में IPv6 zone को handle करने के पक्ष में हूँ, लेकिन एक समय
%को URL-encode करना चाहिए ऐसी guidance रही है, इसलिए अब इसे पलटना वास्तव में ambiguity पैदा करता है। अफ़सोस की बात हैpct-encoded = "%" HEXDIG HEXDIGयहाँ
HEXDIGको[a-fA-F]के रूप में define किया गया है, इसलिए%etको invalid sequence की तरह parse किया जाता हैspec यह भी कहती है कि
%character percent-encoded octet के indicator के रूप में इस्तेमाल होता है, इसलिए अगर उसे URI के अंदर data के रूप में इस्तेमाल करना हो तो%25के रूप में percent-encode करना चाहिए। अगर पहले से decoded string को फिर decode किया जाए तो percent data octet को percent encoding की शुरुआत समझने की गलती हो सकती है, और पहले से encoded string को फिर encode करने पर उलटी समस्या हो सकती है, इसलिए implementation को एक ही string को एक से ज़्यादा बार encode या decode नहीं करना चाहिएइसलिए यह परेशान करने वाला तो है, लेकिन व्यवहार में इसे bug कहना मुश्किल है
%को सीधे इस्तेमाल करना इतना भयानक क्यों माना जाए, यह समझ नहीं आता। Encoded character host हिस्से में भी allowed हैं, और zone address में%को जस का तस लिखने पर ambiguity पैदा होती है%खुद unreserved character नहीं है, इसलिए उसे percent-encode करना सही हैGo का
net/urlऔरnet/httpका URL RFC से टकराना कोई नई बात नहीं है। खासकरnet/url.URL.Pathका मौजूद होना औरnet/httpमें उसका इस्तेमाल काफ़ी झुंझलाहट भरा है, क्योंकि यह%2Fको तोड़ देता है।net/http.Redirectभीpath.Cleanका इस्तेमाल करके//को ग़लती से/में समेट देता हैGo standard library में URL को handle करने वाले हिस्सों को fork करने का मन होने, या
net/url/v2जैसी किसी चीज़ का प्रस्ताव रखने की वजहें बहुत हैं। लेकिन इस लेख में जो दिखता है, उसके हिसाब से Go का IPv6 zone address handling काफ़ी उचित और सही लगता है