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
호스트 이름이 유효한 경우 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. 호스트 이름으로 제공하고 있습니다
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 버그 로보고되었습니다.