URI बनाते समय होस्टनाम क्यों अमान्य घोषित किया गया है


17

इस कोड को JDK 1.8 के साथ चलाना:

try {
    System.out.println( new URI(null, null, "5-12-145-35_s-81", 443, null, null, null));
} catch (URISyntaxException e) {
    e.printStackTrace();
}

इस त्रुटि के परिणाम: java.net.URISyntaxException: Illegal character in hostname at index 13: //5-12-145-35_s-81:443

प्रकार के URI वर्णों के अनुसार, सभी होस्टनाम वर्णों को वैध मानते हुए यह त्रुटि कहां से आई है ?


यदि मैं इन URL का उपयोग करता हूं: //5-12-145-35_s-81:443या /5-12-145-35_s-81:443त्रुटि चली गई है।


टिप्पणियों से, मैं समझता हूं कि, RFC-2396 के अनुसार , होस्टनाम में कोई अंडरस्कोर वर्ण नहीं हो सकते।

यह प्रश्न अब भी है कि स्लैश या डबल स्लैश से शुरू होने वाले एक होस्टनाम को अंडरस्कोर करने की अनुमति क्यों है?


1
@ernest_k योजना नहीं दी गई है, यह शून्य है।
यूजेन कोवेसी

अगर आप अभी भी _ url में चाहते हैं तो @ fg78nc वर्कअराउंड आपके लिए काम करेगा। उपयोग न करें / क्योंकि होस्टनाम अमान्य होगा और फ़ील्ड नहीं बनाएगा
salesh

3
RFC-2396 खंड 3.2.2 देखें । URI में एक होस्टनाम अल्फ़ान्यूमेरिक + का केवल एक या अधिक समूह हो सकता है -, जिसे डॉट्स द्वारा अलग किया गया है
Mark Rotteveel

@MarkRotteveel java.net.URI नवीनतम चश्मे के साथ अद्यतित नहीं है
fg78nc

@ fg78nc यद्यपि RFC-3986 इसे शिथिल करता है, फिर भी यह उल्लेख करता है कि "DNS में देखने के लिए पंजीकृत एक पंजीकृत नाम [RFC1034] की धारा 3.5 [RFC1123] की धारा 2.1 में परिभाषित वाक्यविन्यास का उपयोग करता है।" , और वह मूल रूप से RFC-2396 खंड 3.2.2 का वाक्यविन्यास है।
मार्क रोटेटेवेल

जवाबों:


8

होस्ट नाम निम्न सिंटैक्स से मेल खाना चाहिए:

hostname      = domainlabel [ "." ] | 1*( domainlabel "." ) toplabel [ "." ]
domainlabel   = alphanum | alphanum *( alphanum | "-" ) alphanum
toplabel      = alpha | alpha *( alphanum | "-" ) alphanum

जैसा कि आप देख सकते हैं, केवल .और -अनुमति है, _नहीं है।


फिर आप कहते हैं कि //5-12-145-35_s-81:443इसकी अनुमति है, और यह मेजबान नाम के लिए नहीं है ।

यह देखने के लिए कि कैसे पैन निकलता है:

URI uriBadHost = URI.create("//5-12-145-35_s-81:443");
System.out.println("uri = " + uriBadHost);
System.out.println("  authority = " + uriBadHost.getAuthority());
System.out.println("  host = " + uriBadHost.getHost());
System.out.println("  port = " + uriBadHost.getPort());
URI uriGoodHost = URI.create("//example.com:443");
System.out.println("uri = " + uriGoodHost);
System.out.println("  authority = " + uriGoodHost.getAuthority());
System.out.println("  host = " + uriGoodHost.getHost());
System.out.println("  port = " + uriGoodHost.getPort());

उत्पादन

uri = //5-12-145-35_s-81:443
  authority = 5-12-145-35_s-81:443
  host = null
  port = -1
uri = //example.com:443
  authority = example.com:443
  host = example.com
  port = 443

जैसा कि आप देख सकते हैं, जब authorityएक मान्य होस्ट नाम होता है, hostऔर portपार्स किया जाता है, लेकिन जब मान्य नहीं होता है, तो authorityइसे फ्रीफ़ॉर्म टेक्स्ट के रूप में माना जाता है, और आगे कोई पार्स नहीं किया जाता है।


अपडेट करें

टिप्पणी से:

System.out.println( new URI(null, null, "/5-12-145-35_s-81", 443, null, null, null))आउटपुट: /// 5-12-145-35_s-81: 443। मैं इसे hostname के रूप में दे रहा हूं

जिस URIकंस्ट्रक्टर को आप बुला रहे हैं वह एक सुविधा विधि है, और यह सरल पूर्ण यूआरआई स्ट्रिंग बनाता है और फिर इसे पार्स करता है।

पासिंग "5-12-145-35_s-81", 443बन जाता है //5-12-145-35_s-81:443
पासिंग "/5-12-145-35_s-81", 443बन जाता है ///5-12-145-35_s-81:443

पहले में, यह एक मेजबान और बंदरगाह है , और पार्स करने में विफल रहता है।
दूसरे में अधिकार भाग खाली है, और /5-12-145-35_s-81:443एक मार्ग है

