Ana bilgisayar adı bir URI oluştururken neden geçersiz olarak bildiriliyor?


17

Bu kodu JDK 1.8 ile çalıştırma:

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

bu hatayla sonuçlanır: java.net.URISyntaxException: Illegal character in hostname at index 13: //5-12-145-35_s-81:443

URI karakterleri türüne göre, tüm ana bilgisayar adı karakterlerinin yasal göründüğü düşünüldüğünde bu hata nereden geliyor ?


Bu URL'leri kullanırsam: //5-12-145-35_s-81:443veya /5-12-145-35_s-81:443hata gitti.


Yorumlardan, RFC-2396'ya göre, ana bilgisayar adının alt çizgi karakterleri içeremediğini anlıyorum .

Hala devam eden soru, eğik çizgi veya çift eğik çizgi ile başlayan bir ana bilgisayar adının neden alt çizgi içermesine izin verilmesidir?


1
@ernest_k Şema verilmiyor, boş.
Eugen Covaci

hala url @ fg78nc içinde _ istiyorsanız geçici çözüm sizin için çalışacaktır. / Kullanmayın çünkü hostname geçersiz olacak ve alan oluşturmayacak
salesh

3
Bkz. RFC-2396 bölüm 3.2.2. -
URI'daki

@MarkRotteveel java.net.URI en son teknik özelliklere sahip değil
fg78nc

@ fg78nc Her ne kadar RFC-3986 onu rahatlatsa da, yine de "DNS'de arama amaçlı kayıtlı bir adın [RFC1034] Kısım 3.5 ve [RFC1123] Kısım 2.1'de tanımlanan sözdizimini kullandığı belirtilmektedir. ve bu temel olarak RFC-2396 bölüm 3.2.2'nin sözdizimidir.
Mark Rotteveel

Yanıtlar:


8

Ana bilgisayar adı, aşağıdaki sözdizimiyle eşleşmelidir:

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

Gördüğünüz gibi, sadece .ve -izin verilir, buna izin verilmez _.


Daha sonra //5-12-145-35_s-81:443buna izin verildiğini söylersiniz ve buna izin verilir, ancak ana bilgisayar adı için değil .

Bunun nasıl ortaya çıktığını görmek için:

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());

Çıktı

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

Gördüğünüz gibi, authoritygeçerli bir ana bilgisayar adına sahip olduğunda ve hostve portayrıştırılır, ancak geçerli olmadığında, authorityserbest biçimli metin olarak ele alınır ve daha fazla ayrıştırılmaz.


GÜNCELLEME

Yorumdan:

System.out.println( new URI(null, null, "/5-12-145-35_s-81", 443, null, null, null))çıkışlar: /// 5-12-145-35_s-81: 443. Hostname olarak veriyorum

URIYapıcı Sen çağıran bir kolaylık yöntemdir ve basit bir tam URI dizesini oluşturur ve daha sonra bu ayrıştırır.

Geçmek "5-12-145-35_s-81", 443olur //5-12-145-35_s-81:443.
Geçmek "/5-12-145-35_s-81", 443olur ///5-12-145-35_s-81:443.

İlk olarak, bir ana bilgisayar ve bağlantı noktasıdır ve ayrıştırılamaz.
İkincisinde otorite bölümü boştur ve /5-12-145-35_s-81:443bir yoldur .

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());

Çıktı

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

Şimdi anlıyorum, ama neden diyelim ki /a_bizin veriliyor. Tek fark, bunun göreceli değil, mutlak olmasıdır
Eugen Covaci

System.out.println( new URI(null, null, "/5-12-145-35_s-81", 443, null, null, null))çıkışlar: ///5-12-145-35_s-81:443. Bunu hostname olarak veriyorum.
Eugen Covaci

Bu davranış (hostname mutlak olduğunda), en azından söylemek gariptir. URI'nin yapıcısı bir ana bilgisayar adı ve bir bağlantı noktası veriyor ve sonuçta ortaya çıkan URI'de bir tane yok, sadece bir yol var.
Eugen Covaci

5

Hata, Java'da değil, ana bilgisayarı adlandırırken, alt çizgi bir ana bilgisayar adında geçerli bir karakter olmadığından. Yaygın olarak yanlış kullanılmasına rağmen, Java bu tür ana bilgisayar adlarını işlemeyi reddediyor


Bu /5-12-145-35_s-81:443yasal.
Eugen Covaci

2

Alt çizgiler URI'lerde desteklenmez.

Ana bilgisayar adı alt çizgi karakteri (_) gibi başka karakterler içermese de, diğer DNS adları alt çizgi içerebilir. [5] [6] Bu kısıtlama, RFC 2181, Bölüm 11 tarafından kaldırılmıştır. DomainKeys ve hizmet kayıtları gibi sistemler, alt karakterini, özel karakterlerinin ana bilgisayar adlarıyla karıştırılmamasını sağlamak için bir araç olarak kullanır. Örneğin, _http._sctp.www.example.com, example.com etki alanındaki SCTP özellikli bir web sunucusu ana bilgisayarı (www) için bir hizmet işaretçisi belirtir. Standart olmasına rağmen, Chrome, Firefox, Internet Explorer, Edge ve Safari, ana makine adlarında alt çizgilere izin verir, ancak ana makine adının herhangi bir bölümü alt çizgi karakteri içeriyorsa IE'deki çerezler düzgün çalışmaz

Vikipedi

Javadocs'tan:

public URI (String str) URISyntaxException atar: URISyntaxException - Verilen dize, yukarıdaki sapmalar ile artırıldığı gibi RFC 2396'yı ihlal ederse

Javadocs

(Hacky) Çözümü:

    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

Bu bildirildi - JDK hatası


1
Vay canına, bu hileli bir çözüm. Bunun, içsel bir sınıfla ilgili içsel varsayımlarda bulunduğu ve doğrudan erişmek için yansıma kullandığından, gelecekte kırılacağını söyleyebilirsiniz. Böylece uygulama herhangi bir Java sürümü ile değişebilir, bu durumda bu durum bozulabilir. Bir çözüm sağlamak için +1 .
Zabuzard

Bu geçici çözümü koymak istediğim kadarıyla, bu şeylerle ilgili sorun Zabuza'nın bahsettiği şey. + Kurallara uymaya başlarsak, her şey yavaşça çökmeye başlar. Bunun ilk etapta çalışmamasının iyi bir nedeni var.
salesh

@salesh Peki bu iyi sebep nedir?
fg78nc

"DomainKeys ve servis kayıtları gibi sistemler, alt çizgiyi özel karakterlerinin ana makine adlarıyla karıştırılmamasını sağlamak için bir araç olarak kullanır." wikipedia ve burada iyi bir cevap yoktur nisapları
Salesh

1
Bunu yaparsanız nullev sahibi olarak alacaksınız .
fg78nc
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.