[java] URI를 만들 때 호스트 이름이 유효하지 않은 것으로 선언 된 이유

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 에 따르면 호스트 이름에 밑줄 문자를 사용할 수 없다는 것을 알고 있습니다.

여전히 남아있는 질문은 슬래시 또는 이중 슬래시로 시작하는 호스트 이름에 밑줄이 포함될 수있는 이유는 무엇입니까?



답변

호스트 이름은 다음 구문과 일치해야합니다.

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호스트 이름이 유효한 경우 hostport구문 분석되지만 유효하지 않은 경우 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. 호스트 이름으로 제공하고 있습니다

URI호출 하는 생성자는 편리한 메소드이며 전체 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


답변

밑줄이 호스트 이름에 유효한 문자가 아니기 때문에 버그는 Java가 아니라 호스트 이름을 지정할 때 발생합니다. 널리 사용되지는 않지만 Java는 이러한 호스트 이름을 처리하지 않습니다.


답변

밑줄은 URI에서 지원되지 않습니다.

호스트 이름에는 밑줄 문자 (_)와 같은 다른 문자가 포함될 수 없지만 다른 DNS 이름에는 밑줄이 포함될 수 있습니다. [5] [6] 이 제한은 RFC 2181, 섹션 11에 의해 해제되었습니다. DomainKeys 및 서비스 레코드와 같은 시스템은 특수 문자가 호스트 이름과 혼동되지 않도록하기 위해 밑줄을 사용합니다. 예를 들어, _http._sctp.www.example.com은 example.com 도메인에서 SCTP 가능 웹 서버 호스트 (www)에 대한 서비스 포인터를 지정합니다. 표준에도 불구하고 Chrome, Firefox, Internet Explorer, Edge 및 Safari는 호스트 이름에 밑줄을 허용하지만 호스트 이름의 일부에 밑줄 문자가 포함되어 있으면 IE의 쿠키가 올바르게 작동하지 않습니다

위키 백과

Javadocs에서 :

public URI (String str) throws URISyntaxException Throws : URISyntaxException-지정된 캐릭터 라인이 RFC 2396를 위반했을 경우, 위의 편차에 의해 증대 된

자바 독

(해키) 해결책 :

    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 버그 로보고되었습니다.


답변