목표
URL 표준은 URL의 완전한 상호 운용성을 달성하기 위해 다음과 같은 접근 방식을 취합니다:
-
RFC 3986 및 RFC 3987을 최신 구현과 일치시키고, 이 과정에서 해당 RFC를 폐기합니다. (예: 공백, 기타 "불법" 코드 포인트, 쿼리 인코딩, 동등성, 정준화는 모두 완전히 공유되거나 정의된 개념이 아닙니다.) URL 파싱은 HTML 파싱만큼 견고해져야 합니다. [RFC3986] [RFC3987]
-
URL 용어를 표준화합니다. URI와 IRI는 혼란을 야기합니다. 실제로 두 가지 모두에 단일 알고리즘이 사용되므로 구분하는 것은 도움이 되지 않습니다. URL은 또한 검색 결과 인기 경쟁에서도 쉽게 우승합니다.
-
URI의 Origin [sic]을 대체합니다. [RFC6454]
-
URL의 기존 JavaScript API를 완전하게 정의하고, 더 쉽게 사용할 수 있도록 개선 사항을 추가합니다. HTML 요소를 사용하지 않고 URL을 조작할 수 있도록 새로운
URL객체도 추가합니다. (JavaScript 워커 환경에서 유용합니다.) -
파서, 직렬화기, API의 조합이 멱등성을 보장하도록 합니다. 예를 들어, 파싱 후 직렬화 작업의 실패하지 않는 결과는 추가적인 파싱-직렬화 작업을 적용해도 변경되지 않습니다. 마찬가지로, API를 통해 실패하지 않는 결과를 조작해도, 직렬화-파싱 작업을 여러 번 적용해도 변경되지 않습니다.
편집자가 주제를 더 깊이 학습함에 따라 목표의 범위가 다소 증가할 수 있습니다.
1. 인프라스트럭처
이 명세는 Infra에 의존합니다. [INFRA]
이 명세에서 사용되는 일부 용어들은 다음 표준 및 명세에서 정의됩니다:
- Encoding [ENCODING]
- File API [FILEAPI]
- HTML [HTML]
- Unicode IDNA Compatibility Processing [UTS46]
- Web IDL [WEBIDL]
정수를 직렬화하다는, 가능한 가장 짧은 십진수로 표현하는 것을 의미합니다.
1.1. 작성
검증 오류는 입력과 유효한 입력이 일치하지 않음을 나타냅니다. 사용자 에이전트, 특히 적합성 검사기는 이러한 오류를 어딘가에 보고하는 것이 권장됩니다.
검증 오류가 발생해도 파서가 종료된다는 의미는 아닙니다. 파서의 종료는 항상 명시적으로, 예를 들어 return 문을 통해 나타납니다.
검증 오류를 알리는 것은 오류 처리 방식이 직관적이지 않을 수 있고, 레거시 사용자 에이전트가 올바른 오류 처리를 구현하지 않을 수 있으며, 작성된 의도가 다른 개발자에게 명확하지 않을 수 있으므로 유용합니다.
| 오류 유형 | 오류 설명 | 실패 |
|---|---|---|
| IDNA | ||
| domain-to-ASCII |
Unicode ToASCII가 오류를 기록하거나 빈 문자열을 반환합니다. [UTS46] Unicode ToASCII 오류에 대한 세부 정보가 기록된 경우, 사용자 에이전트는 이를 전달하는 것이 권장됩니다. | 예 (단, domain이 ASCII 문자열인 경우는 제외) |
| domain-invalid-code-point |
입력의 호스트가 금지된 도메인 코드 포인트를 포함합니다. | 예 |
| 호스트 구문 분석 | ||
| host-invalid-code-point |
(특수가 아닌 URL에서) 불투명 호스트가 금지된 호스트 코드 포인트를 포함합니다. | 예 |
| IPv4-empty-part |
IPv4 주소가 U+002E (.)로 끝납니다. | · |
| IPv4-too-many-parts |
IPv4 주소가 정확히 4개의 부분으로 구성되어 있지 않습니다. | 예 |
| IPv4-non-numeric-part |
IPv4 주소 부분이 숫자가 아닙니다. | 예 |
| IPv4-non-decimal-part |
IPv4 주소가 16진수 또는 8진수 숫자를 사용해 표현된 숫자를 포함합니다. | · |
| IPv4-out-of-range-part |
IPv4 주소 부분이 255를 초과합니다. | 예 (마지막 부분에 적용되는 경우에만) |
| IPv6-unclosed |
IPv6 주소에 닫는 U+005D (])가 없습니다. | 예 |
| IPv6-invalid-compression |
IPv6 주소가 부적절한 압축으로 시작합니다. | 예 |
| IPv6-too-many-pieces |
IPv6 주소가 8개보다 많은 조각을 포함합니다. | 예 |
| IPv6-multiple-compression |
IPv6 주소가 둘 이상의 위치에서 압축되어 있습니다. | 예 |
| IPv6-invalid-code-point |
IPv6 주소가 ASCII 16진수 숫자 또는 U+003A (:)가 아닌 코드 포인트를 포함합니다. 또는 예기치 않게 끝납니다. | 예 |
| IPv6-too-few-pieces |
압축되지 않은 IPv6 주소가 8개보다 적은 조각을 포함합니다. | 예 |
| IPv4-in-IPv6-too-many-pieces | 예 | |
| IPv4-in-IPv6-invalid-code-point |
| 예 |
| IPv4-in-IPv6-out-of-range-part | 예 | |
| IPv4-in-IPv6-too-few-parts | 예 | |
| URL 구문 분석 | ||
| invalid-URL-unit |
URL 단위가 아닌 코드 포인트가 발견되었습니다. | · |
| special-scheme-missing-following-solidus |
입력의 스킴 뒤에 " | · |
| missing-scheme-non-relative-URL |
입력은 스킴이 없습니다. 이는 입력이 ASCII 알파로 시작하지 않고, 기본 URL이 제공되지 않았거나 기본 URL이 불투명 경로를 가지기 때문에 기본 URL로 사용할 수 없기 때문입니다. | 예 |
| invalid-reverse-solidus |
URL이 특수 스킴을 가지며, U+002F (/) 대신 U+005C (\)를 사용합니다. | · |
| invalid-credentials |
입력이 자격 증명을 포함합니다. | · |
| host-missing | 예 | |
| port-out-of-range |
입력의 포트가 너무 큽니다. | 예 |
| port-invalid |
입력의 포트가 유효하지 않습니다. | 예 |
| file-invalid-Windows-drive-letter |
입력이 상대
URL 문자열이며, Windows 드라이브 문자로 시작하고
기본
URL의 스킴이 "
| · |
| file-invalid-Windows-drive-letter-host |
| · |
1.2. 파서
EOF 코드 포인트는 문자열이나 코드 포인트 스트림의 끝을 나타내는 개념적인 코드 포인트입니다.
문자열 input에 대한 포인터는 input 내의 코드 포인트를 가리키는 정수입니다. 처음에는 input의 시작을 가리킵니다. 만약 값이 −1이면 아무 곳도 가리키지 않습니다. input의 코드 포인트 길이보다 크거나 같으면 EOF 코드 포인트를 가리킵니다.
포인터가 사용될 때, c는 코드 포인트 중 포인터가 가리키는 위치를 참조합니다. 단, 아무 곳도 가리키지 않을 때는 사용할 수 없습니다. 포인터가 아무 곳도 가리킬 때 c는 사용할 수 없습니다.
포인터가 사용될 때, remaining은 문자열의 끝까지의 코드 포인트 서브스트링을 포인터 + 1 부터 참조합니다. 단, c가 EOF 코드 포인트가 아닐 때만 사용할 수 있습니다. c가 EOF 코드 포인트일 때 remaining은 사용할 수 없습니다.
"mailto:username@example"가 처리 중인 문자열이고 포인터가 @을 가리킨다면, c는 U+0040 (@)이고 remaining은
"example"입니다.
빈 문자열을 처리 중이고 포인터가 시작을 가리키다가 −1로 감소된다면, c나 remaining을 사용하는 것은 오류입니다.
1.3. 퍼센트 인코딩 바이트
퍼센트 인코딩 바이트는 U+0025 (%) 뒤에 두 개의 ASCII 16진수가 오는 것입니다.
퍼센트 인코딩 바이트 시퀀스는 퍼센트 디코딩 후 BOM 없이 UTF-8 디코드 또는 실패에 전달될 때 실패로 끝나지 않는 것이 일반적으로 좋습니다. 이 중요성은 퍼센트 인코딩 바이트가 사용되는 위치에 따라 다릅니다. 예를 들어, 호스트 파서에서는 이 권고를 따르지 않으면 치명적이지만, URL 렌더링에서는 퍼센트 인코딩 바이트가 퍼센트 디코딩되어 렌더링되지 않습니다.
byte byte를 퍼센트 인코딩하려면, U+0025 (%) 뒤에 byte를 나타내는 두 개의 ASCII 대문자 16진수가 오는 문자열을 반환합니다.
byte sequence input을 퍼센트 디코딩하려면, 다음 절차를 수행합니다:
input에 ASCII 바이트가 아닌 바이트가 포함되어 있을 때 BOM 없이 UTF-8 디코드 외의 것을 사용하는 것은 안전하지 않으며 권장되지 않습니다.
-
output을 빈 byte sequence로 둡니다.
-
input의 각 byte에 대해:
-
byte가 0x25 (%)가 아니면 output에 byte를 추가합니다.
-
그렇지 않고, byte가 0x25 (%)이며 input의 byte 다음 두 바이트가 0x30(0)~0x39(9), 0x41(A)~0x46(F), 0x61(a)~0x66(f) 범위에 속하지 않으면 output에 byte를 추가합니다.
-
그 외의 경우:
-
bytePoint를 input의 byte 뒤의 두 바이트를 디코딩 후 16진수 숫자로 해석한 값으로 둡니다.
-
bytePoint 값을 가지는 바이트를 output에 추가합니다.
-
input의 다음 두 바이트를 건너뜁니다.
-
-
-
output을 반환합니다.
string input을 퍼센트 디코딩하려면:
일반적으로 퍼센트 인코딩 결과는 입력보다 U+0025 (%) 코드 포인트가 더 많고, 퍼센트 디코딩 결과는 입력보다 0x25 (%) 바이트가 더 적습니다.
percent-encode set은 집합이며, 코드 포인트의 집합이다.
C0 control percent-encode set은 percent-encode set이며, C0 제어 문자와 U+007E (~)보다 큰 모든 코드 포인트로 구성된다.
fragment percent-encode set은 percent-encode set이며, C0 control percent-encode set과 U+0020 SPACE, U+0022 ("), U+003C (<), U+003E (>), U+0060 (`)으로 이루어진다.
query percent-encode set은 percent-encode set이며, C0 control percent-encode set과 U+0020 SPACE, U+0022 ("), U+0023 (#), U+003C (<), U+003E (>)로 이루어진다.
query percent-encode set은 fragment percent-encode set에서 U+0060 (`)이 빠져있으므로 그와 같은 관점에서 정의할 수 없다.
special-query percent-encode set은 percent-encode set이며, query percent-encode set과 U+0027 (')으로 이루어진다.
path percent-encode set은 percent-encode set이며, query percent-encode set과 U+003F (?), U+005E (^), U+0060 (`), U+007B ({), U+007D (})로 이루어진다.
userinfo percent-encode set은 percent-encode set이며, path percent-encode set과 U+002F (/), U+003A (:), U+003B (;), U+003D (=), U+0040 (@), U+005B ([)부터 U+005D (])까지 포함하여, U+007C (|)도 포함한다.
component percent-encode set은 percent-encode set이며, userinfo percent-encode set과 U+0024 ($)부터 U+0026 (&)까지, U+002B (+), U+002C (,)을 포함한다.
이것은 HTML의
registerProtocolHandler()에서
사용되고,
다른 표준에서 데이터를 percent-encode 하여
URL의
경로(path),
쿼리(query),
프래그먼트(fragment)
혹은 불투명 호스트(opaque host)에
삽입하는 데에도 사용될 수 있다.
UTF-8
percent-encode와
함께 사용하면 JavaScript의
encodeURIComponent()와
동일한 결과를 준다. [HTML]
[ECMA-262]
application/x-www-form-urlencoded
percent-encode set은
percent-encode
set이며,
component percent-encode set과
U+0021 (!), U+0027 (')부터 U+0029 오른쪽 괄호, 그리고 U+007E (~)를 포함한다.
application/x-www-form-urlencoded
percent-encode set은
ASCII 영숫자,
U+002A (*), U+002D (-), U+002E (.), U+005F (_)를 제외한
모든 코드 포인트를 포함한다.
percent-encode after encoding 은 다음과 같이 주어진 인코딩(encoding) encoding, 스칼라 값 문자열(scalar value string) input, 그리고 percent-encode set percentEncodeSet을 사용한다:
-
단언: encoding은 UTF-8이거나 percentEncodeSet이 special-query percent-encode set 또는
application/x-www-form-urlencodedpercent-encode set이어야 한다. -
spaceAsPlus를 percentEncodeSet이
application/x-www-form-urlencodedpercent-encode set이면 true로, 그렇지 않으면 false로 한다. -
encoder를 인코더 가져오기를 encoding에 대해 실행한 결과로 한다.
-
inputQueue를 input을 I/O 큐로 변환한 값으로 한다.
-
output을 빈 문자열로 한다.
-
potentialError를 0으로 한다.
while 루프를 시작하려면 이 값이 null이 아니어야 한다.
-
potentialError가 null이 아닐 동안:
-
encodeOutput을 비어 있는 I/O 큐로 한다.
-
potentialError를 encode or fail을 inputQueue, encoder, encodeOutput으로 실행한 결과로 한다.
-
encodeOutput을 바이트 시퀀스로 변환한 각 byte에 대해:
-
spaceAsPlus가 true이고 byte가 0x20 (SP)이면, output에 U+002B (+)를 추가하고 계속한다.
-
단언: percentEncodeSet은 ASCII 코드 포인트가 아닌 모든 값을 포함한다.
-
isomorph가 percentEncodeSet에 없다면 output에 isomorph를 추가한다.
-
그렇지 않으면, percent-encode byte를 해서 결과를 output에 추가한다.
-
-
만약 potentialError가 null이 아니라면, output에 “
%26%23”, 그리고 ASCII 숫자로 potentialError를 10진수로 가장 짧은 시퀀스로 나타낸 뒤, “%3B”를 덧붙인다.이것은 encoding이 UTF-8이 아닐 때 발생할 수 있다.
-
-
output을 반환한다.
percentEncodeSet 인자 값 중 U+0025 (%)를 인코딩하여
“왕복 가능한 데이터(roundtripable data)”를 제공하는 것은
component percent-encode set과
application/x-www-form-urlencoded
percent-encode set
두 가지 뿐이다. percentEncodeSet 인자의 다른 값들
(즉, URL 파서에서
사용되는 값)은 U+0025 (%)를 변환하지 않고 넘겨서
적절하게 표현하려면 먼저
percent-encode 해야 한다.
UTF-8 percent-encode는 스칼라 값 scalarValue와 percentEncodeSet에 대해 percent-encode after encoding을 UTF-8, scalarValue(문자열), percentEncodeSet에 대해 수행한 결과를 반환한다.
UTF-8 percent-encode는 스칼라 값 문자열 input과 percentEncodeSet을 사용해 percent-encode after encoding을 UTF-8, input, percentEncodeSet으로 수행한 결과를 반환한다.
아래는 위에서 정의된 연산들의 예시 요약이다:
| Operation | Input | Output |
|---|---|---|
| Percent-encode input | 0x23 | "%23"
|
| 0x7F | "%7F"
| |
| Percent-decode input | `%25%s%1G`
| `%%s%1G`
|
| Percent-decode input | "‽%25%2E"
| 0xE2 0x80 0xBD 0x25 0x2E |
| Percent-encode after encoding with Shift_JIS, input, and the special-query percent-encode set | " "
| "%20"
|
"≡"
| "%81%DF"
| |
"‽"
| "%26%238253%3B"
| |
| Percent-encode after encoding with ISO-2022-JP, input, and the special-query percent-encode set | "¥"
| "%1B(J\%1B(B"
|
Percent-encode after encoding
with Shift_JIS, input, and
the application/x-www-form-urlencoded
percent-encode set
| "1+1 ≡ 2%20‽"
| "1%2B1+%81%DF+2%2520%26%238253%3B"
|
| UTF-8 percent-encode input using the userinfo percent-encode set | U+2261 (≡) | "%E2%89%A1"
|
| U+203D (‽) | "%E2%80%BD"
| |
| UTF-8 percent-encode input using the userinfo percent-encode set | "Say what‽"
| "Say%20what%E2%80%BD"
|
2. 보안 고려사항
URL의 보안은 그 환경에 따라 달라집니다. URL을 렌더링, 해석, 전달할 때 주의해야 합니다.
새 URL을 렌더링하거나 할당할 때 "스푸핑"을 고려해야 한다. 한 호스트 또는 URL이 다른 것과 혼동될 수 있는 공격이 있을 수 있다. 예를 들어, 1/l/I, m/rn/rri, 0/O, 그리고 а/a가 모두 아주 비슷하게 보일 수 있다. 더 심각하게는, U+202A 좌→우 임베딩(LEFT-TO-RIGHT EMBEDDING) 등과 같은 코드 포인트가 보이지 않는 경우도 있다. [UTR36]
URL을 A에서 B로 전달할 때 두 쪽 모두 신중하게 상황을 고려해야 합니다. A는 원하지 않는 데이터를 유출할 수 있고, B는 예상치 못한 입력을 받아 사용자에게 해를 끼칠 수 있습니다. 특히 B는 A를 절대 신뢰해서는 안 되며, 언제든지 A로부터 오는 URL이 신뢰할 수 없는 소스일 수 있습니다.
3. 호스트 (도메인 및 IP 주소)
상위 수준에서 호스트, 유효한 호스트 문자열, 호스트 파서, 호스트 직렬화기는 다음과 같이 연관됩니다:
-
호스트는 메모리 내 표현으로 볼 수 있습니다.
-
유효한 호스트 문자열은 호스트 파서에 입력될 때 검증 오류나 실패를 일으키지 않는 입력을 정의합니다. 즉, 규범적이고 유효한 입력입니다.
-
호스트 직렬화기는 호스트를 받아 ASCII 문자열을 반환합니다. (이 문자열을 파싱하면 결과가 직렬화된 호스트와 동등해야 합니다.)
파싱-직렬화 라운드트립의 결과는 호스트 파서의 isOpaque 인자에 따라 다음과 같습니다:
| 입력 | 출력 (isOpaque = false) | 출력 (isOpaque = true) |
|---|---|---|
EXAMPLE.COM
| example.com (도메인)
| EXAMPLE.COM (불투명 호스트)
|
example%2Ecom
| example%2Ecom (불투명 호스트)
| |
faß.example
| xn--fa-hia.example (도메인)
| fa%C3%9F.example (불투명 호스트)
|
0
| 0.0.0.0 (IPv4)
| 0 (불투명
호스트)
|
%30
| %30 (불투명
호스트)
| |
0x
| 0x (불투명
호스트)
| |
0xffffffff
| 255.255.255.255 (IPv4)
| 0xffffffff (불투명 호스트)
|
[0:0::1]
| [::1] (IPv6)
| |
[0:0::1%5D
| 실패 | |
[0:0::%31]
| ||
09
| 실패 | 09 (불투명
호스트)
|
example.255
| example.255 (불투명 호스트)
| |
example^example
| 실패 | |
3.1. 호스트 표현
호스트는 도메인, IP 주소, 불투명 호스트, 또는 빈 호스트입니다. 일반적으로 호스트는 네트워크 주소로 사용되지만, 네트워크 주소가 필요하지 않은 URL에서 불투명 식별자로 사용되기도 합니다.
전형적인 URL에서 host가 불투명 호스트인 예시는
git://github.com/whatwg/url.git입니다.
아래 문단에서 참조된 RFC는 정보 제공용입니다. 특별히 명시하지 않는 한 호스트 작성, 파싱, 직렬화에 영향을 주지 않습니다.
도메인은 네트워크 내 영역을 식별하는 비어 있지 않은 ASCII 문자열입니다. [RFC1034]
도메인 레이블은 도메인 domain을 U+002E(.)로 엄격하게 분할한 결과입니다.
example.com과 example.com. 도메인은 동등하지 않으며, 일반적으로 별개의 것으로 취급됩니다.
IPv4 주소는 네트워크 주소를 식별하는 32비트 부호 없는 정수입니다. [RFC791]
IPv6 주소는 네트워크 주소를 식별하는 128비트 부호 없는 정수입니다. 이 정수는 리스트로 이루어진 8개의 16비트 부호 없는 정수로 구성되며, IPv6 주소의 조각이라 부릅니다. [RFC4291]
<zone_id> 지원은 의도적으로 생략되었습니다.
불투명 호스트는 추가 처리가 가능한 비어 있지 않은 ASCII 문자열입니다.
빈 호스트는 빈 문자열입니다.
3.2. 호스트 기타
금지된 호스트 코드 포인트는 U+0000(NULL), U+0009(TAB), U+000A(LF), U+000D(CR), U+0020(공백), U+0023(#), U+002F(/), U+003A(:), U+003C(<), U+003E(>), U+003F(?), U+0040(@), U+005B([), U+005C(\), U+005D(]), U+005E(^), 또는 U+007C(|) 입니다.
금지된 도메인 코드 포인트는 금지된 호스트 코드 포인트, C0 제어 문자, U+0025(%), 또는 U+007F(DELETE)입니다.
호스트의 public suffix를 얻으려면 host host에 대해 다음 절차를 실행합니다. 결과는 null 또는 Public Suffix List에 포함된 host의 일부를 나타내는 도메인입니다. [PSL]
-
host가 도메인이 아니면 null을 반환합니다.
-
trailingDot을 host가 "."로 끝나면 "
.", 아니면 빈 문자열로 둡니다. -
publicSuffix를 host를 도메인으로 하여 Public Suffix List 알고리즘을 실행한 결과로 둡니다. [PSL]
-
단언(Assert): publicSuffix는 ASCII 문자열이며, 끝이 trailingDot으로 끝납니다.
-
publicSuffix를 반환합니다.
호스트의 등록 가능 도메인을 얻으려면 host host에 대해 다음 절차를 실행합니다. 결과는 null 또는 host의 public suffix와 그 앞의 도메인 레이블(있다면)로 구성된 도메인입니다.
-
host의 public suffix가 null이거나 host의 public suffix가 host와 동등하다면 null을 반환합니다.
-
trailingDot을 host가 "."로 끝나면 "
.", 아니면 빈 문자열로 둡니다. -
registrableDomain을 host를 도메인으로 하여 Public Suffix List 알고리즘을 실행한 결과로 둡니다. [PSL]
-
단언(Assert): registrableDomain은 ASCII 문자열이며, 끝이 trailingDot으로 끝납니다.
-
registrableDomain을 반환합니다.
| 호스트 입력 | Public suffix | 등록 가능 도메인 |
|---|---|---|
com
| com
| null |
example.com
| com
| example.com
|
www.example.com
| com
| example.com
|
sub.www.example.com
| com
| example.com
|
EXAMPLE.COM
| com
| example.com
|
example.com.
| com.
| example.com.
|
github.io
| github.io
| null |
whatwg.github.io
| github.io
| whatwg.github.io
|
إختبار
| xn--kgbechtv
| null |
example.إختبار
| xn--kgbechtv
| example.xn--kgbechtv
|
sub.example.إختبار
| xn--kgbechtv
| example.xn--kgbechtv
|
[2001:0db8:85a3:0000:0000:8a2e:0370:7334]
| null | null |
명세에서는 보안 결정을 위해 origin 개념을 우선적으로 사용해야 합니다. "public suffix"와 "등록 가능 도메인" 개념은 확실한 보안 경계를 제공하지 않으므로 신뢰할 수 없습니다. public suffix list는 클라이언트마다 다를 수 있습니다. 이 권고를 무시하는 명세는 URL의 scheme을 결정에 포함해야 할지 신중하게 고려해야 하며, 즉 same site 또는 schemelessly same site 개념을 사용할지 고려해야 합니다.
3.3. IDNA
도메인 파서 알고리즘은 스칼라 값 문자열 domain과 불리언 beStrict가 주어지면, 다음 단계를 실행한다. 이 단계들은 실패 또는 도메인을 반환한다.
-
beStrict가 true이면:
-
domain_name을 domain으로 설정하고, CheckHyphens를 true로, CheckBidi를 true로, CheckJoiners를 true로, UseSTD3ASCIIRules를 true로, Transitional_Processing를 false로, VerifyDnsLength를 true로, IgnoreInvalidPunycode를 false로 설정하여 Unicode ToASCII를 실행한 결과를 result라 하자. [UTS46]
-
result가 실패 값이면, domain-to-ASCII 검증 오류이며, 실패를 반환한다.
-
result를 반환한다.
-
-
result를 null로 하자.
-
domain이 ASCII 문자열이면:
-
domain_name을 domain으로 설정하고, CheckHyphens를 false로, CheckBidi를 true로, CheckJoiners를 true로, UseSTD3ASCIIRules를 false로, Transitional_Processing를 false로, VerifyDnsLength를 false로, IgnoreInvalidPunycode를 false로 설정하여 Unicode ToASCII를 실행한 결과가 실패 값이면, domain-to-ASCII 검증 오류이다. [UTS46]
-
result를 소문자화된 domain으로 설정한다.
beStrict가 false이고 domain이 ASCII 문자열인 경우, Unicode ToASCII 실패는 웹 호환성 때문에 전체 알고리즘 실패가 아니라 검증 오류만 발생시킨다. IgnoreInvalidPunycode만으로는 충분하지 않은데, Punycode가 성공적으로 디코드될 수 있지만 여전히 유효성 기준에는 실패할 수 있기 때문이다. 예를 들어
xn--8i7caa는www로 디코드되며, 그 코드 포인트들의 상태는 "mapped"이다. [UTS46] -
-
그렇지 않으면:
-
domain_name을 domain으로 설정하고, CheckHyphens를 false로, CheckBidi를 true로, CheckJoiners를 true로, UseSTD3ASCIIRules를 false로, Transitional_Processing를 false로, VerifyDnsLength를 false로, IgnoreInvalidPunycode를 false로 설정하여 Unicode ToASCII를 실행한 결과로 result를 설정한다. [UTS46]
-
result가 실패 값이면, domain-to-ASCII 검증 오류이며, 실패를 반환한다.
-
-
result가 빈 문자열이면, domain-to-ASCII 검증 오류이며, 실패를 반환한다.
-
result가 금지된 도메인 코드 포인트를 포함하면, domain-invalid-code-point 검증 오류이며, 실패를 반환한다.
웹 호환성 및 DNS 기반이 아닌 시스템과의 호환성 때문에 금지된 도메인 코드 포인트는 UseSTD3ASCIIRules가 true일 때 허용되지 않는 것들의 하위 집합이다. issue #397도 참조하라.
-
result를 반환한다.
이 문서와 웹 플랫폼 전반은 IDNA2008이 아니라
Unicode IDNA Compatibility Processing을 사용한다. 예를 들어,
☕.example은 실패가 아니라 xn--53h.example이 된다. [UTS46] [RFC5890]
도메인 domain이 주어졌을 때, domain to Unicode 알고리즘은 다음 단계를 실행한다:
-
domain_name을 domain으로 설정하고, CheckHyphens를 false로, CheckBidi를 true로, CheckJoiners를 true로, UseSTD3ASCIIRules를 false로, Transitional_Processing를 false로, IgnoreInvalidPunycode를 false로 설정하여 Unicode ToUnicode를 실행한 결과를 result라 하자. [UTS46]
-
오류가 기록되었다면, domain을 반환한다.
domain은 호스트 파서의 결과로만 나올 수 있으므로, 기록된 모든 오류는 이미 검증 오류로 표시되었을 것이다. domain을 반환하면 도메인 파서와 domain to Unicode가
xn--8i7caa와 같은 입력에서 왕복 변환되도록 보장한다. -
result를 반환한다.
3.4. 호스트 작성
유효한 호스트 문자열은 유효한 도메인 문자열, 유효한 IPv4 주소 문자열, 또는 다음이어야 한다: U+005B ([), 뒤이어 유효한 IPv6 주소 문자열, 뒤이어 U+005D (]).
문자열 input은 다음 단계들이 true를 반환하면 유효한 도메인이다:
-
domain을 input 및 true로 도메인 파서를 실행한 결과라 하자.
-
domain이 failure이면 false를 반환하고, 그렇지 않으면 true를 반환한다.
이상적으로는 이를 두더지 잡기식 방식이 아니라 유효한 도메인을 구성하는 코드 포인트 시퀀스로 정의한다: issue 245.
유효한 도메인 문자열은 유효한 도메인인 문자열이어야 한다.
유효한 IPv4 주소 문자열은 0부터 255까지의 범위에 있는 십진수를 나타내는 ASCII 숫자로 된 가능한 한 가장 짧은 문자열 네 개가 U+002E (.)로 서로 구분된 것이어야 한다.
유효한 IPv6 주소 문자열은 IP 버전 6 주소 지정 아키텍처의 "주소의 텍스트 표현" 장에서 정의된다. [RFC4291]
유효한 불투명 호스트 문자열은 다음 중 하나여야 한다:
-
금지된 호스트 코드 포인트를 제외한 하나 이상의 URL 단위
-
U+005B ([), 뒤이어 유효한 IPv6 주소 문자열, 뒤이어 U+005D (]).
이는 구별하기 위해 문맥이 필요하므로 유효한 호스트 문자열 정의의 일부가 아니다.
3.5. 호스트 파싱
호스트 파서는 선택적 불리언 isOpaque(기본값 false)와 함께 스칼라 값 문자열 input을 받아, 다음 단계를 실행한다. 이 단계들은 실패 또는 호스트를 반환한다.
-
input이 U+005B ([)로 시작하면:
-
input이 U+005D (])로 끝나지 않으면, IPv6-unclosed 검증 오류이며, 실패를 반환한다.
-
선행 U+005B ([)와 후행 U+005D (])를 제거한 input으로 IPv6 파싱을 수행한 결과를 반환한다.
-
-
isOpaque가 true이면, input으로 불투명 호스트 파싱을 수행한 결과를 반환한다.
-
Assert: input은 빈 문자열이 아니다.
-
input의 퍼센트 디코딩에 대해 BOM 없는 UTF-8 디코드를 실행한 결과를 domain이라 하자.
또는 실패에 대한 조기 반환과 결합하여 BOM 없는 UTF-8 디코드 또는 실패를 사용할 수도 있다. 이는 도메인 파서가 U+FFFD (�)에서 실패하기 때문이다.
-
domain 및 false로 도메인 파서를 실행한 결과를 asciiDomain이라 하자.
-
asciiDomain이 실패이면, 실패를 반환한다.
-
asciiDomain을 반환한다.
숫자로 끝나는지 검사기는 ASCII 문자열 input을 받아 다음 단계를 실행합니다. 이 단계들은 불리언을 반환합니다.
-
parts를 input을 U+002E (.)에서 엄격하게 분할한 결과로 둡니다.
-
parts의 마지막 항목이 빈 문자열이면:
-
last를 parts의 마지막 항목으로 둡니다.
-
last가 비어 있지 않고 ASCII 숫자만 포함하면, true를 반환합니다.
잘못된 입력 "
09"는 이후 단계에서 IPv4 파서에 의해 잡힙니다. -
last를 IPv4 숫자로 구문 분석한 결과가 실패를 반환하지 않으면, true를 반환합니다.
이는 last가 "
0X" 또는 "0x"이고, 그 뒤에 0개 이상의 ASCII 16진수 숫자가 오는지 검사하는 것과 같습니다. -
false를 반환합니다.
IPv4 파서는 ASCII 문자열 input을 받아 다음 단계를 실행합니다. 이 단계들은 실패 또는 IPv4 주소를 반환합니다.
IPv4 파서는 직접 호출되어서는 안 됩니다. 대신 호스트 파서의 반환값이 IPv4 주소인지 확인하십시오.
-
parts를 input을 U+002E (.)에서 엄격하게 분할한 결과로 둡니다.
-
parts의 마지막 항목이 빈 문자열이면:
-
parts의 크기가 4보다 크면, IPv4-too-many-parts 검증 오류, 실패를 반환합니다.
-
numbers를 빈 리스트로 둡니다.
-
parts의 각 part에 대해 반복합니다:
-
result를 part를 구문 분석한 결과로 둡니다.
-
result가 실패이면, IPv4-non-numeric-part 검증 오류, 실패를 반환합니다.
-
result[1]이 true이면, IPv4-non-decimal-part 검증 오류.
-
result[0]을 numbers에 추가합니다.
-
-
numbers의 어떤 항목이라도 255보다 크면, IPv4-out-of-range-part 검증 오류.
-
numbers에서 마지막 항목을 제외한 어떤 항목이라도 255보다 크면, 실패를 반환합니다.
-
ipv4를 numbers의 마지막 항목으로 둡니다.
-
counter를 0으로 둡니다.
-
numbers의 각 n에 대해 반복합니다:
-
ipv4를 n × 256(3 − counter)만큼 증가시킵니다.
-
counter를 1만큼 증가시킵니다.
-
-
ipv4를 반환합니다.
IPv4 숫자 파서는 ASCII 문자열 input을 받아 다음 단계를 실행합니다. 이 단계들은 실패 또는 숫자와 불리언의 튜플을 반환합니다.
-
input이 빈 문자열이면, 실패를 반환합니다.
-
validationError를 false로 둡니다.
-
R을 10으로 둡니다.
-
input이 적어도 두 개의 코드 포인트를 포함하고 첫 두 코드 포인트가 "
0X" 또는 "0x"이면:-
validationError를 true로 설정합니다.
-
input에서 첫 두 코드 포인트를 제거합니다.
-
R을 16으로 설정합니다.
-
-
그렇지 않고, input이 적어도 두 개의 코드 포인트를 포함하고 첫 코드 포인트가 U+0030 (0)이면:
-
validationError를 true로 설정합니다.
-
input에서 첫 코드 포인트를 제거합니다.
-
R을 8로 설정합니다.
-
-
input이 빈 문자열이면, (0, true)를 반환합니다.
-
input이 기수-R 숫자가 아닌 코드 포인트를 포함하면, 실패를 반환합니다.
-
output을 ASCII 16진수 숫자를 값 0부터 15까지의 숫자에 사용하여, input이 기수-R 표기법으로 나타내는 수학적 정수 값으로 둡니다.
-
(output, validationError)를 반환합니다.
IPv6 파서는 스칼라 값 문자열 input을 받아 다음 단계를 실행합니다. 이 단계들은 실패 또는 IPv6 주소를 반환합니다.
IPv6 파서는 이론상 직접 호출될 수 있지만, 실제로 그렇게 하기 전에 이 문서의 편집자들과 논의하십시오.
-
pieceIndex를 0으로 둡니다.
-
compress를 null로 둡니다.
-
pointer를 input에 대한 포인터로 둡니다.
-
c가 U+003A (:)이면:
-
remaining이 U+003A (:)로 시작하지 않으면, IPv6-invalid-compression 검증 오류, 실패를 반환합니다.
-
pointer를 2만큼 증가시킵니다.
-
pieceIndex를 1만큼 증가시킨 다음 compress를 pieceIndex로 설정합니다.
-
-
c가 EOF 코드 포인트가 아닌 동안:
-
pieceIndex가 8이면, IPv6-too-many-pieces 검증 오류, 실패를 반환합니다.
-
c가 U+003A (:)이면:
-
compress가 null이 아니면, IPv6-multiple-compression 검증 오류, 실패를 반환합니다.
- pointer와 pieceIndex를 1만큼 증가시키고, compress를 pieceIndex로 설정한 다음, 계속합니다.
-
-
value와 length를 0으로 둡니다.
-
length가 4보다 작고 c가 ASCII 16진수 숫자인 동안, value를 value × 0x10 + 16진수로 해석한 c로 설정하고, pointer와 length를 1씩 증가시킵니다.
-
c가 U+002E (.)이면:
-
length가 0이면, IPv4-in-IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
pointer를 length만큼 감소시킵니다.
-
pieceIndex가 6보다 크면, IPv4-in-IPv6-too-many-pieces 검증 오류, 실패를 반환합니다.
-
numbersSeen을 0으로 둡니다.
-
c가 EOF 코드 포인트가 아닌 동안:
-
ipv4Piece를 null로 둡니다.
-
numbersSeen이 0보다 크면:
-
c가 U+002E (.)이고 numbersSeen이 4보다 작으면, pointer를 1만큼 증가시킵니다.
- 그렇지 않으면, IPv4-in-IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
-
c가 ASCII 숫자가 아니면, IPv4-in-IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
-
number를 십진수로 해석한 c로 둡니다.
-
ipv4Piece가 null이면, ipv4Piece를 number로 설정합니다.
-
그렇지 않고, ipv4Piece가 0이면, IPv4-in-IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
그렇지 않으면, ipv4Piece를 ipv4Piece × 10 + number로 설정합니다.
-
ipv4Piece가 255보다 크면, IPv4-in-IPv6-out-of-range-part 검증 오류, 실패를 반환합니다.
-
pointer를 1만큼 증가시킵니다.
-
-
address[pieceIndex]를 address[pieceIndex] × 0x100 + ipv4Piece로 설정합니다.
-
numbersSeen을 1만큼 증가시킵니다.
-
numbersSeen이 2 또는 4이면, pieceIndex를 1만큼 증가시킵니다.
-
-
numbersSeen이 4가 아니면, IPv4-in-IPv6-too-few-parts 검증 오류, 실패를 반환합니다.
-
-
그렇지 않고, c가 U+003A (:)이면:
-
pointer를 1만큼 증가시킵니다.
-
c가 EOF 코드 포인트이면, IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
-
그렇지 않고, c가 EOF 코드 포인트가 아니면, IPv6-invalid-code-point 검증 오류, 실패를 반환합니다.
-
address[pieceIndex]를 value로 설정합니다.
-
pieceIndex를 1만큼 증가시킵니다.
-
-
compress가 null이 아니면:
-
swaps를 pieceIndex − compress로 둡니다.
-
pieceIndex를 7로 설정합니다.
-
pieceIndex가 0이 아니고 swaps가 0보다 큰 동안, address[pieceIndex]를 address[compress + swaps − 1]과 교환한 다음, pieceIndex와 swaps를 모두 1만큼 감소시킵니다.
-
-
그렇지 않고, compress가 null이고 pieceIndex가 8이 아니면, IPv6-too-few-pieces 검증 오류, 실패를 반환합니다.
-
address를 반환합니다.
불투명 호스트 파서는 스칼라 값 문자열 input을 받아 다음 단계를 실행합니다. 이 단계들은 실패 또는 불투명 호스트를 반환합니다.
-
input이 금지된 호스트 코드 포인트를 포함하면, host-invalid-code-point 검증 오류, 실패를 반환합니다.
-
input이 코드 포인트 중 URL 코드 포인트가 아니고 U+0025 (%)도 아닌 것을 포함하면, invalid-URL-unit 검증 오류.
-
input이 U+0025 (%)를 포함하고, 그 뒤의 두 코드 포인트가 ASCII 16진수 숫자가 아니면, invalid-URL-unit 검증 오류.
-
C0 제어 퍼센트 인코딩 집합을 사용해 input에 UTF-8 퍼센트 인코딩을 실행한 결과를 반환합니다.
3.6. 호스트 직렬화
IPv6 직렬화기는 IPv6 주소 address를 받아 다음 단계를 실행합니다. 이 단계들은 ASCII 문자열을 반환합니다.
-
output을 빈 문자열로 둡니다.
-
compress를 address가 주어졌을 때 IPv6 주소의 압축된 조각 인덱스를 찾은 결과로 둡니다.
-
ignore0을 false로 둡니다.
-
address의 조각들의 인덱스에 있는 각 pieceIndex에 대해 반복합니다:
-
ignore0이 true이고 address[pieceIndex]가 0이면, 계속합니다.
-
그렇지 않고, ignore0이 true이면, ignore0을 false로 설정합니다.
-
compress가 pieceIndex이면:
-
separator를 pieceIndex가 0이면 "
::"로, 그렇지 않으면 U+003A (:)로 둡니다. -
separator를 output에 추가합니다.
-
ignore0을 true로 설정하고 계속합니다.
-
-
address[pieceIndex]를 가능한 가장 짧은 소문자 16진수로 표현하여 output에 추가합니다.
-
pieceIndex가 7이 아니면, U+003A (:)를 output에 추가합니다.
-
-
output을 반환합니다.
이 알고리즘은 A Recommendation for IPv6 Address Text Representation의 권고를 필요로 합니다. [RFC5952]
IPv6 주소의 압축된 조각 인덱스를 찾으려면, IPv6 주소 address가 주어졌을 때:
-
longestIndex를 null로 둡니다.
-
longestSize를 1로 둡니다.
-
foundIndex를 null로 둡니다.
-
foundSize를 0으로 둡니다.
-
address의 조각들의 인덱스에 있는 각 pieceIndex에 대해 반복합니다:
-
address의 조각[pieceIndex]이 0이 아니면:
-
foundSize가 longestSize보다 크면, longestIndex를 foundIndex로 설정하고 longestSize를 foundSize로 설정합니다.
- foundIndex를 null로 설정합니다.
- foundSize를 0으로 설정합니다.
-
-
그렇지 않으면:
-
foundIndex가 null이면, foundIndex를 pieceIndex로 설정합니다.
-
foundSize를 1만큼 증가시킵니다.
-
-
-
foundSize가 longestSize보다 크면, foundIndex를 반환합니다.
-
longestIndex를 반환합니다.
3.7. 호스트 동등성
인증서 비교는 도메인의 끝점 점을 무시하는 호스트 동등성 비교가 필요합니다. 그러나 이러한 호스트는 DNS 길이 등 URL에서 강제하지 않는 다양한 측면도 강제됩니다. 이 둘을 더 가깝게 만들 방법이나 좋은 통합 모델에 관한 의견이 있으면 issue를 등록해주세요.
4. URL
상위 수준에서, URL, 유효한 URL 문자열, URL 파서, 그리고 URL 직렬화기는 다음과 같이 관련됩니다:
-
URL 파서는 임의의 스칼라 값 문자열을 받아 실패 또는 URL을 반환합니다. 또한 0개 이상의 검증 오류를 기록할 수도 있습니다.
-
URL은 메모리 내 표현으로 볼 수 있습니다.
-
유효한 URL 문자열은 어떤 입력이 URL 파서에 주어졌을 때 검증 오류나 실패를 발생시키지 않는지를 정의합니다. 즉, 적합하거나 유효하다고 간주되는 입력입니다.
-
URL 직렬화기는 URL을 받아 ASCII 문자열을 반환합니다. (그 문자열이 이후 구문 분석되면, 결과는 직렬화된 URL과 같게 됩니다.) URL 직렬화기의 출력이 항상 유효한 URL 문자열인 것은 아닙니다.
| 입력 | 기준(Base) | 유효성 | 출력 |
|---|---|---|---|
https:example.org
| ❌ | https://example.org/
| |
https://////example.com///
| ❌ | https://example.com///
| |
https://example.com/././foo
| ✅ | https://example.com/foo
| |
hello:world
| https://example.com/
| ✅ | hello:world
|
https:example.org
| https://example.com/
| ❌ | https://example.com/example.org
|
\example\..\demo/.\
| https://example.com/
| ❌ | https://example.com/demo/
|
example
| https://example.com/demo
| ✅ | https://example.com/example
|
file:///C|/demo
| ❌ | file:///C:/demo
| |
..
| file:///C:/demo
| ✅ | file:///C:/
|
file://loc%61lhost/
| ✅ | file:///
| |
https://user:password@example.org/
| ❌ | https://user:password@example.org/
| |
https://example.org/foo bar
| ❌ | https://example.org/foo%20bar
| |
https://EXAMPLE.com/../x
| ✅ | https://example.com/x
| |
https://ex ample.org/
| ❌ | 실패 | |
example
| ❌, 기준 없음 때문 | 실패 | |
https://example.com:demo
| ❌ | 실패 | |
http://[www.example.com]/
| ❌ | 실패 | |
https://example.org//
| ✅ | https://example.org//
| |
https://example.com/[]?[]#[]
| ❌ | https://example.com/[]?[]#[]
| |
https://example/%?%#%
| ❌ | https://example/%?%#%
| |
https://example/%25?%25#%25
| ✅ | https://example/%25?%25#%25
|
4.1. URL 표현
URL은 범용 식별자를 나타내는 구조체입니다. 유효한 URL 문자열과 구분하기 위해, URL 레코드라고도 부를 수 있습니다.
URL의 스킴은 ASCII 문자열로, URL의 유형을 식별하며 구문 분석 후 추가 처리를 위해 URL을 전달하는 데 사용할 수 있습니다. 초기값은 빈 문자열입니다.
URL의 사용자 이름은 사용자 이름을 식별하는 ASCII 문자열입니다. 초기값은 빈 문자열입니다.
URL의 비밀번호는 비밀번호를 식별하는 ASCII 문자열입니다. 초기값은 빈 문자열입니다.
URL의 호스트는 null 또는 호스트입니다. 초기값은 null입니다.
다음 표는 허용되는 URL의 scheme / host 조합을 보여줍니다.
| scheme | host | |||||
|---|---|---|---|---|---|---|
| 도메인 | IPv4 주소 | IPv6 주소 | 불투명 호스트 | 빈 호스트 | null | |
특수 scheme (단
"file" 제외)
| ✅ | ✅ | ✅ | ❌ | ❌ | ❌ |
"file"
| ✅ | ✅ | ✅ | ❌ | ✅ | ❌ |
| 기타 | ❌ | ❌ | ✅ | ✅ | ✅ | ✅ |
URL의 port는 null 또는 네트워킹 포트를 식별하는 16비트 부호 없는 정수입니다. 처음에는 null입니다.
URL의 path는 보통 위치를 식별하는 URL 경로입니다. 처음에는 « »입니다.
특수한 URL의 경로는 항상 리스트입니다. 즉, 불투명하지 않습니다.
URL의 query는 null 또는 ASCII 문자열입니다. 처음에는 null입니다.
URL의 fragment는 null 또는 ASCII 문자열이며, URL의 다른 컴포넌트가 식별하는 리소스에서 추가 처리에 사용할 수 있습니다. 처음에는 null입니다.
URL에는 null 또는 blob URL entry인 blob URL entry가 연결되어 있습니다. 처음에는 null입니다.
이는 "blob" URL이 참조하는 객체와 그 origin을 캐싱하는 데 사용됩니다. URL이 파싱과 fetch 사이에 blob URL store에서 제거되어도
fetch가 성공해야 하므로 캐싱이 중요합니다.
다음 표는 유효한 URL 문자열을 파싱했을 때 URL의 컴포넌트로 어떻게 매핑되는지를 보여줍니다. username, password, blob URL entry는 생략되었으며, 아래 예시에서는 각각 빈 문자열, 빈 문자열, null입니다.
| 입력 | 스킴 | 호스트 | 포트 | 경로 | 쿼리 | fragment |
|---|---|---|---|---|---|---|
https://example.com/
| "https"
| "example.com"
| null | « 빈 문자열 » | null | null |
https://localhost:8000/search?q=text#hello
| "https"
| "localhost"
| 8000 | « "search" »
| "q=text"
| "hello"
|
urn:isbn:9780307476463
| "urn"
| null | null | "isbn:9780307476463"
| null | null |
file:///ada/Analytical%20Engine/README.md
| "file"
| 빈 문자열 | null | « "ada", "Analytical%20Engine", "README.md" »
| null | null |
URL 경로는 URL 경로 세그먼트 또는 0개 이상의 URL 경로 세그먼트의 리스트입니다.
URL 경로 세그먼트는 ASCII 문자열입니다. 일반적으로 디렉터리나 파일을 가리키지만, 사전에 정의된 의미는 없습니다.
A
단일 점 URL 경로 세그먼트는
"."이거나 "%2e"에 대한 ASCII
대소문자 구분 없는
일치인 URL 경로 세그먼트입니다.
A
이중 점 URL 경로 세그먼트는
".."이거나 ".%2e", "%2e.", 또는 "%2e%2e"에 대한
ASCII
대소문자 구분 없는
일치인 URL 경로 세그먼트입니다.
4.2. URL 기타
특수 스킴은 다음 표의 첫 번째 열에 나열된 ASCII 문자열입니다. 특수 스킴의 기본 포트는 같은 행의 두 번째 열에 나열됩니다. 다른 모든 ASCII 문자열에 대한 기본 포트는 null입니다.
| 특수 scheme | 기본 포트 |
|---|---|
"ftp"
| 21 |
"file"
| null |
"http"
| 80 |
"https"
| 443 |
"ws"
| 80 |
"wss"
| 443 |
URL이 특수하다는 URL의 scheme이 특수 scheme일 때입니다. URL이 특수하지 않다는 URL의 scheme이 특수 scheme이 아닐 때입니다.
URL은 자격 증명을 포함한다는 username 또는 password가 빈 문자열이 아닐 때입니다.
URL은 불투명 경로를 가진다는 것은 경로가 URL 경로 세그먼트일 때입니다.
URL은 username/password/port를 가질 수
없다는 host가
null이나 빈 문자열이거나, scheme이
"file"일 때입니다.
URL은 기본 URL로 지정될 수 있습니다.
기본 URL은 입력이 상대-URL 문자열일 수 있을 때 URL 파서에 유용합니다.
Windows 드라이브 문자는 두 개의 코드 포인트로, 첫 번째는 ASCII 알파벳이고 두 번째는 U+003A(:) 또는 U+007C(|)입니다.
정규화된 Windows 드라이브 문자는 두 번째 코드 포인트가 U+003A(:)인 Windows 드라이브 문자입니다.
URL 작성 섹션에 따라, 오직 정규화된 Windows 드라이브 문자만 적합합니다.
문자열이 Windows 드라이브 문자로 시작한다는 다음 조건을 모두 만족할 때입니다:
- 문자열의 길이가 2 이상이다
- 첫 두 코드 포인트가 Windows 드라이브 문자이다
- 문자열의 길이가 2이거나, 세 번째 코드 포인트가 U+002F(/), U+005C(\), U+003F(?), U+0023(#) 중 하나이다.
url의 경로를 단축하기 절차:
4.3. URL 작성
유효한 URL 문자열은 relative-URL-with-fragment 문자열 또는 absolute-URL-with-fragment 문자열이어야 합니다.
absolute-URL-with-fragment 문자열은 absolute-URL 문자열이며, 선택적으로 U+0023(#)와 URL-fragment 문자열이 뒤따를 수 있습니다.
absolute-URL 문자열은 다음 중 하나여야 합니다:
-
URL 스킴 문자열로, ASCII 대소문자 구분 없는 방식으로 특수 스킴과 일치하고 "
file"과는 ASCII 대소문자 구분 없는 방식으로 일치하지 않으며, 그 뒤에 U+003A (:)와 스킴 상대 특수 URL 문자열이 오는 것 -
URL 스킴 문자열로, ASCII 대소문자 구분 없는 방식으로 특수 스킴과 일치하지 않는 것이며, 그 뒤에 U+003A (:)와 상대 URL 문자열이 오는 것
-
URL 스킴 문자열로, ASCII 대소문자 구분 없는 방식으로 "
file"과 일치하며, 그 뒤에 U+003A (:)와 스킴 상대 file URL 문자열이 오는 것
위 모두는 선택적으로 U+003F(?)와 URL-query 문자열이 뒤따를 수 있습니다.
URL-scheme 문자열은 하나의 ASCII 알파벳 뒤에 0개 이상의 ASCII 영숫자, U+002B(+), U+002D(-), U+002E(.)가 올 수 있습니다. scheme은 IANA URI [sic] Schemes 레지스트리에 등록해야 합니다. [IANA-URI-SCHEMES] [RFC7595]
relative-URL-with-fragment 문자열은 relative-URL 문자열이며, 선택적으로 U+0023(#)와 URL-fragment 문자열이 뒤따를 수 있습니다.
relative-URL 문자열은 기본 URL의 scheme에 따라 다음 중 하나여야 합니다:
- 특수 scheme, 단
"
file" 제외 -
scheme-relative-special-URL 문자열
- "
file" -
path-absolute-URL 문자열 (기본 URL의 host가 빈 호스트일 때)
path-absolute-non-Windows-file-URL 문자열 (기본 URL의 host가 빈 호스트가 아닐 때)
- 기타
-
위 모두는 선택적으로 U+003F(?)와 URL-query 문자열이 뒤따를 수 있습니다.
상대-URL 문자열을 파싱할 때는 기본 URL이 null이 아니어야 합니다.
scheme-relative-special-URL 문자열은 "//" 뒤에 유효한 호스트 문자열, 선택적으로
U+003A(:)와 URL-port 문자열,
선택적으로 path-absolute-URL 문자열이 뒤따라야 합니다.
URL-port 문자열은 다음 중 하나여야 합니다:
-
빈 문자열
-
하나 이상의 ASCII 숫자로, 10진수로 표현된 16비트 부호 없는 정수여야 합니다.
scheme-relative-URL 문자열은
"//" 뒤에 불투명-호스트-및-포트 문자열, 선택적으로 path-absolute-URL 문자열이 뒤따라야
합니다.
불투명-호스트-및-포트 문자열은 빈 문자열이거나, 유효한 불투명 호스트 문자열 뒤에 선택적으로 U+003A(:)와 URL-port 문자열이 올 수 있습니다.
scheme-relative-file-URL 문자열은
"//" 뒤에 다음 중 하나여야 합니다:
path-absolute-URL 문자열은 U+002F(/) 뒤에 path-relative-URL 문자열이 와야 합니다.
path-absolute-non-Windows-file-URL 문자열은 path-absolute-URL 문자열로, U+002F(/)로 시작하지 않으며, U+002F(/) 뒤에 Windows 드라이브 문자와 다시 U+002F(/)가 오지 않아야 합니다.
path-relative-URL 문자열은 0개 이상의 URL-path-segment 문자열로, U+002F(/)로 구분되며, 처음이 U+002F(/)가 아니어야 합니다.
path-relative-scheme-less-URL 문자열은 path-relative-URL 문자열로, 시작이 URL-scheme 문자열과 U+003A(:)가 아니어야 합니다.
URL-path-segment 문자열은 다음 중 하나여야 합니다:
-
U+002F(/), U+003F(?)를 제외한 0개 이상의 URL 유닛으로 구성되고, 전체가 단일 점 URL 경로 세그먼트 또는 이중 점 URL 경로 세그먼트가 아니어야 함.
URL-query 문자열은 0개 이상의 URL 유닛입니다.
URL-fragment 문자열은 0개 이상의 URL 유닛입니다.
URL 코드 포인트는 ASCII 영숫자, U+0021(!), U+0024($), U+0026(&), U+0027('), U+0028((), U+0029()), U+002A(*), U+002B(+), U+002C(,), U+002D(-), U+002E(.), U+002F(/), U+003A(:), U+003B(;), U+003D(=), U+003F(?), U+0040(@), U+005F(_), U+007E(~), 그리고 U+00A0~U+10FFFD 범위의 코드 포인트(서러것 및 비문자 제외)입니다.
U+007F(DELETE) 초과 코드 포인트는 URL 파서에서 퍼센트 인코딩 바이트로 변환됩니다.
HTML에서 문서 인코딩이 레거시 인코딩일 경우, URL-query 문자열의 U+007F(DELETE) 초과 코드 포인트는 문서의 인코딩을 사용하여 퍼센트 인코딩 바이트로 변환됩니다. 이는 한 문서에서 동작하는 URL이 다른 인코딩을 사용하는 문서에 복사되면 문제가 생길 수 있습니다. UTF-8 인코딩을 항상 사용하면 이 문제가 해결됩니다.
예를 들어 다음 HTML 문서를 생각해보세요:
<!doctype html>
< meta charset = "windows-1252" >
< a href = "?smörgåsbord" > Test</ a >
문서 인코딩이 windows-1252이므로, 링크의 URL의 query는 "sm%F6rg%E5sbord"가 됩니다. 만약 인코딩이 UTF-8이었다면
"sm%C3%B6rg%C3%A5sbord"가 되었을 것입니다.
URL 유닛은 URL 코드 포인트와 퍼센트 인코딩 바이트입니다.
퍼센트 인코딩 바이트는 URL 코드 포인트가 아니거나 기록이 금지된 코드 포인트를 인코딩하는 데 사용할 수 있습니다.
username 또는 password를 URL 레코드에서 유효한 URL 문자열로 표현할 방법은 없습니다.
4.4. URL 파싱
URL 파서는 스칼라 값 문자열 input과 선택적 null 또는 기본 URL base(기본값 null), 선택적 encoding encoding(기본값 UTF-8)을 받아, 다음 단계를 실행합니다:
웹 브라우저가 아닌 구현체는 기본 URL 파서만 구현하면 됩니다.
웹 브라우저 주소창의 사용자 입력이 URL 레코드로 변환되는 과정은 이 표준의 범위에 포함되지 않습니다. 신뢰 결정과 관련된 URL 렌더링 요구사항은 포함되어 있습니다.
-
url을 기본 URL 파서를 input, base, encoding에 대해 실행한 결과로 둡니다.
-
url이 실패면 실패 반환.
-
url의 scheme이 "
blob"이 아니면 url 반환. -
url의 blob URL entry를 blob URL 해석 url 실행 결과(실패가 아니면)로, 실패면 null로 설정.
-
url 반환.
기본 URL 파서는 스칼라 값 문자열 input과 선택적 null 또는 기본 URL base(기본값 null), 선택적 encoding encoding(기본값 UTF-8), 선택적 URL url, 선택적 상태 오버라이드 state override를 받아 다음 단계를 실행합니다:
encoding 인자는 레거시 개념으로 HTML에만 관련 있습니다. url과 state override 인자는 다양한 API만 사용합니다. [HTML]
url과 state override 인자가 전달되지 않으면 기본 URL 파서는 새 URL 또는 실패를 반환합니다. 전달되면, 알고리즘은 전달된 url을 수정하며 반환 없이 종료할 수 있습니다.
-
url이 주어지지 않았다면:
-
url을 새 URL로 설정합니다.
-
input이 선행 또는 후행 C0 제어 문자 또는 공백을 포함하면, invalid-URL-unit 검증 오류.
-
input에서 모든 선행 및 후행 C0 제어 문자 또는 공백을 제거합니다.
-
-
input이 ASCII 탭 또는 줄바꿈을 포함하면, invalid-URL-unit 검증 오류.
-
input에서 모든 ASCII 탭 또는 줄바꿈을 제거합니다.
-
state를 state override가 주어졌다면 그것으로, 그렇지 않으면 스킴 시작 상태로 둡니다.
-
encoding을 encoding에서 출력 인코딩 얻기를 수행한 결과로 설정합니다.
-
buffer를 빈 문자열로 둡니다.
-
atSignSeen, insideBrackets, passwordTokenSeen을 false로 둡니다.
-
pointer를 input에 대한 포인터로 둡니다.
-
state에 따라 전환하면서 다음 상태 기계를 계속 실행합니다. 실행 후 pointer가 EOF 코드 포인트를 가리키면, 다음 단계로 갑니다. 그렇지 않으면, pointer를 1만큼 증가시키고 상태 기계를 계속합니다.
- 스킴 시작 상태
- 스킴 상태
-
-
c가 ASCII 영숫자, U+002B (+), U+002D (-), 또는 U+002E (.)이면, c를 소문자화하여 buffer에 추가합니다.
-
그렇지 않고, c가 U+003A (:)이면:
-
state override가 주어졌다면:
-
url의 스킴을 buffer로 설정합니다.
-
state override가 주어졌다면:
-
buffer를 빈 문자열로 설정합니다.
-
url의 스킴이 "
file"이면:-
remaining이 "
//"로 시작하지 않으면, special-scheme-missing-following-solidus 검증 오류. -
state를 file 상태로 설정합니다.
-
-
그렇지 않고, url이 특수하고, base가 null이 아니며, base의 스킴이 url의 스킴이라면:
-
state를 특수 상대 또는 권한 상태로 설정합니다.
-
그렇지 않고, url이 특수하면, state를 특수 권한 슬래시 상태로 설정합니다.
-
그렇지 않고, remaining이 U+002F (/)로 시작하면, state를 경로 또는 권한 상태로 설정하고 pointer를 1만큼 증가시킵니다.
-
-
그렇지 않고, state override가 주어지지 않았다면, buffer를 빈 문자열로 설정하고, state를 스킴 없음 상태로 설정한 다음, (input의 첫 번째 코드 포인트부터) 다시 시작합니다.
-
그렇지 않으면, 실패를 반환합니다.
이 실패 표시는 오직
Location객체의protocolsetter에서만 사용됩니다. 또한, 이 상태에서 앞서 나오는 실패가 아닌 종료는 해당 setter를 정의하기 위한 의도적인 차이입니다.
-
- 스킴 없음 상태
-
-
base가 null이거나, base가 불투명 경로를 갖고 c가 U+0023 (#)이 아니면, missing-scheme-non-relative-URL 검증 오류, 실패를 반환합니다.
-
그렇지 않고, base가 불투명 경로를 갖고 c가 U+0023 (#)이면, url의 스킴을 base의 스킴으로, url의 경로를 base의 경로로, url의 쿼리를 base의 쿼리로, url의 프래그먼트를 빈 문자열로 설정하고, state를 프래그먼트 상태로 설정합니다.
-
그렇지 않고, base의 스킴이 "
file"이 아니면, state를 상대 상태로 설정하고 pointer를 1만큼 감소시킵니다. -
그렇지 않으면, state를 file 상태로 설정하고 pointer를 1만큼 감소시킵니다.
-
- 특수 상대 또는 권한 상태
-
-
c가 U+002F (/)이고 remaining이 U+002F (/)로 시작하면, state를 특수 권한 슬래시 무시 상태로 설정하고 pointer를 1만큼 증가시킵니다.
-
그렇지 않으면, special-scheme-missing-following-solidus 검증 오류를 발생시키고, state를 상대 상태로 설정한 뒤 pointer를 1만큼 감소시킵니다.
-
- 경로 또는 권한 상태
- 상대 상태
-
-
Assert: base의 스킴은 "
file"이 아닙니다. -
그렇지 않고, url이 특수하고 c가 U+005C (\)이면, invalid-reverse-solidus 검증 오류를 발생시키고, state를 상대 슬래시 상태로 설정합니다.
-
그렇지 않으면:
-
- 상대 슬래시 상태
- 특수 권한 슬래시 상태
-
-
c가 U+002F (/)이고 remaining이 U+002F (/)로 시작하면, state를 특수 권한 슬래시 무시 상태로 설정하고 pointer를 1만큼 증가시킵니다.
-
그렇지 않으면, special-scheme-missing-following-solidus 검증 오류를 발생시키고, state를 특수 권한 슬래시 무시 상태로 설정한 뒤 pointer를 1만큼 감소시킵니다.
-
- 특수 권한 슬래시 무시 상태
- 권한 상태
-
-
c가 U+0040 (@)이면:
-
atSignSeen이 true이면, "
%40"을 buffer 앞에 붙입니다. -
atSignSeen을 true로 설정합니다.
-
buffer의 각 codePoint에 대해:
-
codePoint가 U+003A (:)이고 passwordTokenSeen이 false이면, passwordTokenSeen을 true로 설정하고 계속합니다.
-
encodedCodePoints를 userinfo 퍼센트 인코딩 집합을 사용해 codePoint에 UTF-8 퍼센트 인코딩을 실행한 결과로 둡니다.
-
passwordTokenSeen이 true이면, encodedCodePoints를 url의 비밀번호에 추가합니다.
-
그렇지 않으면, encodedCodePoints를 url의 사용자 이름에 추가합니다.
-
-
buffer를 빈 문자열로 설정합니다.
-
그렇지 않고, 다음 중 하나가 true이면:
-
c가 EOF 코드 포인트, U+002F (/), U+003F (?), 또는 U+0023 (#)입니다
그러면:
-
atSignSeen이 true이고 buffer가 빈 문자열이면, host-missing 검증 오류, 실패를 반환합니다.
-
pointer를 buffer의 코드 포인트 길이 + 1만큼 감소시키고, buffer를 빈 문자열로 설정하며, state를 호스트 상태로 설정합니다.
-
-
그렇지 않으면, c를 buffer에 추가합니다.
-
- 호스트 상태
- 호스트명 상태
-
-
state override가 주어지고 url의 스킴이 "
file"이면, pointer를 1만큼 감소시키고 state를 file 호스트 상태로 설정합니다. -
그렇지 않고, c가 U+003A (:)이고 insideBrackets가 false이면:
-
그렇지 않고, 다음 중 하나가 true이면:
-
c가 EOF 코드 포인트, U+002F (/), U+003F (?), 또는 U+0023 (#)입니다
그러면 pointer를 1만큼 감소시키고, 다음을 수행합니다:
-
url이 특수하고 buffer가 빈 문자열이면, host-missing 검증 오류, 실패를 반환합니다.
-
그렇지 않고, state override가 주어졌고, buffer가 빈 문자열이며, url이 자격 증명을 포함하거나 url의 포트가 null이 아니면, 실패를 반환합니다.
-
host가 실패이면, 실패를 반환합니다.
-
state override가 주어졌다면, 반환합니다.
-
-
그렇지 않으면:
-
- 포트 상태
-
-
그렇지 않고, 다음 중 하나가 true이면:
-
c가 EOF 코드 포인트, U+002F (/), U+003F (?), 또는 U+0023 (#)입니다;
-
state override가 주어졌습니다,
그러면:
-
buffer가 빈 문자열이 아니면:
-
port를 값 0부터 9까지의 숫자에 ASCII 숫자를 사용해 기수 10으로 buffer가 나타내는 수학적 정수 값으로 둡니다.
-
port가 16비트 부호 없는 정수가 아니면, port-out-of-range 검증 오류, 실패를 반환합니다.
-
port가 url의 스킴의 기본 포트이면 url의 포트를 null로 설정하고, 그렇지 않으면 port로 설정합니다.
-
buffer를 빈 문자열로 설정합니다.
-
state override가 주어졌다면, 반환합니다.
-
-
state override가 주어졌다면, 실패를 반환합니다.
-
state를 경로 시작 상태로 설정하고 pointer를 1만큼 감소시킵니다.
-
-
그렇지 않으면, port-invalid 검증 오류, 실패를 반환합니다.
- file 상태
-
-
url의 스킴을 "
file"로 설정합니다. -
url의 호스트를 빈 문자열로 설정합니다.
-
c가 U+002F (/) 또는 U+005C (\)이면:
-
c가 U+005C (\)이면, invalid-reverse-solidus 검증 오류.
-
state를 file 슬래시 상태로 설정합니다.
-
-
그렇지 않고, base가 null이 아니고 base의 스킴이 "
file"이면:-
url의 호스트를 base의 호스트로, url의 경로를 base의 경로의 복제본으로, 그리고 url의 쿼리를 base의 쿼리로 설정합니다.
-
그렇지 않고, c가 U+0023 (#)이면, url의 프래그먼트를 빈 문자열로 설정하고 state를 프래그먼트 상태로 설정합니다.
-
그렇지 않고, c가 EOF 코드 포인트가 아니면:
-
url의 쿼리를 null로 설정합니다.
-
pointer에서 input의 끝까지의 코드 포인트 부분 문자열이 Windows 드라이브 문자로 시작하지 않으면, url의 경로를 단축합니다.
-
그렇지 않으면:
-
url의 경로를 « »로 설정합니다.
이는 (플랫폼 독립적인) Windows 드라이브 문자 특이 사항입니다.
-
state를 경로 상태로 설정하고 pointer를 1만큼 감소시킵니다.
-
-
-
그렇지 않으면, state를 경로 상태로 설정하고, pointer를 1만큼 감소시킵니다.
-
- file 슬래시 상태
-
-
c가 U+002F (/) 또는 U+005C (\)이면:
-
c가 U+005C (\)이면, invalid-reverse-solidus 검증 오류.
-
state를 file 호스트 상태로 설정합니다.
-
-
그렇지 않으면:
-
base가 null이 아니고 base의 스킴이 "
file"이면:-
pointer에서 input의 끝까지의 코드 포인트 부분 문자열이 Windows 드라이브 문자로 시작하지 않고, base의 경로[0]이 정규화된 Windows 드라이브 문자이면, base의 경로[0]을 url의 경로에 추가합니다.
이는 (플랫폼 독립적인) Windows 드라이브 문자 특이 사항입니다.
-
state를 경로 상태로 설정하고, pointer를 1만큼 감소시킵니다.
-
-
- file 호스트 상태
-
-
c가 EOF 코드 포인트, U+002F (/), U+005C (\), U+003F (?), 또는 U+0023 (#)이면, pointer를 1만큼 감소시킨 다음:
-
state override가 주어지지 않았고 buffer가 Windows 드라이브 문자이면, file-invalid-Windows-drive-letter-host 검증 오류를 발생시키고, state를 경로 상태로 설정합니다.
이는 (플랫폼 독립적인) Windows 드라이브 문자 특이 사항입니다. 여기서 buffer는 재설정되지 않고 대신 경로 상태에서 사용됩니다.
-
그렇지 않고, buffer가 빈 문자열이면:
-
그렇지 않으면, 다음 단계를 실행합니다:
-
-
그렇지 않으면, c를 buffer에 추가합니다.
-
- 경로 시작 상태
-
-
url이 특수하면:
-
c가 U+005C (\)이면, invalid-reverse-solidus 검증 오류.
-
state를 경로 상태로 설정합니다.
-
c가 U+002F (/) 및 U+005C (\) 중 어느 것도 아니면, pointer를 1만큼 감소시킵니다.
-
-
그렇지 않고, state override가 주어지지 않았고 c가 U+003F (?)이면, url의 쿼리를 빈 문자열로 설정하고 state를 쿼리 상태로 설정합니다.
-
그렇지 않고, state override가 주어지지 않았고 c가 U+0023 (#)이면, url의 프래그먼트를 빈 문자열로 설정하고 state를 프래그먼트 상태로 설정합니다.
-
그렇지 않고, c가 EOF 코드 포인트가 아니면:
-
그렇지 않고, state override가 주어졌으며 url의 호스트가 null이면, 빈 문자열을 url의 경로에 추가합니다.
-
- 경로 상태
-
-
다음 중 하나가 true이면:
-
c가 EOF 코드 포인트 또는 U+002F (/)입니다
-
state override가 주어지지 않았고 c가 U+003F (?) 또는 U+0023 (#)입니다
그러면:
-
url이 특수하고 c가 U+005C (\)이면, invalid-reverse-solidus 검증 오류.
-
buffer가 이중 점 URL 경로 세그먼트이면:
-
그렇지 않고, buffer가 단일 점 URL 경로 세그먼트이며, c가 U+002F (/)도 아니고, url이 특수하며 c가 U+005C (\)인 것도 아니면, 빈 문자열을 url의 경로에 추가합니다.
-
그렇지 않고, buffer가 단일 점 URL 경로 세그먼트가 아니면:
-
buffer를 빈 문자열로 설정합니다.
-
c가 U+0023 (#)이면, url의 프래그먼트를 빈 문자열로 설정하고 state를 프래그먼트 상태로 설정합니다.
-
-
그렇지 않으면, 다음 단계를 실행합니다:
-
c가 URL 코드 포인트가 아니고 U+0025 (%)도 아니면, invalid-URL-unit 검증 오류.
-
c가 U+0025 (%) 이고 remaining이 두 개의 ASCII 16진수 숫자로 시작하지 않으면, invalid-URL-unit 검증 오류.
-
경로 퍼센트 인코딩 집합을 사용해 c에 UTF-8 퍼센트 인코딩을 수행하고, 그 결과를 buffer에 추가합니다.
-
-
- 불투명 경로 상태
-
-
그렇지 않고, c가 U+0023 (#)이면, url의 프래그먼트를 빈 문자열로 설정하고 state를 프래그먼트 상태로 설정합니다.
-
그렇지 않고, c가 U+0020 SPACE이면:
-
그렇지 않고, c가 EOF 코드 포인트가 아니면:
-
c가 URL 코드 포인트가 아니고 U+0025 (%)도 아니면, invalid-URL-unit 검증 오류.
-
c가 U+0025 (%) 이고 remaining이 두 개의 ASCII 16진수 숫자로 시작하지 않으면, invalid-URL-unit 검증 오류.
-
C0 제어 퍼센트 인코딩 집합을 사용해 c에 UTF-8 퍼센트 인코딩을 수행하고, 그 결과를 url의 경로에 추가합니다.
-
- 쿼리 상태
-
-
encoding이 UTF-8이 아니고 다음 중 하나가 true이면:
그러면 encoding을 UTF-8로 설정합니다.
-
다음 중 하나가 true이면:
-
state override가 주어지지 않았고 c가 U+0023 (#)입니다
-
c가 EOF 코드 포인트입니다
그러면:
-
queryPercentEncodeSet을 url이 특수하면 special-query 퍼센트 인코딩 집합으로, 그렇지 않으면 쿼리 퍼센트 인코딩 집합으로 둡니다.
-
encoding, buffer, queryPercentEncodeSet을 사용해 인코딩 후 퍼센트 인코딩을 수행하고, 그 결과를 url의 쿼리에 추가합니다.
이 작업은 상태를 가지는 ISO-2022-JP 인코더 때문에 코드 포인트별로 호출할 수 없습니다.
-
buffer를 빈 문자열로 설정합니다.
-
c가 U+0023 (#)이면, url의 프래그먼트를 빈 문자열로 설정하고 state를 프래그먼트 상태로 설정합니다.
-
-
그렇지 않고, c가 EOF 코드 포인트가 아니면:
-
c가 URL 코드 포인트가 아니고 U+0025 (%)도 아니면, invalid-URL-unit 검증 오류.
-
c가 U+0025 (%) 이고 remaining이 두 개의 ASCII 16진수 숫자로 시작하지 않으면, invalid-URL-unit 검증 오류.
-
c를 buffer에 추가합니다.
-
-
- 프래그먼트 상태
-
-
c가 EOF 코드 포인트가 아니면:
-
c가 URL 코드 포인트가 아니고 U+0025 (%)도 아니면, invalid-URL-unit 검증 오류.
-
c가 U+0025 (%) 이고 remaining이 두 개의 ASCII 16진수 숫자로 시작하지 않으면, invalid-URL-unit 검증 오류.
-
프래그먼트 퍼센트 인코딩 집합을 사용해 c에 UTF-8 퍼센트 인코딩을 수행하고, 그 결과를 url의 프래그먼트에 추가합니다.
-
-
-
url을 반환합니다.
username 설정을 url과 username에 대해 실행할 때, url의 username을 username에 UTF-8 퍼센트 인코드를 userinfo percent-encode set으로 실행한 결과로 설정한다.
password 설정을 url과 password에 대해 실행할 때, url의 password를 password에 UTF-8 퍼센트 인코드를 userinfo percent-encode set으로 실행한 결과로 설정한다.
4.5. URL 직렬화
URL 직렬화기는 URL url과, 선택적 불리언 fragment 제외(기본값 false)를 받아 다음 단계를 실행한다. 반환값은 ASCII 문자열이다.
-
output을 url의 scheme과 U+003A(:)를 연결한 값으로 둔다.
-
url의 host가 null이 아니면:
-
url의 host가 null이고, url이 불투명 경로를 가지지 않으며, url의 경로의 크기가 1보다 크고, url의 경로[0]이 빈 문자열이면, U+002F(/)와 U+002E(.)를 output에 추가한다.
이것은
web+demo:/.//not-a-host/또는web+demo:/path/..//not-a-host/가 파싱 후 직렬화되어web+demo://not-a-host/가 되지 않게 한다(결과는web+demo:/.//not-a-host/). -
URL 경로 직렬화를 url에 대해 실행한 결과를 output에 추가.
-
exclude fragment가 false이고 url의 fragment가 null이 아니면, U+0023(#)와 url의 fragment를 output에 추가.
-
output을 반환.
4.6. URL 동등성
URL A가 URL B와 동일한지 판단할 때, 선택적 불리언 fragment 제외(기본값: false)와 함께 다음 단계를 실행한다:
-
serializedA를 직렬화를 A에 대해 fragment 제외를 fragment 제외로 하여 실행한 결과로 둔다.
-
serializedB를 직렬화를 B에 대해 fragment 제외를 fragment 제외로 하여 실행한 결과로 둔다.
-
serializedA가 serializedB와 같으면 true를, 아니면 false를 반환한다.
4.7. 오리진
오리진의 정의는 HTML에서 필수 배경 정보를 참고하세요. [HTML]
URL url의 오리진은 아래 단계들을 실행하여 얻어지는 오리진으로, url의 스킴에 따라 분기한다:
- "
blob" -
-
url의 blob URL entry가 null이 아니면, url의 blob URL entry의 environment의 오리진을 반환.
-
pathURL을 파싱한 URL 경로 직렬화 url의 결과로 둔다.
-
pathURL이 실패면 새 불투명 오리진을 반환한다.
-
pathURL의 scheme이 "
http", "https", 또는 "file"이면 pathURL의 오리진을 반환한다. -
새 불투명 오리진을 반환한다.
blob:https://whatwg.org/d0360e2f-caee-469f-9a2f-87d5b0456f6f의 오리진은 튜플 오리진 ("https", "whatwg.org", null, null)이다. -
- "
ftp"- "
http"- "
https"- "
ws"- "
wss" - "
- "
file" -
유감스럽게도, 이는 독자에게 맡깁니다. 확실하지 않을 때는 새 불투명 오리진을 반환하세요.
- 그 외
-
새 불투명 오리진을 반환한다.
4.8. URL 렌더링
URL은 아래에 설명된 수정과 함께 직렬화된 형태로 렌더링되어야 한다. 이는 URL을 표시하는 주요 목적이 사용자가 보안 또는 신뢰 결정을 내리게 하는 경우에 적용된다. 예를 들어, 사용자는 브라우저 주소창에 렌더링된 URL을 기반으로 신뢰 결정을 내릴 것으로 기대된다.
4.8.1. 사람이 읽기 어려운 또는 중요하지 않은 구성요소 단순화
스푸핑 기회를 제공하거나 보안 관련 정보를 방해할 수 있는 구성요소를 제거한다:
-
브라우저는 URL의 host만 렌더링할 수 있다. 이는 최종 사용자가 host와 경로 등 URL의 다른 부분을 구별하는 것이 중요한 경우에 적용된다. 브라우저는 host를 더 단순화하여 등록 가능 도메인에 주의를 끌도록 고려할 수 있다. 예를 들어, 브라우저는 앞쪽의
www또는m도메인 레이블을 생략하여 host를 단순화하거나, 등록 가능 도메인만 표시하여 서브도메인이 제공하는 스푸핑 기회를 제거할 수 있다(https://examplecorp.attacker.com/등). -
브라우저는 URL의 username과 password를 렌더링해서는 안 된다. 이는 host로 오인될 수 있기 때문이다(
https://examplecorp.com@attacker.example/등). -
브라우저는 표시 영역이 단일 스킴만 허용하는 경우 URL의 scheme을 표시하지 않을 수 있다(예: 브라우저 기능이
https://를 생략하는 경우). 그렇지 않으면 스킴을 사람이 읽을 수 있는 문자열(예: "보안 아님"), 보안 표시 아이콘 또는 둘 모두로 대체하거나 보충할 수 있다.
4.8.2. 생략(Elision)
공간이 제한된 표시에서는 사용자가 보안 결정을 내릴 때 오해하지 않도록 URL을 신중하게 생략해야 한다:
-
브라우저는 URL을 렌더링할 때 최소한 등록 가능 도메인이 보여질 수 있도록 해야 한다(예:
...examplecorp.com만 보여주고 실제로는https://not-really-examplecorp.com/를 로딩하는 경우를 피함). -
전체 host를 렌더링할 수 없을 때, 브라우저는 가장 낮은 수준의 도메인 레이블부터 생략해야 한다. 예를 들어,
examplecorp.com.evil.com은...com.evil.com로 생략되어야 하며examplecorp.com...로 생략해서는 안 된다. (양방향 텍스트에서는 가장 낮은 도메인 레이블이 왼쪽에 표시되지 않을 수도 있음)
4.8.3. 국제화 및 특수 문자
국제화 도메인 이름(IDN), 특수 문자 및 양방향 텍스트는 스푸핑을 방지하기 위해 주의해서 처리해야 한다:
-
URL의 호스트가 도메인이면, 브라우저는 URL의 호스트로 domain to Unicode를 실행하여 이를 렌더링해야 한다.
동형이의어 스푸핑 공격에는 다양한 문자가 사용될 수 있다. 혼동하기 쉬운 문자를 탐지하고 사용 중일 때 경고하는 것을 고려하라. [IDNFAQ] [UTS39]
-
URL은 양방향 텍스트를 포함할 때 호스트와 경로 사이의 혼동이 특히 발생하기 쉬우므로, 이 경우에는 URL의 호스트만 렌더링하는 것이 특히 권장된다. 가독성을 위해, URL의 다른 부분을 렌더링하는 경우에는, 그러한 퍼센트 인코딩된 바이트 시퀀스를 해당 시퀀스의 퍼센트 디코딩에 대해 BOM 없는 UTF-8 디코드를 실행하여 얻은 코드 포인트로 대체해야 한다. 단, 그렇게 렌더링했을 때 해당 시퀀스가 보이지 않게 되는 경우는 제외한다. 브라우저는 스푸핑 위험을 나타내는 특정 시퀀스(예: U+1F512 (🔒))를 디코드하지 않도록 선택할 수 있다.
-
브라우저는 양방향 텍스트를 왼쪽에서 오른쪽 임베딩 안에 있는 것처럼 렌더링해야 한다. [BIDI]
안타깝게도, 렌더링된 URL은 문자열이며 어디에나 나타날 수 있으므로, 렌더링된 URL을 위한 특정 양방향 알고리즘은 널리 채택되지 않을 것이다. 양방향 텍스트는 URL의 각 부분과 상호작용하여 렌더링이 모델과 달라질 수 있다. 양방향 언어 사용자들은 특히 일반 텍스트 환경에서 이를 예상하게 될 수 있다.
5.
application/x-www-form-urlencoded
application/x-www-form-urlencoded 포맷은
목록에 있는 튜플 각각을 name과
value로 구성된 쌍으로 인코딩하는 방법을 제공한다.
application/x-www-form-urlencoded 포맷은 여러 면에서 이상하고 기형적인 결과물이며, 수년간 구현
사고와 타협의 결과로 상호운용성을 위해 필요한 요구사항 집합으로 이어졌지만, 결코 좋은 설계 관행을 나타내지는 않는다. 특히, 반복적(때로는 중첩된) 문자 인코딩과 바이트 시퀀스 간 변환의 꼬인
세부사항을 주의 깊게 살펴야 한다. 안타깝게도 HTML 폼의 보편적 사용으로 인해 이 포맷은 널리 쓰이고 있다. [HTML]
5.1. application/x-www-form-urlencoded 파싱
레거시 서버 중심 구현은 인코딩이 UTF-8이 아닌
경우나 name이 `_charset`인 튜플에 대해 특별한 처리 로직을 지원해야 할 수 있다. 이러한 로직은 여기서 기술하지 않으며, UTF-8만이
준수하는
인코딩이다.
application/x-www-form-urlencoded 파서는 바이트 시퀀스
input을 받아 다음 단계를 실행한다:
-
sequences를 input을 0x26(&)으로 분할한 결과로 둔다.
-
output을 name과 value가 문자열을 담는 튜플로 구성된, 초기에는 빈 목록으로 둔다.
-
각 바이트 시퀀스 bytes에 대해 sequences에서:
-
bytes가 빈 바이트 시퀀스이면 계속.
-
bytes에 0x3D(=)가 있으면, name을 bytes의 처음부터 첫 번째 0x3D(=) 직전까지의 바이트로, value를 첫 번째 0x3D(=) 이후부터 끝까지의 바이트로 둔다. 0x3D(=)가 첫 번째 바이트면 name은 빈 바이트 시퀀스가 되고, 마지막이면 value는 빈 바이트 시퀀스가 된다.
-
그 외에는 name을 bytes 값으로, value를 빈 바이트 시퀀스로 둔다.
-
name과 value의 모든 0x2B(+)를 0x20(SP)로 치환한다.
-
nameString과 valueString을 각각 BOM 없는 UTF-8 디코드를 퍼센트 디코딩된 name과 value에 대해 실행한 결과로 둔다.
-
append (nameString, valueString)를 output에 추가.
-
-
output을 반환한다.
5.2. application/x-www-form-urlencoded 직렬화
application/x-www-form-urlencoded 직렬화기는
name-value 튜플 tuples 목록과 선택적 인코딩
encoding(기본 UTF-8)을 받아 다음 단계를 실행한다. 반환값은 ASCII 문자열이다.
-
encoding을 output encoding을 얻기를 encoding에 대해 실행한 결과로 설정한다.
-
output을 빈 문자열로 한다.
-
각 tuple에 대해 tuples에서 반복한다:
-
name을 다음의 결과로 한다: percent-encode after encoding을 encoding, tuple의 name, 그리고
application/x-www-form-urlencodedpercent-encode set으로 실행한 결과. -
value를 다음의 결과로 한다: percent-encode after encoding을 encoding, tuple의 value, 그리고
application/x-www-form-urlencodedpercent-encode set으로 실행한 결과. -
output이 빈 문자열이 아니라면 U+0026 (&)를 output에 추가한다.
- name을 추가하고 U+003D (=)를 추가한 뒤 value를 output에 추가한다.
- output을 반환한다.
5.3. 후크(Hooks)
application/x-www-form-urlencoded 문자열 파서는 스칼라 값 문자열 input을 받아 UTF-8로 인코드하고, 그 결과를
application/x-www-form-urlencoded 파싱에 넘긴 결과를
반환한다.
6. API
이 절에서는 Web IDL의 용어를 사용한다. 브라우저 사용자 에이전트는 이 API를 반드시 지원해야 한다. JavaScript 구현도 이 API를 지원해야 한다. 기타 사용자 에이전트나 프로그래밍 언어는 자신들의 필요에 맞는 적절한 API를 사용하는 것이 권장되며, 반드시 이 API일 필요는 없다. [WEBIDL]
6.1. URL 클래스
[Exposed=*,LegacyWindowAlias =]webkitURL interface {URL constructor (USVString ,url optional USVString );base static URL ?parse (USVString ,url optional USVString );base static boolean canParse (USVString ,url optional USVString );base stringifier attribute USVString href ;readonly attribute USVString origin ;attribute USVString protocol ;attribute USVString username ;attribute USVString password ;attribute USVString host ;attribute USVString hostname ;attribute USVString port ;attribute USVString pathname ;attribute USVString search ; [SameObject ]readonly attribute URLSearchParams searchParams ;attribute USVString hash ;USVString toJSON (); };
URL 객체에는 다음이 연관되어 있다:
- URL: URL 값.
- query 객체:
URLSearchParams객체.
new URL(url, base) 생성자 단계는 다음과 같다:
-
parsedURL을 API URL 파서를 url에 base(있으면)와 함께 실행한 결과로 둔다.
-
parsedURL이 실패면 TypeError 예외를 던진다.
-
initialize를 this와 parsedURL에 실행.
문자열을 URL로 파싱하려면 기준 URL 없이 URL 생성자에 인자를 하나만 넘겨서
호출한다:
var input = "https://example.org/💩" ,
url = new URL( input)
url. pathname // "/%F0%9F%92%A9"
입력이 상대-URL 문자열이면 예외가 발생한다:
try {
var url = new URL( "/🍣🍺" )
} catch ( e) {
// that happened
}
이 경우에는 기준 URL이 필요하다:
var input = "/🍣🍺" ,
url = new URL( input, document. baseURI)
url. href // "https://url.spec.whatwg.org/%F0%9F%8D%A3%F0%9F%8D%BA"
URL 객체는 기준 URL로도 사용할 수
있다(IDL은 인자에 문자열을 요구하며, URL 객체는 href
getter의 반환값으로 문자열화된다):
var url = new URL( "🏳️🌈" , new URL( "https://pride.example/hello-world" ))
url. pathname // "/%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88"
static parse(url, base) 메서드 단계:
-
parsedURL을 API URL 파서를 url에 base(있으면)와 함께 실행한 결과로 둔다.
-
parsedURL이 실패면 null을 반환.
-
url을 새
URL객체로 둔다. -
initialize를 url과 parsedURL에 실행.
-
url을 반환.
정적 canParse(url, base)
메서드 단계:
-
parsedURL에 API URL 파서를 url과 base가 있는 경우 실행한 결과를 할당합니다.
-
parsedURL이 실패면 false를 반환합니다.
-
true를 반환합니다.
href
setter 단계:
-
parsedURL에 basic URL 파서를 입력값에 실행한 결과를 할당합니다.
-
this의 query object의 list를 비웁니다.
-
query가 null이 아니면 this의 query object의 list에 파싱 query 결과를 할당합니다.
protocol
setter 단계는
basic
URL 파싱을 입력값과 U+003A (:)가 뒤따르도록 한 후
this의 URL을 url로
하고
scheme start
state를 state override로 지정하여 실행합니다.
username
setter 단계:
-
this의 URL이 username/password/port를 가질 수 없으면 return.
-
set the username을 this의 URL과 입력값으로 수행합니다.
password
setter 단계:
-
this의 URL이 username/password/port를 가질 수 없으면 return.
-
set the password를 this의 URL과 입력값으로 수행합니다.
host getter 단계:
host
setter 단계:
-
this의 URL이 opaque path를 가지면 return.
-
Basic URL 파서를 입력값에 this의 URL을 url로, host state를 state override로 지정해 실행합니다.
만약
host
setter에 주어진 값에 port가
없다면, this의
URL의 port는 변경되지 않습니다.
host getter는 URL-port string을 반환하므로, setter도 항상 둘 다 "리셋"된다고 기대할 수 있으나 그렇지 않을 수
있습니다.
hostname
setter 단계:
-
this의 URL이 opaque path를 가지면 return.
-
Basic URL 파서를 입력값에 this의 URL을 url로, hostname state를 state override로 지정해 실행합니다.
port
setter 단계:
-
this의 URL이 username/password/port를 가질 수 없으면 return.
-
그 밖의 경우, basic URL 파서를 입력값에 this의 URL을 url로, port state를 state override로 지정해 실행합니다.
pathname getter 단계는
URL 경로 시리얼라이즈된
this의 URL을 반환합니다.
pathname
setter 단계:
-
this의 URL이 opaque path를 가지면 return.
-
Basic URL 파서를 입력값에 this의 URL을 url로, path start state를 state override로 지정해 실행합니다.
search getter 단계:
search
setter 단계:
-
입력값이 빈 문자열이면 url의 query를 null로, 비우기 this의 query object의 list를 비우고 return.
-
input에 입력값에서 선행 U+003F (?) 1개를 제거한 값을 할당합니다.
-
url의 query를 빈 문자열로 설정합니다.
-
Basic URL 파서를 input과 url을 url, query state를 state override로 지정해 실행합니다.
-
this의 query object의 list에 파싱 input 결과를 할당합니다.
searchParams getter 단계는
this의 query
object를 반환합니다.
hash getter 단계:
hash
setter 단계:
-
input에 입력값에서 선행 U+0023 (#) 1개를 제거한 값을 할당합니다.
-
Basic URL 파서를 input과 this의 URL을 url로, fragment state를 state override로 지정해 실행합니다.
6.2. URLSearchParams 클래스
[Exposed=*]interface {URLSearchParams constructor (optional (sequence <sequence <USVString >>or record <USVString ,USVString >or USVString )= "");init readonly attribute unsigned long size ;undefined append (USVString ,name USVString );value undefined delete (USVString ,name optional USVString );value USVString ?get (USVString );name sequence <USVString >getAll (USVString );name boolean has (USVString ,name optional USVString );value undefined set (USVString ,name USVString );value undefined sort ();iterable <USVString ,USVString >;stringifier ; };
URLSearchParams
객체를 생성하고 문자열화하는 것은 꽤 간단하다:
let params = new URLSearchParams({ key: "730d67" })
params. toString() // "key=730d67"
URLSearchParams
객체는 내부적으로 application/x-www-form-urlencoded
포맷을 사용하므로,
특정 코드 포인트의 인코딩 방식이 URL 객체(예를 들면
href
및 search)
와 다를 수 있다.
특히 searchParams
를 사용해 URL의 query를 조작할 때 이런
차이로 인해 놀랄 수 있다.
const url = new URL( 'https://example.com/?a=b ~' );
console. log( url. href); // "https://example.com/?a=b%20~"
url. searchParams. sort();
console. log( url. href); // "https://example.com/?a=b+%7E"
const url = new URL( 'https://example.com/?a=~&b=%7E' );
console. log( url. search); // "?a=~&b=%7E"
console. log( url. searchParams. get( 'a' )); // "~"
console. log( url. searchParams. get( 'b' )); // "~"
URLSearchParams
객체는
application/x-www-form-urlencoded
percent-encode set에 포함된 모든 것을 percent-encode하며,
U+0020 SPACE는 U+002B(+)로 인코딩한다.
인코딩은 무시하고(UTF-8 사용), search
는
query
percent-encode set이나 special-query percent-encode set에
포함된 모든 것을 percent-encode한다(해당 URL이 special인지에 따라 다름).
URLSearchParams
객체에는 다음이 연관되어 있다:
initialize를 URLSearchParams
객체 query에 init으로 실행할 때:
update를 URLSearchParams
객체 query에 실행할 때:
new URLSearchParams(init)
생성자 단계는 다음과 같다:
-
init이 문자열이고 앞에 U+003F(?)가 있으면 처음 코드 포인트를 제거한다.
-
initialize를 this와 init에 실행한다.
delete(name, value)
메서드 단계는 다음과 같다:
getAll(name) 메서드 단계는
this의
list에서 name이 name인 모든 tuple의
value를 리스트 순서대로 반환하며, 없으면 빈 sequence를 반환합니다.
has(name, value)
메서드 단계:
set(name, value)
메서드 단계:
URLSearchParams
객체에서 name-value 튜플을 정렬하는 것은 캐시 적중률을 높이는 등 유용할 수 있습니다. 이 작업은
sort()
메서드를 호출해 수행할 수 있습니다:
const url = new URL( "https://example.org/?q=🏳️🌈&key=e1f7bc78" );
url. searchParams. sort();
url. search; // "?key=e1f7bc78&q=%F0%9F%8F%B3%EF%B8%8F%E2%80%8D%F0%9F%8C%88"
입력을 변경하지 않고 예를 들어 비교 목적처럼 사용하려면 새 URLSearchParams
객체를 생성하세요:
const sorted = new URLSearchParams( url. search)
sorted. sort()
sort() 메서드 단계:
반복에 사용할 value pair는 this의 list의 tuples이며, key는 name이고 value는 value입니다.
문자열화 동작 단계는 시리얼라이징된 this의 list를 반환합니다.
6.3. 다른 곳의 URL API
URL를 노출하는 표준은
내부 URL을
시리얼라이즈하여
문자열로 노출해야 합니다.
표준은 URL 객체로
URL을 노출해서는 안 됩니다.
URL 객체는
URL 조작을 위해 사용되는 것입니다.
IDL에서는 USVString 타입을 사용해야 합니다.
여기서 더 높은 수준의 개념은 값들이 불변 데이터 구조로 노출되어야 한다는 것이다.
표준이 자신이 정의하는 기능에 "URL"이라는 이름의 변형을 사용하기로 한다면, 해당 기능의 이름을 "url"(소문자, 끝에 "l" 포함)로 지어야 한다. "URL", "URI", "IRI"와 같은 이름은 사용하지 않아야 한다. 다만, 이름이 복합어일 경우 "URL"(대문자)이 선호된다. 예: "newURL", "oldURL".
HTML의 EventSource
및 HashChangeEvent
인터페이스는 적절한 명명 예시이다. [HTML]
감사의 글
수년간 URL을 더 상호운용성 있게 만드는데 많은 분들이 도움을 주었으며, 이 표준의 목표를 더욱 발전시켰습니다. 마찬가지로 많은 분들이 이 표준이 오늘날의 모습이 되도록 도왔습니다.
이에 대해, 100の人, Adam Barth, Addison Phillips, Adrián Chaves, Adrien Ricciardi, Albert Wiersch, Alex Christensen, Alexandre Morgaut, Alexis Hunt, Alwin Blok, Andrew Sullivan, Arkadiusz Michalski, Behnam Esfahbod, Bobby Holley, Boris Zbarsky, Brad Hill, Brandon Ross, Cailyn Hansen, Chris Dumez, Chris Rebert, Corey Farwell, Dan Appelquist, Daniel Bratell, Daniel Stenberg, David Burns, David Håsäther, David Sheets, David Singer, David Walp, Domenic Denicola, Emily Schechter, Emily Stark, Eric Lawrence, Erik Arvidsson, Gavin Carothers, Geoff Richards, Glenn Maynard, Gordon P. Hemsley, hemanth, Henri Sivonen, Ian Hickson, Ilya Grigorik, Italo A. Casas, Jakub Gieryluk, James C. Wise, James Graham, James Manger, James Ross, Jeff Hodges, Jeffrey Posnick, Jeffrey Yasskin, Joe Duarte, Joshua Bell, Jxck, Karl Wagner, Kemal Zebari, 田村健人 (Kent TAMURA), Kevin Grandon, Kornel Lesiński, Larry Masinter, Leif Halvard Silli, Mark Amery, Mark Davis, Marcos Cáceres, Marijn Kruisselbrink, Martin Dürst, Mathias Bynens, Matt Falkenhagen, Matt Giuca, Michael Peick, Michael™ Smith, Michal Bukovský, Michel Suignard, Mikaël Geljić, Nikita Skovoroda, Noah Levitt, Peter Occil, Philip Jägenstedt, Philippe Ombredanne, Prayag Verma, Rimas Misevičius, Robert Kieffer, Rodney Rehm, Roy Fielding, Ryan Sleevi, Sam Ruby, Sam Sneddon, Santiago M. Mola, Sebastian Mayr, Shannon Booth, Simon Pieters, Simon Sapin, Steven Vachon, Stuart Cook, Sven Uhlig, Tab Atkins, 吉野剛史 (Takeshi Yoshino), Tantek Çelik, Tiancheng "Timothy" Gu, Tim Berners-Lee, 簡冠庭 (Tim Guan-tin Chien), Titi_Alone, Tomek Wytrębowicz, Trevor Rowbotham, Tristan Seligmann, Valentin Gosu, Vyacheslav Matva, Wei Wang, Wolf Lammen, 山岸和利 (Yamagishi Kazutoshi), Yongsheng Zhang, 成瀬ゆい (Yui Naruse), 그리고 zealousidealroll 여러분께 진심으로 감사드립니다!
이 표준은 Anne van Kesteren (Apple, annevk@annevk.nl)이 작성했습니다.
지적 재산권
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 이 저작물은 크리에이티브 커먼즈 저작자 표시 4.0 국제 라이선스에 따라 라이선스가 부여됩니다. 소스 코드에 포함된 부분에 대해서는, 해당 부분은 BSD 3-Clause 라이선스에 따라 소스 코드에 라이선스가 부여됩니다.
이 문서는 현행 표준(Living Standard)입니다. 특허 심사 버전에 관심이 있다면 현행 표준 심사 초안을 참고하십시오.