URI uri1 = new URI(null, null, "/5-12-145-35_s-81", 443, null, null, null);
System.out.println("uri = " + uri1);
System.out.println("  authority = " + uri1.getAuthority());
System.out.println("  host = " + uri1.getHost());
System.out.println("  port = " + uri1.getPort());
System.out.println("  path = " + uri1.getPath());

उत्पादन

uri = ///5-12-145-35_s-81:443
  authority = null
  host = null
  port = -1
  path = /5-12-145-35_s-81:443

अब मुझे समझ में आया, लेकिन क्यों, आइए बताते हैं /a_b, अनुमति है। अंतर केवल इतना है कि यह एक पूर्ण है, सापेक्ष नहीं
यूजेन कोवेसी

System.out.println( new URI(null, null, "/5-12-145-35_s-81", 443, null, null, null))आउटपुट: ///5-12-145-35_s-81:443। मैं इसे hostname के रूप में दे रहा हूं।
यूजेन कोवेसी

यह व्यवहार (जब होस्टनाम निरपेक्ष है) अजीब है, कम से कम कहने के लिए। URI का निर्माता होस्टनाम और पोर्ट दे रहा है, और परिणामी URI के पास न तो केवल एक ही रास्ता है।
यूजेन कोवेसी

5

बग जावा में नहीं है, लेकिन होस्ट का नामकरण करने के बाद से, एक अंडरस्कोर होस्टनाम में एक वैध चरित्र नहीं है। यद्यपि व्यापक रूप से गलत तरीके से उपयोग किया जाता है, जावा ऐसे होस्टनाम को संभालने से इनकार करता है


यह एक /5-12-145-35_s-81:443कानूनी है।
यूजेन कोवेसी

2

URI में अंडरस्कोर का समर्थन नहीं किया जाता है।

हालांकि एक होस्टनाम में अन्य वर्ण नहीं हो सकते हैं, जैसे कि अंडरस्कोर वर्ण (_), अन्य DNS नामों में अंडरस्कोर हो सकता है। [५] [६] इस प्रतिबंध को RFC 2181, धारा 11 द्वारा हटा दिया गया था। DomainKeys और सर्विस रिकॉर्ड जैसे सिस्टम यह सुनिश्चित करने के लिए अंडरस्कोर का उपयोग करते हैं कि उनका विशेष चरित्र होस्टनाम के साथ भ्रमित नहीं है। उदाहरण के लिए, _http._sctp.www.example.com डोमेन example.com में SCTP- सक्षम वेबसर्वर होस्ट (www) के लिए एक सेवा सूचक निर्दिष्ट करता है। मानक के बावजूद, Chrome, Firefox, Internet Explorer, Edge और Safari होस्टनाम में अंडरस्कोर की अनुमति देता है, हालाँकि IE में कुकीज़ ठीक से काम नहीं करती हैं यदि होस्टनाम के किसी भी हिस्से में अंडरस्कोर वर्ण नहीं है

विकिपीडिया

जावदोक्स से:

सार्वजनिक URI (स्ट्रिंग str) URISyntaxException फेंकता है: URISyntaxException - यदि दी गई स्ट्रिंग RFC 2396 का उल्लंघन करती है, जैसा कि उपरोक्त विचलन द्वारा संवर्धित है।

javadocs

(हैकी) समाधान:

    URI url = URI.create("https://5-12-145-35_s-8:8080");

    System.out.println(url.getHost()) // null

    if (url.getHost() == null) {
        final Field hostField = URI.class.getDeclaredField("host");
        hostField.setAccessible(true);
        hostField.set(url, "5-12-145-35_s-81");
    }
    System.out.println(url.getHost()); // 5-12-145-35_s-81

यह बताया गया था - JDK बग


1
वाह, यह एक hacky समाधान है। आप कह सकते हैं कि यह भविष्य में टूट सकता है, क्योंकि यह आंतरिक वर्ग के बारे में आंतरिक मान रहा है और इसे सीधे उपयोग करने के लिए प्रतिबिंब का उपयोग करता है। तो कार्यान्वयन किसी भी जावा रिलीज के साथ बदल सकता है, जिस स्थिति में यह टूट सकता है। हालांकि एक समाधान प्रदान करने के लिए +1 ।
ज़बुज़ार्ड

जितना मैं इस समाधान को रखना चाहता था, मैंने नहीं किया, इन चीजों के साथ समस्या सिर्फ ज़ुबुज़ा का उल्लेख है। + अगर हम नियमों को मानना ​​शुरू करते हैं तो सब कुछ धीरे-धीरे खत्म होने लगेगा। एक अच्छा कारण है कि यह पहली जगह में काम क्यों नहीं करता है।
salesh

@ शैलेश और वह अच्छा कारण क्या है?
fg78nc

"डोमेनकेय और सर्विस रिकॉर्ड जैसे सिस्टम इस बात का आश्वासन देने के लिए अंडरस्कोर का उपयोग करते हैं कि उनके विशेष चरित्र को होस्टनाम के साथ भ्रमित नहीं किया गया है।" विकिपीडिया और यहाँ अच्छा जवाब है quora
salesh

1
यदि आप ऐसा करेंगे तो आपको nullमेजबान के रूप में मिलेगा ।
fg78nc
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.