목표
이 표준의 목표는 웹 플랫폼 전반에 걸쳐 패칭을 통합하고, 이에 관련된 모든 것에 대해 일관된 처리를 제공하는 것입니다. 여기에는 다음이 포함됩니다:
- URL 스킴
- 리디렉션
- 교차 출처(Cross-origin) 의미
- CSP [CSP]
- 패치 메타데이터 [FETCH-METADATA]
- 서비스 워커 [SW]
- 혼합 콘텐츠 [MIX]
- 비보안 요청 업그레이드 [UPGRADE-INSECURE-REQUESTS]
- `
Referer` [REFERRER]
이를 위해 HTTP `Origin` 헤더 의미를
원래 The Web Origin Concept에서 정의했던 것보다 대체합니다. [ORIGIN]
1. 서문
상위 관점에서 리소스를 패칭하는 것은 꽤 단순한 작업입니다. 요청이 들어가고, 응답이 나옵니다. 하지만 그 작업의 세부사항은 매우 복잡하며, 예전에는 명확하게 문서화되지 않았고 API마다 다르게 동작했습니다.
수많은 API가 리소스를 패치하는 기능을 제공합니다. 예를 들면 HTML의 img와
script 요소, CSS의 cursor와 list-style-image,
navigator.sendBeacon() 및 self.importScripts() 같은 JavaScript
API들이 있습니다. 패치 표준은 이러한 기능들을 위한 통합된 아키텍처를 제공하여, 리디렉션 및
CORS 프로토콜 등 패칭의 다양한 측면에서 모두 일관성을 갖도록 합니다.
패치 표준은 또한 fetch() JavaScript API를 정의하며,
이는 대부분의 네트워킹 기능을 비교적 낮은 추상화 수준에서 노출합니다.
2. 인프라스트럭처
이 명세는 Infra 표준에 의존합니다. [INFRA]
이 명세는 ABNF, Encoding, HTML, HTTP, MIME Sniffing, Streams, URL, Web IDL, WebSockets, 그리고 WebTransport에서 용어를 사용합니다. [ABNF] [ENCODING] [HTML] [HTTP] [MIMESNIFF] [STREAMS] [URL] [WEBIDL] [WEBSOCKETS] [WEBTRANSPORT]
ABNF는 HTTP에서 확장된 ABNF(특히
#의 추가)와 RFC 7405를 의미합니다. [RFC7405]
인증 정보(Credentials)는 HTTP 쿠키, TLS 클라이언트 인증서, 그리고 인증 항목(HTTP 인증용)입니다. [COOKIES] [TLS] [HTTP]
fetch params는 struct로, fetch 알고리즘에서 부기 용도로 사용됩니다. 다음과 같은 항목을 가집니다:
- request
- request.
- 요청 본문 청크 길이 처리
(기본값 null)
- process request end-of-body (기본값 null)
- process early hints response (기본값 null)
- process response (기본값 null)
- process response end-of-body (기본값 null)
- process response consume body (기본값 null)
- process request end-of-body (기본값 null)
- Null 또는 알고리즘.
- task destination (기본값 null)
- Null, global object, 또는 parallel queue.
- cross-origin isolated capability (기본값 false)
- 불리언 값.
- controller (기본값 새 fetch controller)
- fetch controller.
- timing info
- fetch timing info.
- preloaded response candidate (기본값 null)
- Null, "
pending", 또는 response.
fetch controller는 struct로, fetch 호출자가 시작 후 특정 작업을 수행할 수 있도록 합니다. 다음과 같은 항목을 가집니다:
- state (기본값 "
ongoing") - "
ongoing", "terminated", 또는 "aborted" - full timing info (기본값 null)
- Null 또는 fetch timing info.
- report timing steps (기본값 null)
- Null 또는 global object를 인자로 받는 알고리즘.
- serialized abort reason (기본값 null)
- Null 또는 Record (StructuredSerialize 결과).
- next manual redirect steps (기본값 null)
- Null 또는 인자를 받지 않는 알고리즘.
특정 fetch controller controller에 대해 타이밍 보고(report timing)를 하려면, global object global을 받아 다음을 실행합니다:
-
Assert: controller의 report timing steps가 null이 아님을 확인합니다.
-
controller의 report timing steps를 global과 함께 호출합니다.
특정 fetch controller controller에 대해 다음 수동 리디렉트 처리를 하려면:
-
Assert: controller의 next manual redirect steps가 null이 아님을 확인합니다.
-
controller의 next manual redirect steps를 호출합니다.
fetch controller controller에 대해 전체 타이밍 정보 추출을 하려면:
-
Assert: controller의 full timing info가 null이 아님을 확인합니다.
-
controller의 full timing info를 반환합니다.
특정 fetch controller controller에 대해 선택적 error와 함께 abort 하려면:
-
controller의 state를 "
aborted"로 설정합니다. -
fallbackError를 "
AbortError"DOMException으로 둡니다. -
error가 주어지지 않았다면 fallbackError로 설정합니다.
-
serializedError를 StructuredSerialize(error)로 둡니다. 예외가 발생하면 serializedError를 StructuredSerialize(fallbackError)로 둡니다.
-
controller의 serialized abort reason을 serializedError로 설정합니다.
null 또는 Record abortReason 및 realm realm이 주어졌을 때 serialize된 abort reason 역직렬화는 다음과 같습니다:
-
fallbackError를 "
AbortError"DOMException으로 둡니다. -
deserializedError를 fallbackError로 둡니다.
-
abortReason이 null이 아니면, deserializedError를 StructuredDeserialize(abortReason, realm)로 둡니다. 예외가 발생하거나 undefined를 반환하면 deserializedError를 fallbackError로 둡니다.
-
deserializedError를 반환합니다.
fetch controller
controller를 종료(terminate)하려면, controller의 state를
"terminated"로 설정합니다.
fetch params
fetchParams는, 그 controller의 state가
"aborted"일 때 중단(aborted) 상태입니다.
fetch params
fetchParams는, 그 controller의 state가
"aborted" 또는 "terminated"일 때 취소(canceled) 상태입니다.
fetch timing info는 struct로, Resource Timing과 Navigation Timing에 필요한 타이밍 정보를 유지합니다. 다음의 항목을 가집니다: [RESOURCE-TIMING] [NAVIGATION-TIMING]
- start time (기본값 0)
- redirect start time (기본값 0)
- redirect end time (기본값 0)
- post-redirect start time (기본값 0)
- final service worker start time (기본값 0)
- final network-request start time (기본값 0)
- first interim network-response start time (기본값 0)
- final network-response start time (기본값 0)
- end time (기본값 0)
- redirect start time (기본값 0)
DOMHighResTimeStamp.- final connection timing info (기본값 null)
- Null 또는 connection timing info.
- 서비스 워커 타이밍 정보 (기본값 null)
- Null 또는 서비스 워커 타이밍 정보.
- server-timing headers (기본값 « »)
- 문자열의 list.
- render-blocking (기본값 false)
- 불리언 값.
response body info 는 struct로, Resource Timing과 Navigation Timing에 필요한 정보를 유지합니다. 다음의 항목을 가집니다: [RESOURCE-TIMING] [NAVIGATION-TIMING]
- encoded size
(기본값 0)
- decoded size (기본값 0)
- 숫자.
- content type (기본값 빈 문자열)
- ASCII 문자열.
- content encoding (기본값 빈 문자열)
- ASCII 문자열.
fetch timing info timingInfo가 주어졌을 때 불투명 타이밍 정보 생성은, timingInfo의 start time과 post-redirect start time이 timingInfo의 start time인 새로운 fetch timing info를 반환합니다.
알고리즘 algorithm, global object 또는 parallel queue taskDestination이 주어졌을 때 fetch 태스크 큐잉(queue a fetch task)은 다음과 같이 실행합니다:
-
taskDestination이 parallel queue라면, enqueue algorithm을 taskDestination에 추가합니다.
-
그렇지 않으면, 글로벌 태스크(global task)를 networking task source에 taskDestination과 algorithm으로 큐잉합니다.
환경 설정 객체 environment 오프라인 여부 확인:
-
사용자 에이전트가 인터넷 연결이 없다고 가정하면, true를 반환한다.
-
environment의 WebDriver BiDi 네트워크 오프라인 여부를 반환한다.
정수 직렬화(serialize an integer)란, 정수를 가능한 가장 짧은 십진수 문자열로 표현하는 것입니다.
이 부분은 Infra에서 더 자세한 알고리즘으로 교체될 예정입니다. infra/201 참고.
2.1. URL
로컬 스킴(local scheme)은
"about", "blob", 또는
"data"입니다.
URL이 로컬임(is local)은 해당 스킴이 로컬 스킴일 때입니다.
이 정의는 Referrer Policy에서도 사용됩니다. [REFERRER]
HTTP(S) 스킴은
"http" 또는
"https"입니다.
패치 스킴(fetch scheme)은
"about", "blob",
"data", "file", 또는 HTTP(S) 스킴입니다.
HTTP(S) 스킴과 패치 스킴 역시 HTML에서 사용됩니다. [HTML]
2.2. HTTP
패칭은 HTTP에만 국한되지 않지만,
HTTP에서 여러 개념을 차용하여 다른
방식(예: data URL)으로 획득한 리소스에도 적용합니다.
HTTP 탭 또는 공백(HTTP tab or space)은 U+0009 TAB 또는 U+0020 SPACE입니다.
HTTP 공백(HTTP whitespace)은 U+000A LF, U+000D CR, 또는 HTTP 탭 또는 공백입니다.
HTTP 공백은 HTTP 헤더 맥락 이외에서 재사용되는 특정 구조에만 유용합니다(예: MIME 타입). HTTP 헤더 값에는 HTTP 탭 또는 공백 사용을 권장하며, 그 외 맥락에서는 ASCII 공백을 권장합니다. ASCII 공백과 달리 U+000C FF는 제외됩니다.
HTTP 줄바꿈 바이트(HTTP newline byte)는 0x0A (LF) 또는 0x0D (CR)입니다.
HTTP 탭 또는 공백 바이트(HTTP tab or space byte)는 0x09 (HT) 또는 0x20 (SP)입니다.
HTTP 공백 바이트(HTTP whitespace byte)는 HTTP 줄바꿈 바이트 또는 HTTP 탭 또는 공백 바이트입니다.
HTTP 따옴표 문자열 수집(collect an HTTP quoted string) 을 하려면 문자열(string) input, 위치 변수(position variable) position, 선택적 불리언 extract-value (기본값 false)가 주어졌을 때 다음을 수행합니다:
-
positionStart를 position으로 둡니다.
-
value를 빈 문자열로 둡니다.
-
position을 1만큼 증가시킵니다.
-
다음이 참인 동안:
-
U+0022 (") 또는 U+005C (\)가 아닌 코드 포인트 시퀀스 수집 결과를 input, position으로부터 value에 추가합니다.
-
position이 input의 끝을 지난 경우, break합니다.
-
quoteOrBackslash를 input의 position에 있는 코드 포인트로 둡니다.
-
position을 1만큼 증가시킵니다.
-
quoteOrBackslash가 U+005C (\)이면:
-
그 외의 경우:
-
-
extract-value가 true라면 value를 반환합니다.
-
input의 positionStart부터 position까지(포함)의 코드 포인트들을 반환합니다.
2.2.1. 메서드
메서드(method)란 바이트 시퀀스로, method 토큰 생성식을 만족하는 것입니다.
CORS-안전 목록 메서드(CORS-safelisted method)는
메서드 중
`GET`,
`HEAD`, 또는 `POST`인 것입니다.
금지된 메서드(forbidden
method)란
메서드 중
바이트 대소문자 구분 없이 `CONNECT`, `TRACE`, 또는
`TRACK`와 일치하는 것입니다.
[HTTPVERBSEC1], [HTTPVERBSEC2],
[HTTPVERBSEC3]
메서드 정규화(normalize)를 하려면,
메서드가 바이트 대소문자
구분 없이
`DELETE`, `GET`,
`HEAD`, `OPTIONS`, `POST`, 또는
`PUT`와 일치한다면, 대문자 바이트(byte-uppercase)로 변환합니다.
정규화는 과거와의 호환성 및 API 간의 일관성을 위해 수행되며, 메서드는 실제로 "대소문자 구분"입니다.
`patch`를 사용하면 `405 Method Not Allowed`가 발생할 가능성이 높습니다. 반면 `PATCH`는 성공
가능성이 훨씬 더 높습니다.
메서드에는 제한이 없습니다. `CHICKEN`도 완벽하게 허용됩니다(그리고
`CHECKIN`의 오타가 아닙니다). 정규화되는 것 외에는 대소문자 제한도 없습니다.
`Egg`나 `eGg`도 괜찮지만, 일관성을 위해 대문자를 권장합니다.
2.2.2. 헤더
HTTP는 일반적으로 헤더를 "필드(field)" 또는 "헤더 필드(header field)"라고 부릅니다. 웹 플랫폼에서는 더 구어체인 "헤더(header)"라는 용어를 사용합니다. [HTTP]
헤더 목록(header list)은 리스트(list)이며, 0개 이상의 헤더(header)를 포함합니다. 처음에는 « »입니다.
헤더 목록은 본질적으로 특수한 멀티맵: 키-값 쌍의 순서 있는 리스트로, 키가 중복될 수 있습니다.
`Set-Cookie`를 제외한 헤더는 클라이언트 측 JavaScript에 노출될 때 항상 합쳐지므로, 구현체는 `Set-Cookie` 헤더용 별도
데이터 구조만 지원하면 더 효율적인 표현을 선택할 수 있습니다.
구조화 필드 값 가져오기(get a structured field value) 를 하려면 헤더 이름 name과 문자열 type이 헤더 목록 list에서 주어졌을 때 다음 단계를 실행합니다. 결과는 null 또는 구조화 필드 값(structured field value)입니다.
-
Assert: type은 "
dictionary", "list", 또는 "item" 중 하나입니다. -
value를 헤더 목록에서 name을 가져온 결과로 둡니다.
-
value가 null이면 null을 반환합니다.
-
result를 구조화 필드 파싱(parsing structured fields)의 결과로 둡니다. input_string은 value, header_type은 type입니다.
-
파싱에 실패했다면 null을 반환합니다.
-
result를 반환합니다.
구조화 필드 값 가져오기는 해당 헤더가 존재하지 않는 것과 값이 구조화 필드 값으로 파싱에 실패한 것을 의도적으로 구분하지 않습니다. 이는 웹 플랫폼 전반에서 일관된 처리를 보장합니다.
구조화 필드 값 설정(set a structured field value) 을 하려면 튜플(tuple) (헤더 이름 name, 구조화 필드 값 structuredValue)과 헤더 목록 list가 주어집니다:
-
serializedValue를 구조화 필드 직렬화(serializing structured fields) 알고리즘을 structuredValue에 적용한 결과로 둡니다.
-
Set (name, serializedValue) 를 list에 적용합니다.
구조화 필드 값은 HTTP가(결국) 흥미롭고 효율적으로 직렬화할 수 있는 객체로 정의되어 있습니다. 현재 Fetch는 헤더 값만 바이트 시퀀스로 지원하므로, 이 객체들은 직렬화를 통해서만 헤더 목록에 설정할 수 있고, 파싱을 통해서만 헤더 목록에서 얻을 수 있습니다. 앞으로는 객체 상태가 끝까지 유지될 수도 있습니다. [RFC9651]
헤더 목록 list가 헤더를 포함(contains)하는지 여부는 헤더 이름 name이 list에 포함된 헤더 중 name이 바이트 대소문자 구분 없이 name과 일치하는 것이 있는지로 판단합니다.
가져오기(get)는 헤더 이름 name과 헤더 목록 list가 주어졌을 때 다음 단계를 실행합니다. 결과는 null 또는 헤더 값입니다.
-
list가 name을 포함하지 않으면 null을 반환합니다.
-
list에서 헤더 중 name이 바이트 대소문자 구분 없이 name과 일치하는 모든 값을 0x2C 0x20(쉼표+공백)으로 구분하여 순서대로 반환합니다.
가져오기, 디코드 및 분할(get, decode, and split) 은 헤더 이름 name과 헤더 목록 list가 주어졌을 때 다음 단계를 실행합니다. 결과는 null 또는 리스트 ( 문자열(string) )입니다.
-
value를 name을 가져온 결과로 둡니다.
-
value가 null이면 null을 반환합니다.
-
get, decode, and split을 value에 적용한 결과를 반환합니다.
다음은 get, decode, and split이 실제로 어떻게 동작하는지,
name 인자가 `A`일 때의 예시입니다:
| 헤더(네트워크 상) | 출력 |
|---|---|
| « "nosniff", "" »
|
| |
| « "" » |
| null |
| « "text/html;", x/x" »
|
| |
| « "x/x;test="hi"", "y/y" »
|
| |
| « "x / x", "", "", "1" »
|
| |
| « ""1,2"", "3" »
|
|
get, decode, and split 을 헤더 값(header value) value에 대해 실행하려면 다음 단계를 따릅니다. 반환 값은 문자열 리스트(list of strings)입니다.
-
input을 isomorphic decoding value 결과로 둡니다.
-
position을 위치 변수(position variable)로, input의 시작 위치로 지정합니다.
-
values를 문자열 리스트(list of strings)로, 처음에는 « »로 둡니다.
-
temporaryValue를 빈 문자열로 둡니다.
-
다음이 참인 동안 반복합니다:
-
U+0022 (") 또는 U+002C (,)가 아닌 코드 포인트 시퀀스 수집 결과를 input, position으로부터 temporaryValue에 추가합니다.
이 결과는 빈 문자열일 수도 있습니다.
-
position이 input의 끝을 지나지 않았고, position 위치의 코드 포인트가 U+0022 (")이면:
-
temporaryValue에 HTTP 따옴표 문자열 수집 결과를 input, position으로부터 추가합니다.
- position이 끝을 지나지 않았다면 continue합니다.
-
-
temporaryValue의 시작과 끝에서 HTTP 탭 또는 공백을 모두 제거합니다.
-
Append temporaryValue를 values에 추가합니다.
-
temporaryValue를 빈 문자열로 설정합니다.
-
position이 input의 끝을 지났다면 values를 반환합니다.
-
position을 1만큼 증가시킵니다.
-
특정 허용된 호출지(blessed call sites)를 제외하고, 위 알고리즘을 직접 호출하지 않아야 합니다. 대신 get, decode, and split을 사용하세요.
append는 헤더(header) (name, value)를 헤더 목록(header list) list에 추가하는 알고리즘입니다:
delete는 헤더 이름(header name) name을 헤더 목록(header list) list에서 제거하는 알고리즘입니다. 이때 헤더의 name이 바이트 대소문자 구분 없이 name과 일치하는 모든 헤더를 list에서 제거합니다.
set은 헤더(header) (name, value)를 헤더 목록(header list) list에 설정하는 방법입니다:
-
list가 name을 포함하면, 첫 번째 해당 헤더(header)의 값(value)을 value로 설정하고, 나머지 해당 헤더들은 제거한다.
-
그렇지 않으면, append (name, value)를 list에 추가합니다.
combine은 헤더(header) (name, value)를 헤더 목록(header list) list에 결합하는 방법입니다:
-
list가 name을 포함하면, 첫 번째 해당 헤더의 value 뒤에 0x2C 0x20(쉼표+공백), value를 순서대로 이어붙입니다.
-
그렇지 않으면, append (name, value)를 list에 추가합니다.
combine은 XMLHttpRequest
및
WebSocket 프로토콜 핸드셰이크에서 사용됩니다.
헤더 이름을 정렬된 소문자 집합으로 변환(convert header names to a sorted-lowercase set)하려면, 리스트(list) headerNames가 주어졌을 때 다음 단계를 따릅니다. 반환값은 순서 있는 집합(ordered set)의 헤더 이름(header name)입니다.
-
headerNamesSet을 새로운 순서 있는 집합으로 둡니다.
-
각 name에 대해, 바이트 소문자화(byte-lowercasing) name을 headerNamesSet에 append합니다.
-
오름차순 정렬을 headerNamesSet에 바이트 비교(byte less than)로 적용한 결과를 반환합니다.
sort and combine은 헤더 목록(header list) list를 입력받아, 다음 단계를 실행합니다. 반환값은 헤더 목록(header list)입니다.
-
headers를 헤더 목록(header list)으로 둡니다.
-
names를 헤더 이름을 정렬된 소문자 집합으로 변환한 결과로 둡니다. 이때 list 내 헤더들의 이름을 사용합니다.
-
각 name에 대해:
-
headers를 반환합니다.
헤더(header)는 튜플(tuple)로, 이름(name) (헤더 이름)과 값(value) (헤더 값)으로 구성됩니다.
헤더 이름(header name)은 바이트 시퀀스로, field-name 토큰 생성식을 만족합니다.
헤더 값(header value)은 바이트 시퀀스로, 다음 조건을 모두 만족해야 합니다:
-
선행 또는 후행 HTTP 탭 또는 공백 바이트가 없어야 합니다.
-
0x00 (NUL) 또는 HTTP 줄바꿈 바이트를 포함하지 않아야 합니다.
헤더 값의 정의는 field-value 토큰 생성식을 따르지 않는 것이, 배포된 콘텐츠와 호환되지 않기 때문입니다.
헤더 값 정규화(normalize)는 바이트 시퀀스 potentialValue에서 선행 및 후행 HTTP 공백 바이트를 제거하는 것입니다.
헤더 (name, value) 가 CORS-안전 목록 요청 헤더(CORS-safelisted request-header)인지 판단하려면 다음 단계를 실행합니다:
-
value의 길이가 128을 초과하면 false를 반환합니다.
-
바이트 소문자화(Byte-lowercase)한 name에 따라 분기합니다:
- `
accept` -
value에 CORS-비안전 요청 헤더 바이트가 있으면 false를 반환합니다.
- `
accept-language`- `
content-language` - `
-
value에 0x30 (0)~0x39 (9), 0x41 (A)~0x5A (Z), 0x61 (a)~0x7A (z), 0x20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;), 0x3D (=)에 속하지 않는 바이트가 있으면 false를 반환합니다.
- `
content-type` -
-
value에 CORS-비안전 요청 헤더 바이트가 있으면 false를 반환합니다.
-
mimeType을 파싱(parsing)한 등가 디코딩(isomorphic decoding) value 결과로 둡니다.
-
mimeType이 실패(failure)라면 false를 반환합니다.
-
mimeType의 essence가 "
application/x-www-form-urlencoded", "multipart/form-data", 또는 "text/plain"이 아니면 false를 반환합니다.
이는 MIME 타입 추출(extract a MIME type) 알고리즘을 사용하지 않습니다. 해당 알고리즘은 관대하며, 서버가 이를 구현해야 한다고 기대하지 않기 때문입니다.
MIME 타입 추출을 사용할 경우 아래 요청은 CORS 프리플라이트 없이 처리되고, 서버의 단순 파서는 요청 본문을 JSON으로 처리할 수 있습니다:
fetch( "https://victim.example/naïve-endpoint" , { method: "POST" , headers: [ [ "Content-Type" , "application/json" ], [ "Content-Type" , "text/plain" ] ], credentials: "include" , body: JSON. stringify( exerciseForTheReader) }); -
- `
range` -
-
rangeValue를 단일 range 헤더 값 파싱(parsing a single range header value) 에 value와 false를 넘긴 결과로 둡니다.
-
rangeValue가 실패(failure)면 false를 반환합니다.
-
rangeValue[0]이 null이면 false를 반환합니다.
웹 브라우저는 `
bytes=-500`와 같은 range를 내보내지 않으므로 이 알고리즘은 그런 경우를 safelist하지 않습니다.
-
- 기타
-
false를 반환합니다.
- `
-
true를 반환합니다.
`Content-Type` 헤더 safelist에는 제한적 예외가 있습니다. 자세한 내용은 CORS 프로토콜 예외를 참고하세요.
CORS-비안전 요청 헤더 바이트(CORS-unsafe request-header byte)는 바이트 byte가 다음 중 하나에 해당할 때입니다:
-
byte가 0x20 미만이고 0x09 HT가 아닌 경우
-
byte가 0x22 ("), 0x28 (왼쪽 괄호), 0x29 (오른쪽 괄호), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), 또는 0x7F DEL인 경우.
CORS-비안전 요청 헤더 이름(CORS-unsafe request-header names)은 헤더 목록 headers에 대해 다음과 같이 결정합니다:
CORS
non-wildcard 요청 헤더 이름(CORS non-wildcard request-header name)은 헤더 이름 중
바이트 대소문자 구분 없이 `Authorization`와 일치하는 것입니다.
특권 no-CORS 요청 헤더 이름(privileged no-CORS request-header name)은 헤더 이름 중 바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:
- `
Range`.
이들은 특권 API에서 설정할 수 있으며, 관련 요청 객체가 복사될 때는 보존되지만, 권한이 없는 API가 요청을 수정하는 경우 제거됩니다.
`Range` 헤더는 주로 다운로드
및 미디어 패치에서 사용됩니다.
특정 요청에 range 헤더 추가를 위한 헬퍼가 제공됩니다.
CORS-안전 목록 응답 헤더 이름(CORS-safelisted response-header name)은 리스트의 헤더 이름 list에 대해, 다음 중 하나와 바이트 대소문자 구분 없이 일치하는 것입니다:
- `
Cache-Control` - `
Content-Language` - `
Content-Length` - `
Content-Type` - `
Expires` - `
Last-Modified` - `
Pragma` - 리스트(list)의 모든 항목 중 금지된 응답 헤더 이름(forbidden response-header name)이 아닌 것.
no-CORS-안전 목록 요청 헤더 이름(no-CORS-safelisted request-header name)은 헤더 이름 중 바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:
- `
Accept` - `
Accept-Language` - `
Content-Language` - `
Content-Type`
헤더 (name, value)가 no-CORS-안전 목록 요청 헤더(no-CORS-safelisted request-header)인지 판단하려면 다음 단계를 실행합니다:
-
name이 no-CORS-안전 목록 요청 헤더 이름이 아니면 false를 반환합니다.
-
(name, value)가 CORS-안전 목록 요청 헤더인지 여부를 반환합니다.
헤더 (name, value)가 금지된 요청 헤더(forbidden request-header)인지 판단하려면 다음 단계가 true를 반환하면 됩니다:
-
name이 다음 중 하나와 바이트 대소문자 구분 없이 일치하면:
- `
Accept-Charset` - `
Accept-Encoding` - `
Access-Control-Request-Headers` - `
Access-Control-Request-Method` - `
Connection` - `
Content-Length` - `
Cookie` - `
Cookie2` - `
Date` - `
DNT` - `
Expect` - `
Host` - `
Keep-Alive` - `
Origin` - `
Referer` - `
Set-Cookie` - `
TE` - `
Trailer` - `
Transfer-Encoding` - `
Upgrade` - `
Via`
true를 반환합니다.
- `
-
name이 다음 중 하나와 바이트 대소문자 구분 없이 일치하면:
- `
X-HTTP-Method` - `
X-HTTP-Method-Override` - `
X-Method-Override`
다음 절차를 실행합니다:
-
parsedValues를 get, decode, and split value의 결과로 둡니다.
-
각 parsedValues의 method에 대해, isomorphic encoding한 method가 금지된 메서드(forbidden method)라면 true를 반환합니다.
- `
-
false를 반환합니다.
이 헤더들은 사용자 에이전트가 완전히 제어할 수 있도록 금지됩니다.
헤더 이름이
`Sec-`로 시작하는 경우, 헤더가
fetch 등 개발자가 헤더를 제어할 수
있는 API에 의해 사용될 때, 새 헤더가 안전하게 도입될 수 있도록 예약되어 있습니다. 예: XMLHttpRequest.
[XHR]
`Set-Cookie` 헤더는 의미상 응답 헤더이므로 요청에서는 쓸모가 없습니다. `Set-Cookie` 헤더는 결합(combine)될
수 없으므로, Headers
객체에서 더 복잡하게 처리해야 합니다. 여기서 금지하는 이유는 이 복잡성이 요청으로 새어 나가는 것을 막기 위함입니다.
금지된 응답 헤더 이름(forbidden response-header name)은 헤더 이름 중 바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:
- `
Set-Cookie` - `
Set-Cookie2`
요청 본문 헤더 이름(request-body-header name)은 헤더 이름 중 바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:
- `
Content-Encoding` - `
Content-Language` - `
Content-Location` - `
Content-Type`
헤더 값 추출(extract header values) 은 헤더(header) header가 주어졌을 때 다음 단계를 실행합니다:
헤더 목록 값 추출(extract header list values) 은 헤더 이름 name과 헤더 목록(header list) list가 주어졌을 때 다음 단계를 실행합니다:
-
list가 name을 포함하지 않으면 null을 반환합니다.
-
name에 대한 ABNF가 단일 헤더(header)만 허용하고, list가 name을 중복 포함하면 failure를 반환합니다.
다른 오류 처리가 필요하다면, 먼저 원하는 헤더를 추출하세요.
-
values를 빈 리스트로 둡니다.
-
list에 name을 포함하는 모든 헤더(header) header에 대해:
-
values를 반환합니다.
콘텐츠 범위 생성(build a content range)은 정수 rangeStart, 정수 rangeEnd, 정수 fullLength가 주어졌을 때 다음 단계를 실행합니다:
단일 range 헤더 값 파싱(parse a single range header value)은 바이트 시퀀스 value와 불리언 allowWhitespace가 주어졌을 때 다음을 실행합니다:
-
data를 등가 디코딩(isomorphic decoding) value 결과로 둡니다.
-
data가 "
bytes"로 시작하지 않으면 failure를 반환합니다. -
position을 위치 변수(position variable)로, data의 5번째 코드 포인트 위치로 둡니다.
-
allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.
-
data의 position 위치 코드 포인트가 U+003D (=)가 아니면 failure를 반환합니다.
-
position을 1만큼 증가시킵니다.
-
allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.
-
rangeStart를 ASCII 숫자(ASCII digits) 시퀀스를 data, position에서 수집한 결과로 둡니다.
-
rangeStartValue를 rangeStart가 빈 문자열이 아니면 10진수로 해석한 값, 아니면 null로 둡니다.
-
allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.
-
data의 position 위치 코드 포인트가 U+002D (-)가 아니면 failure를 반환합니다.
-
position을 1만큼 증가시킵니다.
-
allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.
-
rangeEnd를 ASCII 숫자(ASCII digits) 시퀀스를 data, position에서 수집한 결과로 둡니다.
-
rangeEndValue를 rangeEnd가 빈 문자열이 아니면 10진수로 해석한 값, 아니면 null로 둡니다.
-
position이 data의 끝을 지나지 않았다면 failure를 반환합니다.
-
rangeEndValue와 rangeStartValue가 모두 null이면 failure를 반환합니다.
-
rangeStartValue와 rangeEndValue가 모두 숫자이고, rangeStartValue가 rangeEndValue보다 크면 failure를 반환합니다.
-
(rangeStartValue, rangeEndValue)를 반환합니다.
range 끝이나 시작이 생략될 수 있습니다. 예: `
bytes=0-` 또는 `bytes=-500`도 유효한 range입니다.
단일 range 헤더 값 파싱은 허용된 range 헤더 값의 일부만 성공하지만, 미디어 요청이나 다운로드 재개 등에서 사용자 에이전트가 가장 자주 사용하는 형식입니다. 이 range 헤더 값 형식은 range 헤더 추가를 통해 설정할 수 있습니다.
기본
`User-Agent` 값(default `User-Agent` value)은
구현 정의(implementation-defined) 헤더 값입니다 (`User-Agent` 헤더용).
웹 호환성 문제로 인해, 웹 브라우저는 이 값이 `Mozilla/5.0 (`로 시작하도록 하고, 일반적으로 다른 웹 브라우저를
따라하도록 강하게 권장됩니다.
environment settings object
environment의
environment default `User-Agent` value를
얻으려면:
-
userAgent를 WebDriver BiDi emulated User-Agent로 environment에 대해 설정한다.
-
userAgent가 null이 아니라면, userAgent를 isomorphic encoded된 값으로 반환한다.
-
default `
User-Agent` value를 반환한다.
문서
`Accept` 헤더 값(document `Accept` header value)은
`text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`입니다.
2.2.3. 상태
상태(status)는 0부터 999까지(포함)의 정수입니다.
HTTP/1의 status-code를 이 개념에 매핑할 때의 다양한 경계 사례는 이슈 #1156에서 논의되고 있습니다.
null 본문 상태(null body status)는 101, 103, 204, 205, 304인 상태입니다.
ok 상태(ok status)는 200부터 299까지(포함)의 상태입니다.
범위 상태는 206 또는 416인 상태입니다.
리디렉션 상태는 301, 302, 303, 307 또는 308인 상태입니다.
2.2.4. 본문
본문(body)은 다음으로 구성됩니다:
-
스트림(stream) (
ReadableStream객체). -
소스(source) (null, 바이트 시퀀스,
Blob객체, 또는FormData객체), 초기값은 null. -
길이(length) (null 또는 정수), 초기값은 null.
복제(clone)를 본문 body에 대해 실행하려면 다음을 따릅니다:
바이트 시퀀스 bytes를 본문으로(as a body) 얻으려면, 안전하게 추출(safely extracting) bytes의 결과 중 body를 반환합니다.
점진적으로 읽기(incrementally read)는 본문(body) body와 알고리즘 processBodyChunk, 알고리즘 processEndOfBody, 알고리즘 processBodyError, 옵션으로 null, parallel queue 또는 global object taskDestination (기본값 null)이 주어졌을 때 다음을 실행합니다. processBodyChunk는 바이트 시퀀스를 인자로 받는 알고리즘이어야 하며, processEndOfBody는 인자 없이, processBodyError는 예외를 인자로 받는 알고리즘이어야 합니다.
-
taskDestination이 null이면 새 parallel queue 시작 결과를 taskDestination로 둡니다.
-
reader를 리더(getting a reader)로 body의 스트림에 대해 구합니다.
이 동작은 예외를 발생시키지 않습니다.
-
점진적 읽기 루프(incrementally-read loop)를 reader, taskDestination, processBodyChunk, processEndOfBody, processBodyError로 실행합니다.
점진적 읽기
루프(incrementally-read loop)를 실행하려면, ReadableStreamDefaultReader
객체
reader, parallel queue 또는 global object
taskDestination, 알고리즘 processBodyChunk, 알고리즘
processEndOfBody, 알고리즘 processBodyError가 주어집니다:
-
readRequest를 다음 read request로 둡니다:
- chunk steps (chunk)
-
-
continueAlgorithm을 null로 둡니다.
-
chunk가
Uint8Array객체가 아니라면, continueAlgorithm을 다음 단계로 설정합니다: processBodyError를TypeError와 함께 실행. -
그 외의 경우:
-
fetch 태스크 큐잉을 continueAlgorithm, taskDestination에 실행합니다.
-
- close steps
-
-
fetch 태스크 큐잉을 processEndOfBody, taskDestination에 실행합니다.
-
- error steps (e)
-
-
fetch 태스크 큐잉을 processBodyError에 e와 taskDestination로 실행합니다.
-
-
청크 읽기(Read a chunk)를 reader와 readRequest로 실행합니다.
완전히 읽기(fully read)는 본문(body) body, 알고리즘 processBody, 알고리즘 processBodyError, 옵션으로 null, parallel queue 또는 global object taskDestination (기본값 null)이 주어졌을 때 다음을 실행합니다. processBody는 바이트 시퀀스를 인자로 받는 알고리즘이어야 하며, processBodyError는 예외(옵션)를 인자로 받을 수 있는 알고리즘이어야 합니다.
-
taskDestination이 null이면 새 parallel queue 시작 결과를 taskDestination로 둡니다.
-
successSteps를 fetch 태스크 큐잉을 processBody에 bytes, taskDestination로 실행하는 알고리즘으로 둡니다.
-
errorSteps를 fetch 태스크 큐잉을 processBodyError에 exception, taskDestination로 실행하는 알고리즘으로 둡니다.
-
reader를 리더(getting a reader)로 body의 스트림에 대해 구합니다. 예외가 발생하면 errorSteps를 그 예외와 함께 실행하고 종료합니다.
-
모든 바이트 읽기(Read all bytes)를 reader, successSteps, errorSteps로 실행합니다.
타입이 있는 본문(body with type)은 튜플로, 본문(body) (body)과 타입(type) (헤더 값 또는 null)으로 구성됩니다.
콘텐츠 코딩 처리(handle content codings)는 codings와 bytes가 주어졌을 때 다음 단계를 수행합니다:
-
codings가 지원되지 않으면 bytes를 반환합니다.
-
HTTP에서 설명한 대로 codings로 bytes를 디코딩한 결과를 반환합니다. 디코딩 중 오류가 발생하면 failure를 반환합니다. [HTTP]
2.2.5. 요청
이 절은 요청이 어떻게 동작하는지 자세히 문서화합니다. 시작하려면 요청 설정을 참고하세요.
fetch의 입력값은 요청(request)입니다.
요청은 연관된
메서드(method)를 가집니다.
(method) 별도의 언급이 없으면
`GET`입니다.
리다이렉트 중 HTTP fetch에서 설명된 대로 `GET`으로 변경될 수 있습니다.
구현은 URL 목록 중 첫 번째 요청의 URL 목록을 가리키게 만드는 것이 권장됩니다. 이 필드는 Fetch에 연결되는 다른 표준의 편의를 위해 별도로 제공됩니다.
요청은 연관된 로컬 URL 전용 플래그(local-URLs-only flag)를 가집니다. 별도의 언급이 없으면 설정되지 않음(unset)입니다.
요청은 연관된 헤더 목록(header list)을 가집니다. (header list) 별도의 언급이 없으면 « »입니다.
요청은 연관된 unsafe-request 플래그를 가집니다. 별도의 언급이 없으면 설정되지 않음(unset)입니다.
unsafe-request 플래그는
fetch() 및 XMLHttpRequest와
같은 API에서 설정되어,
지정된 메서드 및 헤더
목록에 따라
CORS-프리플라이트
fetch가 수행됨을 보장합니다. 이는 API가 금지된 메서드 및 금지된 요청 헤더를 허용하지 않는 것과는 별개입니다.
요청은 연관된 본문(body)을 가집니다. (null, 바이트 시퀀스, 또는 body) 별도의 언급이 없으면 null입니다.
바이트 시퀀스는 안전하게 추출되어 body로 바뀌며, HTTP fetch 중 일부 리다이렉트로 인해 이 값이 null이 될 수도 있습니다.
요청은 연관된 클라이언트(client)를 가집니다. (null 또는 environment settings object)
요청은 연관된 reserved client (null, environment, 또는 environment settings object), 별도의 언급이 없으면 null입니다.
이 필드는 탐색 요청(navigation requests) 및 워커 요청에만 사용되며, 서비스 워커 요청에는 사용되지 않습니다. environment는 탐색 요청용, environment settings object는 워커 요청용입니다.
요청은 연관된 replaces client id (문자열) 값을 가집니다. 별도의 언급이 없으면 빈 문자열입니다.
이 필드는 탐색 요청에만 사용됩니다. id는 대상 브라우징 컨텍스트(target browsing context)의 active document 의 environment settings object입니다.
요청은 연관된
사용자 프롬프트용 traversable(traversable for user prompts)을 가집니다.
"no-traversable", "client", 또는 traversable navigable 중 하나입니다. 별도의 언급이 없으면
"client"입니다.
이 필드는 요청과 연관된 UI(예: 인증 프롬프트, 클라이언트 인증서 대화상자 등)를 어디에 표시할지 결정할 때 사용합니다.
- "
no-traversable" - UI를 표시하지 않음; 보통 요청이 네트워크 오류(network error)로 실패함.
- "
client" - 이 값은 fetch 중에 자동으로 "
no-traversable" 또는 traversable navigable로 바뀝니다. 이를 통해 표준에서 요청의 사용자 프롬프트용 traversable을 명시적으로 설정하지 않아도 됩니다. - traversable navigable
- 표시되는 UI는 해당 traversable navigable을 보여주는 브라우저 인터페이스와 연결됩니다.
요청과 연관된 사용자 인터페이스를 사용자 프롬프트용 traversable에서 표시할 때, 사용자 에이전트는 주소 표시줄에 요청의 현재 URL(current URL)에서 유도된 값을 표시해야 합니다(예: 이전 값, 즉 요청의 시작자 URL에서 유도된 값을 표시하지 않아야 함). 또한, 특히 교차 출처 요청의 경우, 요청의 시작자 콘텐츠를 사용자 프롬프트용 traversable에 표시하지 않도록 해야 합니다. 이러한 프롬프트 뒤에 빈 페이지를 표시하는 것이 좋은 방법입니다. 이를 준수하지 않으면 사용자가 어느 출처가 해당 프롬프트를 유발했는지 혼동할 수 있습니다.
요청은 연관된 불리언 keepalive를 가집니다. 별도의 언급이 없으면 false입니다.
이 값이 true이면 요청이 environment settings object보다 오래 지속될 수 있습니다. 예:
navigator.sendBeacon() 및 HTML img 요소가 이 기능을 사용합니다. 이 값이 true인 요청은 추가 처리 요구 사항이
적용됩니다.
요청은 연관된
initiator type을 가집니다. 값은 null,
"audio",
"beacon",
"body",
"css",
"early-hints",
"embed",
"fetch",
"font",
"frame",
"iframe",
"image",
"img",
"input",
"link",
"object",
"ping",
"script",
"track",
"video",
"xmlhttprequest", 또는
"other" 중 하나입니다. 별도의 언급이 없으면 null입니다. [RESOURCE-TIMING]
요청은 연관된
service-workers mode를 가집니다.
값은 "all" 또는 "none" 중 하나입니다. 별도의 언급이 없으면 "all"입니다.
이 값은 어떤 서비스 워커가 이 fetch에 대해 fetch
이벤트를 받을지 결정합니다.
- "
all" - 해당 서비스 워커가 이 fetch에 대해
fetch이벤트를 받게 됩니다. - "
none" - 어떤 서비스 워커도 이 fetch에 대해 이벤트를 받지 않습니다.
요청은 연관된
initiator를 가집니다. 값은 빈 문자열,
"download",
"imageset",
"manifest",
"prefetch",
"prerender", 또는
"xslt" 중 하나입니다. 별도의 언급이 없으면 빈 문자열입니다.
요청의 initiator는 현재로서는 다른 명세에서 더 세분화가 필요하지 않아 비교적 단순합니다. 주로 CSP와 혼합 콘텐츠 정의를 돕는 명세 장치입니다. JavaScript에는 노출되지 않습니다. [CSP] [MIX]
대상 타입(destination type)은
다음 중 하나입니다:
빈 문자열,
"audio",
"audioworklet",
"document",
"embed",
"font",
"frame",
"iframe",
"image",
"json",
"manifest",
"object",
"paintworklet",
"report",
"script",
"serviceworker",
"sharedworker",
"style",
"track",
"video",
"webidentity",
"worker", 또는
"xslt".
요청은 연관된 대상(destination)을 가집니다. (destination type) 별도의 언급이 없으면 빈 문자열입니다.
이 값들은 RequestDestination
에 반영됩니다. 단, "serviceworker"와 "webidentity"는 해당 destination으로의 fetch가 서비스 워커를
건너뜁니다.
요청의 destination이
스크립트류(script-like)이면, 값이 "audioworklet",
"paintworklet", "script", "serviceworker",
"sharedworker", "worker" 중 하나입니다.
알고리즘에서 스크립트류를 사용할 때는 "xslt"도 스크립트 실행을 유발할 수 있음을
고려해야 합니다. 다만 항상 관련되지 않으며 별도 동작이 필요할 수 있어 목록에 포함하지 않았습니다.
다음 표는 요청의 initiator, destination, CSP 지시어, 그리고 기능(feature) 간의 관계를 보여줍니다. 이 표는 모든 기능을 포괄하지 않습니다. 각 기능은 해당 표준에서 관련 값을 정의해야 합니다.
| Initiator | Destination | CSP 지시어 | 기능(Features) |
|---|---|---|---|
| "" | "report"
| — | CSP, NEL 보고서. |
"document"
| HTML의 navigate 알고리즘(최상위만). | ||
"frame"
| child-src
| HTML의 <frame>
| |
"iframe"
| child-src
| HTML의 <iframe>
| |
| "" | connect-src
| navigator.sendBeacon(), EventSource,
HTML의 <a ping="">, <area ping="">,
fetch(), fetchLater(), XMLHttpRequest,
WebSocket,
WebTransport,
Cache API
| |
"object"
| object-src
| HTML의 <object>
| |
"embed"
| object-src
| HTML의 <embed>
| |
"audio"
| media-src
| HTML의 <audio>
| |
"font"
| font-src
| CSS의 @font-face
| |
"image"
| img-src
| HTML의 <img src>, /favicon.ico 리소스,
SVG의 <image>, CSS의 background-image, CSS의
cursor, CSS의 list-style-image 등
| |
"audioworklet"
| script-src
| audioWorklet.addModule()
| |
"paintworklet"
| script-src
| CSS.paintWorklet.addModule()
| |
"script"
| script-src
| HTML의 <script>, importScripts()
| |
"serviceworker"
| child-src, script-src, worker-src
| navigator.serviceWorker.register()
| |
"sharedworker"
| child-src, script-src, worker-src
| SharedWorker
| |
"webidentity"
| connect-src
| Federated Credential Management 요청
| |
"worker"
| child-src, script-src, worker-src
| Worker
| |
"json"
| connect-src
| import "..." with { type: "json" }
| |
"style"
| style-src
| HTML의 <link rel=stylesheet>, CSS의 @import,
import "..." with { type: "css" }
| |
"track"
| media-src
| HTML의 <track>
| |
"video"
| media-src
| HTML의 <video> 요소
| |
"download"
| "" | — | HTML의 download="", "다른 이름으로 링크 저장…" UI
|
"imageset"
| "image"
| img-src
| HTML의 <img srcset>, <picture>
|
"manifest"
| "manifest"
| manifest-src
| HTML의 <link rel=manifest>
|
"prefetch"
| "" | default-src (특정 지시어 없음)
| HTML의 <link rel=prefetch>
|
"prerender"
| HTML의 <link rel=prerender>
| ||
"xslt"
| "xslt"
| script-src
| <?xml-stylesheet>
|
CSP의 form-action은 HTML의 navigate 또는 form 제출 알고리즘에 직접 연결되어야 합니다.
CSP는 또한 다양한 CSP 지시어에 대해 요청의 client의
global object의 연관 Document의
조상 navigable을 확인해야 합니다.
요청은 연관된
우선순위(priority)를 가집니다. 값은 "high", "low",
"auto" 중 하나이며, 별도의 언급이 없으면 "auto"입니다.
요청은 연관된 내부 우선순위(internal priority)(null 또는 구현 정의(implementation-defined) 객체) 값을 가집니다. 별도의 언급이 없으면 null입니다.
요청은 연관된
origin을 가집니다. 값은 "client" 또는 origin입니다. 별도의 언급이 없으면 "client"입니다.
"client"는 origin으로 fetch 중에 변경됩니다. 이를 통해 표준에서 요청의 origin을 직접 설정하지 않아도 됩니다.
요청은 연관된 최상위 navigation initiator origin(top-level navigation initiator origin)을 가집니다. 값은 origin 또는 null입니다. 별도의 언급이 없으면 null입니다.
요청은 연관된
policy container를 가집니다. 값은 "client" 또는 policy container이며, 별도의 언급이 없으면 "client"입니다.
"client"는 policy container로 fetch 중에 변경됩니다. 이를 통해 표준에서 요청의 policy
container를 직접 설정하지 않아도 됩니다.
요청은 연관된
referrer를 가집니다. 값은 "no-referrer",
"client", 또는 URL입니다. 별도의 언급이 없으면 "client"입니다.
"client"는 URL 또는
"no-referrer"로 fetch 중에 변경됩니다. 이를 통해 표준에서 요청의 referrer를 직접 설정하지 않아도 됩니다.
요청은 연관된 referrer policy를 가집니다. 값은 referrer policy이며, 별도의 언급이 없으면 빈 문자열입니다. [REFERRER]
이 값은 해당 요청에 사용할 referrer policy를 덮어쓸 때 사용될 수 있습니다.
request는
연관된
mode를 갖고 있으며,
이 값은 "same-origin", "cors", "no-cors",
"navigate", "websocket", 또는 "webtransport" 중 하나입니다.
별도로 명시되지 않는 한, 기본값은 "no-cors"입니다.
- "
same-origin" - 동일 출처 URL에 대한 요청임을 보장합니다. fetch는 동일 출처가 아니면 네트워크 오류(network error)를 반환합니다.
- "
cors" - response tainting이 "
cors"로 설정된 요청에 사용되며, CORS 요청이 되어, fetch는 요청된 리소스가 CORS 프로토콜을 이해하지 못하거나 CORS 프로토콜에 일부러 참여하지 않는 경우 네트워크 오류를 반환합니다. - "
no-cors" - CORS-안전 목록 메서드와 CORS-안전 목록 요청 헤더만 사용할 수 있도록 제한합니다. 성공 시 fetch는 opaque 필터링된 응답을 반환합니다.
- "
navigate" - 문서 간 탐색(navigating)에만 사용되는 특수 모드입니다.
- "
websocket" - 웹소켓 연결(WebSocket connection)을 설정할 때만 사용되는 특수 모드입니다.
- "
webtransport" - 이것은
WebTransport(url, options)에서만 사용되는 특수 모드입니다.
기본 요청의 mode가
"no-cors"이기는 하지만,
표준에서는 새로운 기능에 이 모드 사용을 적극 권장하지 않습니다. 이 모드는 안전하지 않습니다.
요청은 연관된 use-CORS-preflight 플래그를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
use-CORS-preflight 플래그가 설정된 것은 CORS-프리플라이트 요청이 발생하는 여러 조건 중
하나이다. use-CORS-preflight 플래그는 XMLHttpRequestUpload
객체에 하나 이상의 이벤트 리스너가 등록되었거나, ReadableStream
객체가 요청에 사용된 경우 설정된다.
요청은
연관된
credentials mode
를 가진다. 값은 "omit", "same-origin", "include" 중 하나이며, 별도 언급이 없으면
"same-origin"이다.
- "
omit" - 이 요청에 credentials를 포함하지 않으며, 응답에 포함된 credentials도 무시된다.
- "
same-origin" - 동일 출처 URL에 대한 요청에는 credentials를 포함하고, 동일 출처 응답에 포함된 credentials도 사용한다.
- "
include" - 이 요청에는 항상 credentials를 포함하고, 응답에 포함된 credentials도 항상 사용한다.
요청의 credentials mode는 fetch 중 credentials의 흐름을 제어한다. 요청의 mode가 "navigate"이면
credentials mode는 "include"로 간주되며,
fetch는 현재 다른 값을 고려하지 않는다.
HTML이 이 부분을 변경하면 이 표준도 그에 맞게 변경되어야 한다.
요청은 연관된 use-URL-credentials 플래그 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
이 플래그가 설정된 경우, 요청의 URL에 username과 password가 있고, 해당 인증 항목(authentication entry)이 존재한다면, URL의 credentials가 인증 항목의 credentials보다 우선된다. 최신 명세에서는 URL에 credentials를 넣는 것을 권장하지 않으므로 이 플래그를 잘 사용하지 않지만, 과거 호환성 때문에 설정하는 경우가 있다.
요청은
연관된
cache mode를 가진다. 값은
"default", "no-store", "reload",
"no-cache", "force-cache", "only-if-cached" 중 하나이며, 별도 언급이 없으면
"default"이다.
- "
default" - fetch는 네트워크로 가기 전에 HTTP 캐시를 검사한다. 캐시에 일치하는 fresh response가 있으면 이를 반환한다. stale-while-revalidate response가 있으면 반환 후 조건부 네트워크 fetch로 캐시를 갱신한다. stale response가 있으면 조건부 네트워크 fetch로 캐시를 갱신한다. 없으면 조건 없는 네트워크 fetch로 캐시를 갱신한다. [HTTP] [HTTP-CACHING] [STALE-WHILE-REVALIDATE]
- "
no-store" - fetch는 HTTP 캐시가 전혀 없는 것처럼 동작한다.
- "
reload" - fetch는 네트워크로 가기 전 HTTP 캐시가 없는 것처럼 동작한다. 즉, 일반 요청을 만들고, 응답으로 캐시를 갱신한다.
- "
no-cache" - HTTP 캐시에 응답이 있으면 조건부 요청을, 없으면 일반 요청을 만든다. 그런 뒤 응답으로 캐시를 갱신한다.
- "
force-cache" - HTTP 캐시에 해당 요청에 일치하는 응답이 있으면 무조건 사용한다(오래됐는지 신경쓰지 않음). 없으면 일반 요청을 만들고, 응답으로 캐시를 갱신한다.
- "
only-if-cached" - HTTP 캐시에 해당 요청에 일치하는 응답이 있으면 무조건 사용한다(오래됐는지 신경쓰지 않음). 없으면 네트워크 오류를 반환한다. (요청의 mode가
"
same-origin"일 때만 사용 가능. 캐시된 리다이렉트는 redirect mode가 "follow"이고 리다이렉트가 mode를 위반하지 않으면 따라감.)
헤더
목록이 다음 중
하나를 포함하면:
`If-Modified-Since`,
`If-None-Match`,
`If-Unmodified-Since`,
`If-Match`, 또는
`If-Range`,
fetch는
cache
mode가 "default"라면 "no-store"로 설정한다.
요청은
연관된
redirect mode를 가진다.
값은 "follow", "error", "manual" 중 하나이며, 별도 언급이 없으면
"follow"이다.
- "
follow" - 리소스를 패칭할 때 발생하는 모든 리다이렉트를 따른다.
- "
error" - 요청이 리다이렉트에 부딪히면 네트워크 오류(network error)를 반환한다.
- "
manual" - 요청이 리다이렉트에 부딪히면 서비스 워커가 오프라인으로 리다이렉트를 재생할 수 있도록 opaque-redirect 필터링된 응답을 가져온다. 이 응답은 네트워크 오류와 구별할 수 없다. (원자적 HTTP 리다이렉트 처리를 위반하지 않기 위해.)
요청은 연관된 integrity metadata (문자열)을 가진다. 별도 언급이 없으면 빈 문자열이다.
요청은 연관된 암호학적 nonce metadata(cryptographic nonce metadata) (문자열)을 가진다. 별도 언급이 없으면 빈 문자열이다.
요청은
연관된
파서 메타데이터(parser metadata)
를 가진다. 값은 빈 문자열, "parser-inserted", "not-parser-inserted" 중 하나이며, 별도 언급이 없으면 빈
문자열이다.
요청의 암호학적 nonce metadata와 파서 메타데이터는 일반적으로 해당 요청을 생성한 HTML 요소의 속성 및 플래그에서 채워진다. 이는 콘텐츠 보안 정책(Content Security Policy)의 여러 알고리즘에서 특정 맥락에서 요청 또는 응답을 차단할지 판단하는 데 사용된다. [CSP]
요청은 연관된 reload-navigation 플래그 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
이 플래그는 HTML의 navigate 알고리즘에서만 사용된다. [HTML]
요청은 연관된 history-navigation 플래그 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
이 플래그는 HTML의 navigate 알고리즘에서만 사용된다. [HTML]
요청은 연관된 불리언 user-activation 을 가진다. 별도 언급이 없으면 false다.
이 값은 HTML의 navigate 알고리즘에서만 사용된다. [HTML]
요청은 연관된 불리언 render-blocking 을 가진다. 별도 언급이 없으면 false다.
이 플래그는 HTML의 렌더링-블로킹 메커니즘에서만 독점적으로 사용됩니다. [HTML]
request는 WebTransport-hash 목록이라는 속성을 가진다(WebTransport-hash 목록). 달리 명시하지 않으면 기본값은 « » 이다.
WebTransport-hash 목록은 0개 이상의 WebTransport-hash로 구성된 리스트이다.
WebTransport-hash는 튜플이며, 알고리즘(문자열), 값(바이트 시퀀스) 으로 구성된다.
이 목록은 WebTransport(url, options)
에서
options가 serverCertificateHashes를
포함할 때에만 독점적으로 사용됩니다.
request에는 연관된 URL 목록이 있다(하나 이상의 리스트로서, URL을 포함한다). 달리 명시되지 않는 한, 이 목록은 request의 URL의 복사본을 포함하는 리스트이다.
request는 또한 current URL 속성을 가진다. 이것은 URL의 포인터이고, request의 URL 목록에서 마지막 URL을 가리킨다.
요청(request)에는 리다이렉트 횟수가 연관되어 있다. 달리 명시하지 않는 한, 0이다.
요청(request)에는
응답 오염(response tainting)이 연관되어 있다.
이것은 "basic", "cors", "opaque" 중 하나이며,
달리 명시하지 않는 한 "basic"이다.
요청(request)에는 no-cache cache-control 헤더 수정 방지 플래그가 연관되어 있다. 달리 명시하지 않는 한, 설정되지 않는다.
요청(request)에는 완료 플래그(done flag)가 연관되어 있다. 달리 명시하지 않는 한, 설정되지 않는다.
요청(request)에는 타이밍 허용 실패 플래그(timing allow failed flag)가 연관되어 있다. 달리 명시하지 않는 한, 설정되지 않는다.
요청의 URL 목록, 현재 URL, 리다이렉트 횟수, 응답 오염, 완료 플래그, 타이밍 허용 실패 플래그는 fetch 알고리즘의 부기(bookkeeping) 세부사항으로 사용된다.
서브리소스 요청(subresource
request)은
요청(request)이며,
대상(destination)이 "audio",
"audioworklet",
"font", "image", "json", "manifest",
"paintworklet", "script", "style", "track",
"video", "xslt" 또는 빈 문자열일 때이다.
비서브리소스
요청(non-subresource request)은
요청(request)이며,
대상(destination)이 "document",
"embed",
"frame", "iframe", "object", "report",
"serviceworker", "sharedworker", "worker" 중 하나다.
네비게이션 요청(navigation
request)은
요청(request)이며
대상(destination)이
"document", "embed", "frame", "iframe",
"object" 중 하나다.
이 용어들의 용례에 대해서는 handle fetch를 참조. [SW]
요청(request)
request의
redirect-taint를 계산하려면 다음 단계를 수행한다.
반환값은 "same-origin", "same-site", "cross-site" 중 하나다.
-
단언(assert): request의 origin이 "
client"가 아니다. -
lastURL을 null로 둔다.
-
taint를 "
same-origin"으로 둔다. -
taint를 반환한다.
요청 출처 직렬화(Serializing a request origin)를 요청(request) request에 대해 수행하려면 다음을 따른다:
-
단언(assert): request의 origin이 "
client"가 아니다. -
request의 redirect-taint가 "
same-origin"이 아니라면 "null"을 반환한다. -
request의 origin을 직렬화(serialized)하여 반환한다.
요청 출처 바이트 직렬화(Byte-serializing a request origin)는 요청(request) request를 받아, 요청 출처 직렬화를 request에 수행한 결과를 동형 인코딩(isomorphic encode)하여 반환한다.
복제(clone)하려면, 요청(request) request에 대해 다음 단계를 따른다:
range 헤더 추가(add a range header)하려면, 요청(request) request에 정수 first와, 선택적으로 정수 last를 가지고 다음을 수행한다:
-
단언(assert): last가 주어지지 않았거나, first가 last보다 작거나 같다.
-
rangeValue를 `
bytes=`로 둔다. -
정수 직렬화(serialize) 및 동형 인코딩을 first에 적용하여 그 결과를 rangeValue에 추가한다.
-
0x2D(-)를 rangeValue에 추가한다.
-
추가(Append)(`
Range`, rangeValue)를 request의 헤더 목록(header list)에 추가한다.
range 헤더는 포함 범위의 바이트 구간을 나타낸다. 예를 들어 first가 0이고 last가 500이면, 501바이트 범위이다.
여러 응답을 하나의 논리 리소스로 결합하는 기능들은 역사적으로 보안 버그의 원인이 되어왔다. 파셜 응답(partial responses)와 관련된 기능은 반드시 보안 검토를 받을 것.
응답 URL 직렬화(serialize a response URL for reporting)하려면, 응답(response) response에 대해 다음 단계를 따른다:
-
단언(assert): response의 URL 목록이 비어 있지 않다.
-
url을 response의 URL 목록[0]의 복사본으로 둔다.
이는 response의 URL이 아니다. 리다이렉트 대상 유출을 방지하기 위해서임(비슷한 고려사항은 CSP 보고 참조). [CSP]
-
사용자명(username)을 url에 빈 문자열로 설정한다.
-
비밀번호(password)를 url에 빈 문자열로 설정한다.
-
직렬화(serialization)된 url을 조각(fragment) 제외를 true로 하여 반환한다.
Cross-Origin-Embedder-Policy에서 credentials 허용 여부를 확인하려면, 요청(request) request에 대해 다음 단계를 따른다:
-
단언(assert): request의 origin이 "
client"가 아니다. -
request의 mode가 "
no-cors"가 아니면 true 반환. -
request의 client가 null이면 true 반환.
-
request의 client의 policy container의 embedder policy의 값이 "
credentialless"가 아니면 true 반환. -
request의 origin과 request의 현재 URL의 origin이 동일 출처(same origin)이고, request의 redirect-taint가 "
same-origin"이 아니라면 true 반환. -
false 반환.
2.2.6. 응답
fetch의 결과는 응답(response)이다. 응답은 시간이 지남에 따라 변화한다. 즉, 모든 필드가 즉시 사용 가능한 것은 아니다.
응답은 연관된
type을 가진다.
값은 "basic", "cors", "default", "error",
"opaque", "opaqueredirect" 중 하나다.
별도 언급이 없으면 "default"이다.
응답은 연관된 aborted 플래그를 가질 수 있으며, 기본적으로 설정되지 않음이다.
이 플래그는 요청이 개발자나 최종 사용자에 의해 명시적으로 중단되었음을 나타낸다.
응답은 연관된 URL을 가진다. 이는 URL 리스트의 마지막 항목을 가리키며, 응답의 URL 리스트가 비어있으면 null이다.
응답은 연관된 URL 리스트(URL list)(리스트, 0개 이상의 URL 포함)을 가진다. 별도 언급이 없으면 « »이다.
첫 번째와 마지막 URL을 제외하면, 응답의 URL 리스트는 스크립트에 직접 노출되지 않는다. 이는 원자적 HTTP 리다이렉트 처리를 위반할 수 있기 때문이다.
응답은 연관된 status를 가진다. 값은 상태(status)이다. 별도 언급이 없으면 200이다.
응답은 연관된 status message를 가진다. 별도 언급이 없으면 빈 바이트 시퀀스이다.
HTTP/2 연결의 응답은 항상 빈 바이트 시퀀스를 status message로 가진다. HTTP/2는 status message를 지원하지 않는다.
응답은 연관된 헤더 목록(header list)을 가진다. (header list) 별도 언급이 없으면 « »이다.
응답은 연관된 본문(body)(null 또는 body)을 가진다. 별도 언급이 없으면 null이다.
네트워크 응답의 source와 length 개념은 항상 null이다.
응답은 연관된
캐시 상태(cache state) (빈 문자열, "local",
"validated")를 가진다. 별도 언급이 없으면 빈 문자열이다.
이 내용은 Service Workers 및 Resource Timing에서 사용하기 위한 것입니다. [SW] [RESOURCE-TIMING]
응답은 연관된 CORS 노출 헤더 이름 목록(CORS-exposed header-name list) (0개 이상의 헤더(header) 이름(name)의 리스트). 별도 언급이 없으면 비어 있음.
응답은 일반적으로 extracting header values를 통해
`Access-Control-Expose-Headers` 헤더에서 이
목록을 얻는다.
이 목록은 CORS 필터링 응답에서 노출할 헤더를 결정할 때 사용된다.
응답은 연관된 range-requested 플래그를 가질 수 있으며, 기본적으로 설정되지 않음이다.
이 플래그는 이전 범위 요청(ranged request)에서 온 부분 응답이, 범위 요청을 하지 않은 API에 제공되는 것을 막기 위해 사용된다. 플래그의 사용에 관한 자세한 설명은 해당 공격 설명을 참고.
응답은 연관된 request-includes-credentials (불리언)을 가진다. 기본값은 true이다.
응답은 연관된 timing allow passed 플래그를 가진다. 기본적으로 설정되지 않음이다.
이 플래그는 fetch 호출자가 패치된 리소스의 민감한 타이밍 데이터를 허용하는지 여부를 판단할 수 있도록 한다. 리다이렉트 체인 내 이전 응답에서 플래그가 설정되어 있으면 리다이렉트 응답에도 설정되어야 하므로, 이는 요청의 timing allow failed flag를 통해 내부적으로도 추적된다.
응답은 연관된 body info (response body info)를 가진다. 별도 언급이 없으면 새로운 response body info이다.
응답은 연관된 service worker timing info (null 또는 service worker timing info)를 가진다. 기본값은 null이다.
응답은 연관된 redirect taint
("same-origin", "same-site", "cross-site")를 가진다. 기본값은
"same-origin"이다.
네트워크 오류(network
error)는
응답으로,
type이
"error", status가 0,
status message가 빈 바이트 시퀀스,
header list가 « », body가 null이며,
body
info가 새로운 response body info인 경우이다.
중단된 네트워크 오류(aborted network error)는 네트워크 오류이면서, aborted 플래그가 설정된 경우이다.
적절한 네트워크 오류(appropriate network error)를 fetch params fetchParams에 대해 생성하려면:
-
Assert: fetchParams가 취소(canceled) 상태임을 확인한다.
-
fetchParams가 중단(aborted) 상태면 중단된 네트워크 오류(aborted network error)를 반환하고, 아니면 네트워크 오류를 반환한다.
필터링 응답(filtered response)은 연관된 응답(response)에 대해 제한된 뷰를 제공하는 응답이다. 이 연관된 응답은 filtered response의 내부 응답(internal response) (응답, 네트워크 오류 또는 filtered response가 아님)에서 얻을 수 있다.
별도 언급이 없으면 filtered response의 연관된 개념(예: body)은 내부 응답의 해당 개념을 참조한다. (아래에서 각 filtered response의 구체적 정의에 예외가 명시된다.)
fetch 알고리즘은 processResponse 및 유사한 파라미터를 통해 filtered response를 호출자에게 노출하여, 정보 누출을 방지한다. 레거시 사유로 정보가 노출되어야 할 때(예: 이미지 디코더에 데이터 전달), 명세 알고리즘에서는 연관된 내부 응답을 사용할 수 있다.
새 명세에서는 opaque filtered response나 opaque-redirect filtered response를 기반으로 하지 않아야 한다. 이는 레거시 구조이며, 현대 컴퓨터 아키텍처에서는 항상 충분히 보호할 수 없다.
basic 필터링
응답(basic filtered response)은
filtered
response 중,
type이
"basic"이고,
header list가
내부 응답의
header list에서,
이름이 금지된 응답 헤더 이름인 헤더를 제외한 것이다.
CORS 필터링 응답(CORS
filtered response)은
filtered
response 중,
type이
"cors"이고,
header list가
내부 응답의
header list에서,
이름이 CORS-안전 목록 응답 헤더 이름이 아닌 헤더를
내부 응답의
CORS 노출 헤더 이름 목록과 함께 제외한 것이다.
opaque 필터링
응답(opaque filtered response)은
filtered
response 중,
type이
"opaque"이고,
URL
리스트가 « »,
status가 0,
status message가 빈 바이트 시퀀스,
header list가 « »,
body가 null,
body
info가 새로운 response body info인 경우이다.
opaque-redirect 필터링 응답(opaque-redirect filtered
response)은
filtered
response 중,
type이
"opaqueredirect"이고,
status가 0,
status message가 빈 바이트 시퀀스,
header list가 « »,
body가 null,
body
info가 새로운 response body info인 경우이다.
opaque-redirect filtered response에서 URL 리스트를 노출해도 해가 없다. 리다이렉트가 전혀 수행되지 않기 때문이다.
즉, opaque filtered response와 opaque-redirect filtered response는 네트워크 오류와 거의 구별되지 않는다. 새 API에서는 내부 명세 알고리즘에서 내부 응답을 사용하지 마라. 정보가 노출될 수 있다.
이는 response.ok와 같은 JavaScript API가 쓸모없는 값을 반환할 수 있음을
의미한다.
type 값은
응답(response)의 속성으로,
type
getter를 통해 스크립트에서 확인할 수 있습니다:
console. log( new Response(). type); // "default"
console. log(( await fetch( "/" )). type); // "basic"
console. log(( await fetch( "https://api.example/status" )). type); // "cors"
console. log(( await fetch( "https://crossorigin.example/image" , { mode: "no-cors" })). type); // "opaque"
console. log(( await fetch( "/surprise-me" , { redirect: "manual" })). type); // "opaqueredirect"
(여기서 다양한 리소스가 실제로 존재하고, https://api.example/status는 적절한 CORS 헤더를 갖추고 있으며,
/surprise-me는 리다이렉트 상태를 사용하는 것을 가정합니다.)
복제(clone)를 응답(response) response에 대해 실행하려면:
-
response가 filtered response라면, 동일한 filtered response를 새로 만들되, 내부 응답은 response의 내부 응답을 복제한 것으로 한다.
-
newResponse를 response의 복사본(단, body는 제외)으로 둔다.
-
response의 body가 null이 아니면, newResponse의 body를 복제 response의 body로 설정한다.
-
newResponse를 반환한다.
신선한 응답(fresh response)이란, 응답(response)의 현재 age(current age)가 신선도 수명(freshness lifetime) 이내에 있는 경우를 말합니다.
stale-while-revalidate 응답(stale-while-revalidate response)이란, 응답(response)이 신선한 응답(fresh response)이 아니고, 현재 age가 stale-while-revalidate 수명 이내인 경우를 말합니다. [HTTP-CACHING] [STALE-WHILE-REVALIDATE]
오래된 응답(stale response)이란 응답(response)이 신선한 응답이나 stale-while-revalidate 응답이 아닌 경우입니다.
location URL은 응답(response) response와 null 또는 ASCII 문자열 requestFragment가 주어졌을 때 아래 단계를 따라 값을 반환합니다. 반환 값은 null, failure, 또는 URL입니다.
-
response의 status가 리다이렉트 상태(redirect status)가 아니면 null을 반환합니다.
-
location을 extracting header list values에 `
Location`과 response의 header list를 넘겨 호출한 결과로 둡니다. -
location이 header value라면, location을 파싱(parsing)한 결과로, base는 response의 URL로 설정합니다.
response가
Response생성자로 만들어진 경우 response의 URL은 null이므로, location이 절대 URL+fragment 문자열이어야만 파싱이 성공합니다. -
location이 URL이고 fragment가 null이면, location의 fragment를 requestFragment로 설정합니다.
이렇게 하면 모든(합성 포함) 응답이 HTTP에서 정의된 리다이렉트 처리 모델을 따르게 됩니다. [HTTP]
-
location을 반환합니다.
location URL 알고리즘은 오직 이 표준 및 HTML의 수동 리다이렉트 처리 navigate 알고리즘에서만 사용됩니다. [HTML]
2.2.7. 기타
잠재적
destination(potential destination)은
"fetch"이거나 빈 문자열이 아닌 destination이다.
변환(translate)을 잠재적 destination potentialDestination에 대해 실행하려면 다음을 따른다:
-
potentialDestination이 "
fetch"라면 빈 문자열을 반환한다. -
Assert: potentialDestination이 destination임을 확인한다.
-
potentialDestination을 반환한다.
2.3. 인증 엔트리(Authentication entries)
인증 엔트리(authentication entry)와 프록시 인증 엔트리(proxy-authentication entry)는 HTTP 인증 및 HTTP 프록시 인증에 사용되는 username, password, realm의 튜플이며, 하나 이상의 요청(requests)과 연관된다.
사용자 에이전트는 이 둘을 HTTP 쿠키 및 유사 추적 기능과 함께 모두 삭제할 수 있도록 해야 한다.
자세한 사항은 HTTP에서 정의한다. [HTTP] [HTTP-CACHING]
2.4. Fetch 그룹(Fetch groups)
각 environment settings object에는 fetch group이 연관되어 있으며, 이는 fetch group을 담고 있다.
fetch group은 fetch 관련 정보를 보관한다.
fetch group에는 다음이 연관된다:
- fetch records
- fetch records의 목록(list).
- deferred fetch records
- deferred fetch records의 목록(list).
fetch record는 struct이며, 다음 항목(item)을 가진다:
- request
- request.
- controller
- fetch controller 또는 null.
deferred fetch record는 struct이며, fetch를 나중에 호출해야 할 때(예: 문서가 언로드되거나 fully active가 아니게 될 때) 필요한 상태 유지를 위해 사용된다. 다음 항목(item)을 가진다:
- request
- request.
- notify invoked
- 인자를 받지 않는 알고리즘.
- invoke state (기본값 "
pending") - "
pending", "sent", 또는 "aborted".
fetch group fetchGroup이 terminated되면:
-
각 fetch record record에 대해, fetchGroup의 fetch records 중 record의 controller가 null이 아니고, record의 request의 done flag이 설정되어 있지 않고, keepalive가 false이면, terminate record의 controller를 호출한다.
-
Process deferred fetches를 fetchGroup에 대해 실행한다.
2.5. 도메인 해석
origin 해석(resolve an origin)을 하려면,
네트워크 파티션
키(network partition key) key와 origin origin이 주어진다:
-
origin의 host의 public suffix가 "
localhost" 또는 "localhost."라면, «::1,127.0.0.1»를 반환한다. -
origin을 하나 이상의 IP 주소의 집합(set)으로 변환하는 구현 정의(implementation-defined) 작업을 수행한다.
또한 단순히 IP 주소만 얻는 것 외에, 다른 연결 정보도 얻는 작업이 구현 정의로 수행될 수 있다. 예를 들어, origin의 scheme이 HTTP(S) scheme라면, 구현체는 HTTPS RR에 대한 DNS 질의를 할 수도 있다. [SVCB]
이 작업이 성공하면, IP 주소의 집합(set)과 추가 구현 정의 정보를 반환한다.
-
실패(failure)를 반환한다.
origin 해석 결과는 캐시될 수 있다. 캐시할 경우, key를 캐시 키의 일부로 사용해야 한다.
2.6. 연결
사용자 에이전트는 연관된 연결 풀(connection pool)을 가진다. 연결 풀은 0개 이상의 순서 있는 집합(ordered set)이며, 각각의 연결(connection)은 키(key) (네트워크 파티션 키), origin(origin), credentials(불리언)로 식별된다.
각 connection은 연관된 timing info (connection timing info)를 가진다.
connection timing info는 연결 획득 과정의 타이밍 정보를 보관하는 struct이다. 다음 항목(items)을 가진다:
- 도메인 조회 시작 시각(domain lookup start time)
(기본값 0)
- 도메인 조회 종료 시각(domain lookup end time) (기본값 0)
- 연결 시작 시각(connection start time) (기본값 0)
- 연결 종료 시각(connection end time) (기본값 0)
- 보안 연결 시작 시각(secure connection start time) (기본값 0)
- 도메인 조회 종료 시각(domain lookup end time) (기본값 0)
DOMHighResTimeStamp.- ALPN 협상 프로토콜(ALPN negotiated protocol) (기본값: 빈 바이트 시퀀스)
- 바이트 시퀀스.
connection timing info clamp/coarsen 알고리즘은
connection
timing info timingInfo,
DOMHighResTimeStamp
defaultStartTime, 불리언 crossOriginIsolatedCapability가 주어졌을 때 다음을 실행한다:
-
timingInfo의 connection start time이 defaultStartTime보다 작으면, 모든 시각 값을 defaultStartTime으로 하고 ALPN negotiated protocol은 timingInfo의 값을 사용한 새로운 connection timing info를 반환한다.
-
아니라면 각 시각 값을 coarsen time 알고리즘으로 crossOriginIsolatedCapability를 넘겨 처리한 값을 사용하고, ALPN negotiated protocol은 timingInfo의 값을 사용한 새로운 connection timing info를 반환한다.
새 연결 설정(new connection
setting)은 "no", "yes", "yes-and-dedicated" 중 하나이다.
연결을 획득(obtain a
connection)하려면,
네트워크 파티션
키(network partition key) key,
URL url,
불리언 credentials, 선택적 새 연결 설정(new connection setting) new(기본값
"no"),
선택적 불리언 requireUnreliable(기본값 false), 그리고
선택적 WebTransport-hash 목록
webTransportHashes(기본값 « »)를 입력받아 다음을
따른다:
-
new가 "
no"라면:-
단언(assert): webTransportHashes 가 비어 있음.
-
connections를 사용자 에이전트의 연결 풀(connection pool) 내에서 key가 key이고, origin이 url의 origin이며, credentials이 credentials인 연결(connections)의 집합으로 둔다.
-
connections가 비어 있지 않고 requireUnreliable이 false라면, connections 중 하나를 반환한다.
-
connections 안에 예를 들어 HTTP/3 등 신뢰할 수 없는(unreliable) 전송을 지원할 수 있는 연결이 있다면, 해당 연결을 반환한다.
-
-
proxies를 url에 대해 구현자 정의 방식(implementation-defined manner)으로 프록시를 찾은 결과로 둔다. 프록시가 없으면 proxies는 « "
DIRECT" »로 둔다.여기가 WPAD나 PAC 등의 비표준 기술이 동작하는 부분이다. "
DIRECT" 값은 이 url에 프록시를 사용하지 않음을 의미한다. -
timingInfo를 새로운 connection timing info로 둔다.
-
각 proxies의 proxy에 대해:
-
timingInfo의 domain lookup start time을 unsafe shared current time으로 설정한다.
-
proxy가 "
DIRECT"이면, hosts를 key와 url의 origin을 사용하여 origin 해석(resolve an origin) 을 실행한 결과로 설정한다. -
hosts가 실패(failure)면 continue.
-
timingInfo의 domain lookup end time을 unsafe shared current time으로 둔다.
-
connection을 다음 단계의 결과로 둔다: 연결 생성(create a connection)을 key, url의 origin, credentials, proxy, hosts에서 구현자 정의 방식으로 하나의 host, timingInfo, requireUnreliable, webTransportHashes로 호출한다. 이를 구현자 정의 횟수만큼 서로 병렬(parallel)로 시도하고, 최소 하나 이상 값이 반환될 때까지 기다린다. 구현자 정의 방식으로 반환값 중 하나를 선택해 반환한다. 반환값 중 연결(connection)인 다른 값들은 닫힐 수 있다.
실질적으로 이것은 구현체가 origin 해석(resolve an origin)의 결과(프록시가 "
DIRECT"일 때)로 여러 IP 주소를 받아 병렬로 연결을 시도하거나, IPv6 우선 등 정책을 구현할 수 있음을 의미한다. -
connection이 실패(failure)이면 continue.
-
new가 "
yes-and-dedicated"가 아니라면 append connection을 사용자 에이전트의 connection pool에 추가한다. -
connection을 반환한다.
-
-
실패(failure)를 반환한다.
여러 구현상의 뉘앙스가 존재하므로 의도적으로 다소 포괄적으로 서술되어 있다. 이것이
<link rel=preconnect> 기능도 설명하고,
연결(connection)이
credentials를 기반으로 구분됨을 명확하게
규정한다.
예컨대, TLS 세션 식별자는 credentials가 false인
연결과 true인 연결 간에
재사용되지 않는다는 점이 명확해진다.
연결 생성을 위해, 네트워크 파티션 키 key, origin origin, 불리언 credentials, 문자열 proxy, host host, 연결 타이밍 정보 timingInfo, 불리언 requireUnreliable, 그리고 WebTransport-hash 목록 webTransportHashes가 주어진다:
-
timingInfo의 connection start time을 unsafe shared current time으로 설정한다.
-
connection을 새 연결(connection)로 두되, key는 key, origin은 origin, credentials는 credentials, timing info는 timingInfo로 한다. connection timing info 기록(record connection timing info)을 connection에 대해 수행하고, proxy와 origin을 고려하여 host로 HTTP 연결을 설정한다. 아래 주의사항 참고. [HTTP] [HTTP1] [TLS]
-
requireUnreliable가 true라면, HTTP/3 등 신뢰할 수 없는 전송을 지원하는 연결을 설정한다. [HTTP3]
-
신뢰할 수 없는 전송을 지원하는 연결을 설정할 때는 WebTransport에 필요한 옵션을 활성화해야 한다. HTTP/3의 경우, 초기
SETTINGS프레임에SETTINGS_ENABLE_WEBTRANSPORT와H3_DATAGRAM값을 1로 포함한다. [WEBTRANSPORT-HTTP3] [HTTP3-DATAGRAM] -
credentials가 false면, TLS 클라이언트 인증서를 보내지 않는다.
-
webTransportHashes가 비어 있지 않으면, 기본 인증서 검증 알고리즘 대신, 서버 인증서가 사용자 정의 인증서 요건을 만족하고, 인증서 해시 검증이 webTransportHashes에 대해 true를 반환하면 서버 인증서가 유효한 것으로 간주한다. 조건이 충족되지 않으면 실패를 반환한다.
-
연결 설정에 실패하면(예: UDP, TCP, TLS 오류 등) 실패를 반환한다.
-
-
timingInfo의 ALPN 협상 프로토콜(ALPN negotiated protocol)을 connection의 ALPN Protocol ID로 설정하되, 다음 예외를 적용한다. [RFC7301]
-
프록시가 설정된 경우, 터널 연결이 수립됐다면 그 터널링된 프로토콜의 ALPN Protocol ID여야 하며, 아닐 경우 프록시의 첫 홉(hop)에 대한 값이어야 한다.
-
실험적이거나 등록되지 않은 프로토콜을 사용하는 경우, 사용된 ALPN Protocol ID(있다면)를 사용해야 한다. 프로토콜 협상에 ALPN이 사용되지 않았다면, 설명적인 다른 문자열을 써도 된다.
timingInfo의 ALPN 협상 프로토콜은 실제 협상 방식에 관계없이 사용 네트워크 프로토콜을 식별하기 위한 것이다. 즉 ALPN이 실제로 쓰이지 않더라도 사용된 프로토콜을 지시하는 ALPN Protocol ID다.
IANA는 ALPN Protocol ID 목록을 관리한다.
-
-
connection을 반환한다.
connection timing info 기록(record connection timing info) 알고리즘은 connection connection에 대해 timingInfo를 connection의 timing info로 두고, 다음 사항을 관찰한다:
-
timingInfo의 connection end time은 서버나 프록시 연결 직후 unsafe shared current time이어야 한다. 단, 아래의 세부사항 준수:
-
반환 시각에는 트랜스포트 연결 시간뿐 아니라, SOCKS 인증 등 기타 시간도 포함해야 한다. 자원 요청을 위한 TLS handshake 최소 완료까지의 시간도 포함해야 한다.
-
이 연결에 TLS False Start를 썼다면, 서버 Finished 메시지 수신까지의 시간은 포함하지 않는다. [RFC7918]
-
전체 handshake 완료를 기다리지 않고 early data로 요청을 보낸다면, 서버 ServerHello 수신까지의 시간은 포함하지 않는다. [RFC8470]
-
전체 handshake 완료를 기다려 요청을 보낸 경우, 이 시간에는 전체 TLS handshake가 포함된다(설령 다른 요청이 early data로 이미 전송됐더라도).
예시: 사용자 에이전트가 TLS 1.3 기반 HTTP/2 연결을 맺고
GET과POST요청을 보낸다. t1에 ClientHello 및GET을 early data로 보낸 뒤,POST는 안전하지 않으므로([HTTP] 9.2.1절), handshake가 완료된 t2까지 기다렸다가 보낸다. 두 요청 모두 같은 연결을 사용했지만GET의 connection end time은 t1,POST는 t2로 기록된다. -
-
보안 트랜스포트를 쓴 경우, timingInfo의 secure connection start time은 handshake 시작 직전 unsafe shared current time이어야 한다. [TLS]
-
connection이 HTTP/3라면, timingInfo의 connection start time과 secure connection start time이 동일해야 한다(HTTP/3에서는 보안 handshake가 연결 초기화와 동시에 이루어지기 때문). [HTTP3]
connection timing info clamp/coarsen 알고리즘은 재사용된 연결의 상세 정보 노출 방지 및 시간값 coarsen을 보장한다.
2.7. 네트워크 파티션 키(Network partition keys)
네트워크 파티션 키(network partition key)는 site와 null 또는 구현 정의 값을 요소로 하는 튜플이다.
네트워크 파티션 키 결정(determine the network partition key) 알고리즘은 environment environment가 주어졌을 때 다음을 따른다:
-
topLevelOrigin을 environment의 top-level origin으로 둔다.
-
topLevelOrigin이 null이면, topLevelOrigin을 environment의 top-level creation URL의 origin으로 둔다.
-
topLevelSite를 obtain a site 알고리즘을 topLevelOrigin에 대해 실행한 결과로 둔다.
-
secondKey를 null 또는 구현 정의 값 중 하나로 둔다.
secondKey는 의도적으로 다소 모호하게 정의되어 있다. 세부 내용은 아직 발전 중임. issue #1035 참고.
-
(topLevelSite, secondKey)를 반환한다.
네트워크 파티션 키 결정(determine the network partition key)을 하려면, request request에 대해 다음을 수행한다:
-
request의 reserved client가 null이 아니면, request의 reserved client를 사용하여 네트워크 파티션 키 결정 결과를 반환한다.
-
request의 client가 null이 아니면, request의 client를 사용하여 네트워크 파티션 키 결정 결과를 반환한다.
-
null을 반환한다.
2.8. HTTP 캐시 파티션(HTTP cache partitions)
HTTP 캐시 파티션 결정(determine the HTTP cache partition)을 하려면, request request에 대해 다음을 수행한다:
-
key를 request로 네트워크 파티션 키 결정(determine the network partition key)의 결과로 둔다.
-
key가 null이면, null을 반환한다.
-
key와 연관된 고유 HTTP 캐시를 반환한다. [HTTP-CACHING]
2.9. 포트 차단(Port blocking)
새로운 프로토콜은 TLS의 ALPN을 사용하여 프로토콜 협상을 통해 포트 차단의 필요성을 피할 수 있습니다. 이때는 HTTP 요청으로 프로토콜을 위조할 수 없습니다. [RFC7301]
request request를 가져오는 것이 나쁜 포트(bad port)로 인해 차단되어야 하는지 결정하려면:
-
url을 request의 현재 URL로 한다.
-
url의 스킴(scheme)이 HTTP(S) 스킴이고, url의 포트(port)가 나쁜 포트(bad port)라면, blocked를 반환한다.
-
allowed를 반환한다.
포트(port)가 나쁜 포트(bad port)이면 아래 표의 첫 번째 열에 나열된 값 중 하나이다.
| 포트 | 일반 서비스 |
|---|---|
| 0 | — |
| 1 | tcpmux |
| 7 | echo |
| 9 | discard |
| 11 | systat |
| 13 | daytime |
| 15 | netstat |
| 17 | qotd |
| 19 | chargen |
| 20 | ftp-data |
| 21 | ftp |
| 22 | ssh |
| 23 | telnet |
| 25 | smtp |
| 37 | time |
| 42 | name |
| 43 | nicname |
| 53 | domain |
| 69 | tftp |
| 77 | — |
| 79 | finger |
| 87 | — |
| 95 | supdup |
| 101 | hostname |
| 102 | iso-tsap |
| 103 | gppitnp |
| 104 | acr-nema |
| 109 | pop2 |
| 110 | pop3 |
| 111 | sunrpc |
| 113 | auth |
| 115 | sftp |
| 117 | uucp-path |
| 119 | nntp |
| 123 | ntp |
| 135 | epmap |
| 137 | netbios-ns |
| 139 | netbios-ssn |
| 143 | imap |
| 161 | snmp |
| 179 | bgp |
| 389 | ldap |
| 427 | svrloc |
| 465 | submissions |
| 512 | exec |
| 513 | login |
| 514 | shell |
| 515 | printer |
| 526 | tempo |
| 530 | courier |
| 531 | chat |
| 532 | netnews |
| 540 | uucp |
| 548 | afp |
| 554 | rtsp |
| 556 | remotefs |
| 563 | nntps |
| 587 | submission |
| 601 | syslog-conn |
| 636 | ldaps |
| 989 | ftps-data |
| 990 | ftps |
| 993 | imaps |
| 995 | pop3s |
| 1719 | h323gatestat |
| 1720 | h323hostcall |
| 1723 | pptp |
| 2049 | nfs |
| 3659 | apple-sasl |
| 4045 | npp |
| 4190 | sieve |
| 5060 | sip |
| 5061 | sips |
| 6000 | x11 |
| 6566 | sane-port |
| 6665 | ircu |
| 6666 | ircu |
| 6667 | ircu |
| 6668 | ircu |
| 6669 | ircu |
| 6679 | osaut |
| 6697 | ircs-u |
| 10080 | amanda |
2.10. response를 request에 대해 MIME 타입으로 차단해야 하는가?
다음 단계를 실행한다:
-
mimeType을 response의 header list에서 MIME 타입 추출의 결과로 둔다.
-
mimeType이 failure라면 allowed를 반환한다.
-
destination을 request의 destination으로 둔다.
-
destination이 script-like이고, 아래 중 하나라도 해당되면 blocked를 반환한다:
-
allowed를 반환한다.
3. HTTP 확장
3.1. 쿠키(Cookies)
`Cookie` 요청 헤더와 `Set-Cookie` 응답 헤더는 대부분 자체 명세에서 정의된다. 여기서는 이를 편리하게 사용하기 위한 추가 인프라를
정의한다. [COOKIES].
3.1.1. `Cookie` 헤더
요청의
`Cookie` 헤더를 추가(append a request `Cookie` header)하려면, request
request에 대해 다음을 수행한다:
-
사용자 에이전트가 request에 대해 쿠키를 사용하지 않도록 설정되어 있다면, 반환한다.
-
sameSite를 request에 대해 same-site 모드 결정(determine the same-site mode)의 결과로 둔다.
-
isSecure를 request의 현재 URL의 스킴(scheme)이 "
https"라면 true, 아니면 false로 둔다. -
httpOnlyAllowed를 true로 둔다.
fetch 에서 호출되는 경우이므로
document.cookiegetter와 달리 true가 된다. -
cookies를 쿠키 검색(retrieve cookies)을 isSecure, request의 현재 URL의 host, request의 현재 URL의 path, httpOnlyAllowed, sameSite를 넘겨 호출한 결과로 둔다.
쿠키 저장소는 정렬된 쿠키 목록을 반환한다.
-
cookies가 비어 있다면 반환한다.
-
value를 쿠키 직렬화(serialize cookies)를 cookies에 대해 실행한 결과로 둔다.
-
추가(Append) (`
Cookie`, value)를 request의 헤더 목록(header list)에 추가한다.
3.1.2. `Set-Cookie` 헤더
응답의 `Set-Cookie` 헤더 파싱 및 저장을
하려면,
request
request와 response response를 입력으로 다음을 수행한다:
-
사용자 에이전트가 request에 대해 쿠키 사용을 비활성화한 경우, 반환한다.
-
allowNonHostOnlyCookieForPublicSuffix를 false로 둔다.
-
isSecure를 request의 현재 URL의 스킴(scheme)이 "
https"이면 true, 아니면 false로 둔다. -
httpOnlyAllowed를 true로 둔다.
fetch에서 호출되었으므로(예:
document.cookiegetter가 아님) true가 된다. -
sameSiteStrictOrLaxAllowed를 동일 사이트 모드 결정(determine the same-site mode) 의 결과가 "
strict-or-less"면 true, 아니면 false로 둔다. -
각 response의 헤더 목록(header list)의 header에 대하여:
-
header의 이름(name)이 `
Set-Cookie`와 바이트 대소문자 무시(byte-case-insensitive)로 일치하지 않으면 continue 한다. -
쿠키 파싱 및 저장(Parse and store a cookie)를 header의 값(value), isSecure, request의 현재 URL의 host, request의 현재 URL의 path, httpOnlyAllowed, allowNonHostOnlyCookieForPublicSuffix, sameSiteStrictOrLaxAllowed로 실행한다.
-
쿠키 정리(Garbage collect cookies)를 request의 현재 URL의 host를 넘겨 실행한다.
다른 곳에서도 언급된 것처럼 `
Set-Cookie` 헤더는 병합될 수 없어 각 인스턴스별로 독립적으로 처리되어야 한다. 이는 다른 어떤 헤더에도 허용되지 않는다. -
3.1.3. 쿠키 인프라(Cookie infrastructure)
주어진 request request에 대해 same-site 모드 결정을 하려면:
-
단언(assert): request의 method가 "
GET" 또는 "POST"임을 단언한다. -
request의 최상위 네비게이션 발신자 출처(top-level navigation initiator origin)가 null이 아니고 request의 URL의 origin과 same site가 아니면 "
unset-or-less"를 반환한다. -
request의 method가 "
GET"이고, request의 destination이 "document"이면 "lax-or-less"를 반환한다. -
request의 client의 교차 사이트 상위(cross-site ancestor)가 있으면 "
unset-or-less"를 반환한다. -
request의 redirect-taint가 "
cross-site"이면, "unset-or-less"를 반환한다. -
"
strict-or-less"를 반환한다.
URL url에 대해 직렬화된 쿠키 기본 경로(serialized cookie default path)를 얻으려면:
-
cloneURL을 url의 복제본으로 둔다.
-
cloneURL의 경로(path)를 쿠키 기본 경로(cookie default path)로 설정한다. (대상은 cloneURL의 경로(path)임)
-
cloneURL의 URL 경로 직렬화(URL path serialization)를 반환한다.
3.2. `Origin` 헤더
`Origin`
요청 헤더(header)는
fetch가 어디에서 유래했는지(originates
from)를 나타낸다.
`Origin` 헤더는
경로(path)를 노출하지 않는
`Referer` [sic] 헤더 버전이다.
이는 request의
response tainting이 "cors"인
모든 HTTP fetch뿐 아니라,
request의
method가
`GET` 또는 `HEAD`가 아닐 때도 사용된다.
호환성 제약 때문에 모든 fetch에 포함되지는
않는다.
가능한 값은 요청 출처의 바이트 직렬화(byte-serializing a request origin)의 모든 반환값이며, request 기준으로 결정된다.
이 정의는 The Web Origin Concept의 정의를 대체한다. [ORIGIN]
요청
`Origin` 헤더 추가(append a request `Origin` header)를 하려면,
request
request에 대해 다음을 수행한다:
-
단언(assert): request의 origin이 "
client"가 아님을 단언한다. -
serializedOrigin을 요청 출처 바이트 직렬화(byte-serializing a request origin)를 request로 호출한 결과로 둔다.
-
request의 response tainting이 "
cors"이거나, request의 mode가 "websocket" 또는 "webtransport"이면, 추가(Append) (`Origin`, serializedOrigin)를 request의 헤더 목록(header list)에 추가한다. -
그렇지 않고 request의 method가 `
GET`도 아니고 `HEAD`도 아니라면:-
request의 mode가 "
cors"가 아니라면, request의 referrer policy에 따라 분기한다(switch):- "
no-referrer" -
serializedOrigin을 `
null`로 설정한다. - "
no-referrer-when-downgrade"- "
strict-origin"- "
strict-origin-when-cross-origin" - "
-
request의 origin이 튜플 출처(tuple origin)이고, 그 scheme이 "
https"이며, request의 현재 URL의 scheme이 "https"가 아니면, serializedOrigin을 `null`로 설정한다. - "
same-origin" -
request의 origin이 request의 현재 URL의 origin과 동일 출처(same origin)가 아니면, serializedOrigin을 `
null`로 설정한다. - 그 외
- 아무 것도 하지 않는다.
- "
-
추가(Append) (`
Origin`, serializedOrigin)를 request의 헤더 목록(header list)에 추가한다.
-
request의 referrer policy는, fetcher가 (예: CORS 프로토콜 등으로) 명시적으로 서버에 출처(origin) 공유를 선택하지 않은 모든 fetch에 대해 고려된다.
3.3. CORS 프로토콜
응답을 교차 출처(cross-origin)로 공유할 수 있게 하고 HTML의
form
요소로는 불가능한 더 다양한 fetch를 위해,
CORS 프로토콜이 존재한다.
CORS는 HTTP 위에 계층화되어 있으며, 응답이 다른
출처(origin)와 공유될 수 있음을 선언하도록 한다.
이 메커니즘은 방화벽(인트라넷) 뒤의 응답 데이터가 유출되는 것을 막기 위해 opt-in이어야 한다. 또한 요청(request)이 인증정보(credentials)를 포함할 때, 민감할 수 있는 데이터가 유출되지 않도록 opt-in이어야 한다.
이 절에서는 서버 개발자를 위한 CORS 프로토콜의 내용을 설명한다. 사용자 에이전트에 대한 요구사항은 fetch 알고리즘의 일부이며, 새로운 HTTP 헤더 문법은 예외다.
3.3.1. 일반
CORS 프로토콜은 응답이 교차 출처로 공유될 수 있는지를 나타내는 일련의 헤더로 구성되어 있다.
HTML의
form
요소만으로는 처리할 수 없는 좀 더 복잡한
요청에 대해서는,
CORS-사전요청(CORS-preflight request)을 수행하여,
요청의
현재
URL이
CORS 프로토콜을
지원하는지 확인한다.
3.3.2. HTTP 요청
CORS 요청이란
`Origin`
헤더를 포함하는 HTTP 요청을 말한다.
이 헤더는 CORS 프로토콜에 참여하는지 신뢰성 있게
판별할 수 있는 기준이 되지 않는다. 왜냐하면
`Origin`
헤더는 request의 method가
`GET` 또는
`HEAD`가 아닌 모든 경우에도 포함되기 때문이다.
CORS-사전
요청(CORS-preflight request)이란 CORS 요청으로,
CORS 프로토콜이 적용 가능한지 확인하는 역할을
한다.
이 때 method는
`OPTIONS`이고 다음 헤더가 포함된다:
CORS-사전 요청에는 다음 헤더도 포함될 수 있다:
3.3.3. HTTP 응답
CORS 요청에 대한 HTTP 응답에는 다음 헤더를 포함할 수 있다:
- `
Access-Control-Allow-Origin` -
응답이 공유될 수 있는지 나타내며, 요청의 `
Origin` 헤더의 리터럴 값 (또는 `null`)이나 `*`를 응답에서 반환한다. - `
Access-Control-Allow-Credentials` -
request의 credentials mode가 "
include"일 때 응답이 공유될 수 있는지 나타낸다.CORS-사전 요청의 경우 request의 credentials mode는 항상 "
same-origin"(즉, credentials 미포함)이지만, 이후의 CORS 요청에서는 그렇지 않을 수 있다. 따라서 CORS-사전 요청의 HTTP 응답에도 지원 여부를 표시해야 한다.
CORS-사전 요청에 대한 HTTP 응답에는 다음 헤더를 포함할 수 있다:
- `
Access-Control-Allow-Methods` -
응답의 response의 URL이 CORS 프로토콜 목적으로 지원하는 method를 나타낸다.
`
Allow` 헤더는 CORS 프로토콜 목적과는 무관하다. - `
Access-Control-Allow-Headers` - `
Access-Control-Max-Age` -
`
Access-Control-Allow-Methods`와 `Access-Control-Allow-Headers` 헤더의 정보를 몇 초(기본값 5초) 동안 캐시할 수 있는지 나타낸다.
CORS 요청이면서 CORS-사전 요청이 아닌 경우, 다음 헤더도 포함할 수 있다:
서버 개발자가 공유 의도가 있는 CORS 요청에 대한 성공적인 HTTP 응답은, 위에 명시된 헤더를 요청에 맞는 값으로 포함하기만 하면 어떤 status도 사용할 수 있다.
CORS-사전 요청에 대한 성공적인 HTTP 응답도 유사하나, ok status (예: 200 또는 204)로 제한된다.
그 외의 HTTP 응답은 성공적이지 않으며, 공유가 불가능하거나 CORS-사전 요청에 실패한다. 서버에서 수행한 작업이 타이밍 등 부채널로 누출될 수 있음에 유의해야 한다. 서버 개발자가 이를 명시적으로 나타내고 싶다면, 403 status와 관련 헤더의 생략을 함께 사용할 수 있다.
원한다면 "실패"도 공유할 수 있지만, 그러면 성공적인 HTTP 응답이 됩니다. 그렇기 때문에 CORS 요청에 대한 성공적인 HTTP 응답이 CORS 사전 요청이 아닌 경우, 상태는 403을 포함하여 어떤 값이든 될 수 있습니다.
결국 서버 개발자는 HTTP 응답 처리 방식에서 많은 자유를 가지며, 이러한 전략은 CORS-사전 요청과 그 이후 CORS 요청의 응답 처리 방식이 다를 수 있다:
-
정적 응답을 제공할 수 있다. 이는 캐시 중개자와 함께 작업할 때 유용하다. 정적 응답은 CORS 요청에 따라 성공이거나 아닐 수 있다. 이는 허용된다.
-
동적 응답을 제공할 수 있다. 이는 응답 본문을 특정 origin에 맞게 조정하거나 credentials가 필요하고 여러 origin에 대해 성공적이어야 할 때 유용하다.
3.3.4. HTTP new-header 문법
ABNF (형식)는 CORS 프로토콜에서 사용되는 헤더의 값에 대해 다음과 같다:
Access-Control-Request-Method = method
Access-Control-Request-Headers = 1 #field-name
wildcard = "*"
Access-Control-Allow-Origin = origin-or-null / wildcard
Access-Control-Allow-Credentials = %s"true" ; case-sensitive
Access-Control-Expose-Headers = #field-name
Access-Control-Max-Age = delta-seconds
Access-Control-Allow-Methods = #method
Access-Control-Allow-Headers = #field-name
`Access-Control-Expose-Headers`,
`Access-Control-Allow-Methods`, `Access-Control-Allow-Headers`
응답 헤더의 경우,
값
`*`는
인증정보(credentials)가 없는
요청(request)들에 대해
와일드카드(wildcard)로 취급된다. 이러한 요청에
대해서는 `*`인
헤더 이름 또는
메서드만을
단독으로 매칭시킬 방법은 없다.
3.3.5. CORS 프로토콜과 credentials
요청(request)의
credentials mode가 "include"일 때는
인증정보(credentials)를
fetch에 포함하는 것 외에도
CORS 프로토콜의 동작에 영향을 미친다.
예전에는 XMLHttpRequest를
사용해서
요청(request)의
credentials mode를 "include"로 설정할 수
있었다:
var client = new XMLHttpRequest()
client. open( "GET" , "./" )
client. withCredentials = true
/* … */
현재는 fetch("./", { credentials:"include" }).then(/* … */)
만으로 충분하다.
요청(request)의 credentials mode는 반드시 서버에서 관찰 가능한 것은 아니며, 인증정보(credentials)가 요청(request)에 포함되어야만 결과적으로 관찰된다. 단, CORS-사전요청(CORS-preflight request)에는 credentials가 포함되지 않는다.
따라서 서버 개발자는 인증정보(credentials)로 "오염(tainted)"된 응답을 공유할 수 있을지 여부, 그리고 요청(request)이 CORS-사전요청을 필요로 할 때 credentials를 포함할 수 있을지를 결정해야 한다. 일반적으로, 인증정보를 포함해 응답을 공유하거나 요청을 허용하는 것은 매우 위험하므로, confused deputy problem이 발생하지 않도록 극도의 주의를 기울여야 한다.
인증정보(credentials)와 함께 응답을 공유하려면,
`Access-Control-Allow-Origin` 및
`Access-Control-Allow-Credentials` 헤더(header)가
중요하다. 아래 표는 https://rabbit.invalid/에 대한 요청의 여러 합법/불법 조합을 예시한다:
| Request의 credentials mode | `Access-Control-Allow-Origin`
| `Access-Control-Allow-Credentials`
| 공유됨? | 비고 |
|---|---|---|---|---|
"omit"
| `*`
| 생략 | ✅ | — |
"omit"
| `*`
| `true`
| ✅ | credentials mode가 "include"가 아니면
`Access-Control-Allow-Credentials`
헤더는 무시된다.
|
"omit"
| `https://rabbit.invalid/`
| 생략 | ❌ | 직렬화된(serialized) origin에는 슬래시가 붙지 않는다. |
"omit"
| `https://rabbit.invalid`
| 생략 | ✅ | — |
"include"
| `*`
| `true`
| ❌ | credentials mode가 "include"면
`Access-Control-Allow-Origin`
값이 `*`일 수 없다.
|
"include"
| `https://rabbit.invalid`
| `true`
| ✅ | — |
"include"
| `https://rabbit.invalid`
| `True`
| ❌ | `true`는 (바이트) 대소문자 구분함.
|
마찬가지로,
`Access-Control-Expose-Headers`,
`Access-Control-Allow-Methods`,
`Access-Control-Allow-Headers` 응답 헤더는
request의
credentials mode가
"include"가 아닐 때에만 `*`를 값으로 사용할 수 있다.
3.3.6. 예시
https://foo.invalid/에 있는 스크립트가 https://bar.invalid/에서 데이터를 가져오고 싶어 한다. (credentials나 응답 헤더 접근은 중요하지
않다.)
var url = "https://bar.invalid/api?key=730d67a37d7f3d802e96396d00280768773813fbe726d116944d814422fc1a45&data=about:unicorn" ;
fetch( url). then( success, failure)
이 경우 CORS 프로토콜이 사용되지만,
foo.invalid의 개발자에게는 완전히 투명하다. CORS 프로토콜의 일부로, 사용자 에이전트는 요청에 `Origin` 헤더를 포함한다:
Origin: https://foo.invalid
bar.invalid로부터 응답을 받은 후, 사용자 에이전트는 `Access-Control-Allow-Origin` 응답 헤더를
확인한다. 값이 `https://foo.invalid` 또는 `*`라면 success 콜백을 호출한다. 그 외이거나
해당 헤더가 없으면 failure 콜백을 호출한다.
foo.invalid의 개발자가 다시 나타나, 이번엔 bar.invalid에서 데이터를 가져오면서 응답 헤더에 접근하고자 한다.
fetch( url). then( response => {
var hsts = response. headers. get( "strict-transport-security" ),
csp = response. headers. get( "content-security-policy" )
log( hsts, csp)
})
bar.invalid은 앞선 예시에서와 같이 올바른 `Access-Control-Allow-Origin` 응답 헤더를
제공한다. hsts와 csp 값은 `Access-Control-Expose-Headers` 응답
헤더에 따라 달라진다. 예를 들어, 응답에 다음과 같은 헤더가 있다면
Content-Security-Policy: default-src 'self'
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
Access-Control-Expose-Headers: Content-Security-Policy
이 경우 hsts는 null, csp는 "default-src 'self'"가 된다. 두 헤더 모두 응답에 포함되어
있지만, bar.invalid가 `Access-Control-Expose-Headers` 응답
헤더에 이름을 명시적으로 나열해 공유해야 하기 때문이다.
반대로, bar.invalid이 credentials를 포함하지 않는 요청에 대해 응답 헤더 전체를 공유하고 싶다면, `Access-Control-Expose-Headers` 응답
헤더 값으로 `*`를 사용할 수 있다. credentials가 포함된 요청의 경우에는 헤더 이름을 명시적으로 나열해야 하며 `*`는 사용할
수 없다.
foo.invalid의 개발자가 다시 돌아와, 이번에는 credentials를 포함해 bar.invalid에서 데이터를 가져온다. 이 경우 CORS 프로토콜이 개발자에게 투명하지
않다. credentials를 사용하려면 명시적으로
opt-in이 필요하기 때문이다:
fetch( url, { credentials: "include" }). then( success, failure)
이 경우 bar.invalid의 `Set-Cookie` 응답 헤더도 완전히 동작한다(그렇지 않으면 무시됨).
사용자 에이전트는 요청에 필요한 credentials도
모두 포함시킨다.
또한 응답에는 더 엄격한 요구사항이 적용된다. bar.invalid는 반드시 `https://foo.invalid` 값을 가진 `Access-Control-Allow-Origin` 헤더와,
`Access-Control-Allow-Credentials`
헤더도 포함해야 한다(`*`는 credentials가 있을 때 허용되지 않음):
Access-Control-Allow-Origin: https://foo.invalid
Access-Control-Allow-Credentials: true
응답에 이 두 헤더가 해당 값으로 포함되어 있지 않으면 failure 콜백이 호출된다. 단, `Set-Cookie` 응답 헤더는 항상
적용된다.
3.3.7. CORS 프로토콜 예외
명세에 따라 CORS safelist에 포함되지 않은 `Content-Type` 헤더 값에 대해 제한적인 예외가 허용되어 있다. 이러한 예외는 웹 콘텐츠가 트리거할 수
있지만, 웹 콘텐츠가 헤더와 본문을 최소한으로만 제어할 수 있는 요청에 한해서 만들어진 것이다. 따라서 서버는 교차 출처 웹 콘텐츠가 다음과 같은 safelist에 없는
`Content-Type` 헤더 값으로 사전 요청(preflight) 없이 요청을 트리거할 수 있음을 예상해야 한다:
- `
application/csp-report` [CSP] - `
application/expect-ct-report+json` [RFC9163] - `
application/xss-auditor-report` - `
application/ocsp-request` [RFC6960]
명세에서는 새 예외 도입을 피해야 하며, 반드시 신중히 보안 영향을 고려하여야 한다. 새로운 예외는 이슈 등록을 통해 제안할 수 있다.
3.4. `Content-Length` 헤더
`Content-Length` 헤더는 주로 HTTP에서 정의되어 있다. HTTP에서 정의된 처리 모델이 웹 콘텐츠와 호환되지 않으므로 여기서 처리 모델을 정의한다. [HTTP]
길이 추출(extract a length) 알고리즘은 header list headers에서 다음 단계를 실행한다:
-
values를 getting, decoding, and splitting `
Content-Length` from headers의 결과로 둔다. -
values가 null이면 null을 반환한다.
-
candidateValue를 null로 둔다.
-
각 values의 value에 대해:
-
candidateValue가 null이면 candidateValue에 value를 할당한다.
-
아니라면 value가 candidateValue와 다르면 failure를 반환한다.
-
-
candidateValue가 빈 문자열이거나, code point 중 ASCII digit이 아닌 것이 있으면 null을 반환한다.
-
candidateValue를 10진수 숫자로 해석하여 반환한다.
3.5. `Content-Type` 헤더
`Content-Type` 헤더는 주로 HTTP에서 정의되어 있다. HTTP에서 정의된 처리 모델이 웹 콘텐츠와 호환되지 않으므로 여기서 처리 모델을 정의한다. [HTTP]
MIME 타입 추출(extract a MIME type) 알고리즘은 header list headers에서 다음 단계를 실행한다. 반환 값은 failure 또는 MIME 타입이다.
-
charset을 null로 둔다.
-
essence를 null로 둔다.
-
mimeType을 null로 둔다.
-
values를 getting, decoding, and splitting `
Content-Type` from headers의 결과로 둔다. -
values가 null이면 failure를 반환한다.
-
각 values의 value에 대해:
-
temporaryMimeType을 MIME 타입 파싱(parsing) value 결과로 둔다.
-
temporaryMimeType이 failure이거나, 그 essence가 "
*/*"면 continue한다. -
mimeType을 temporaryMimeType으로 둔다.
-
mimeType의 essence가 essence와 다르면:
-
charset을 null로 둔다.
-
mimeType의 parameters["
charset"]가 존재하면 charset을 그 값으로 둔다. -
essence를 mimeType의 essence로 둔다.
-
-
아니라면, mimeType의 parameters["
charset"]가 존재하지 않고, charset이 null이 아니면 mimeType의 parameters["charset"]를 charset으로 둔다.
-
-
mimeType이 null이면 failure를 반환한다.
-
mimeType을 반환한다.
MIME 타입 추출이 failure를 반환하거나, MIME 타입의 essence가 해당 포맷에 대해 부적절할 경우, 이는 치명적 오류로 간주한다. 기존 웹 플랫폼 기능들은 항상 이 패턴을 따르지 않아 다수의 보안 취약점 원인이 되어 왔다. 이에 반해 MIME 타입의 parameters는 일반적으로 무시해도 안전하다.
MIME 타입 추출 알고리즘의 실제 동작 예시:
| 헤더(네트워크 상) | 출력(직렬화(serialized)) |
|---|---|
| text/html
|
| text/html;x=y;charset=gbk
|
| |
| text/html;x=y
|
| text/html
|
| |
|
레거시 인코딩 추출(legacy extract an encoding) 알고리즘은 failure 또는 MIME 타입 mimeType과 encoding fallbackEncoding이 주어졌을 때 다음을 따른다:
-
mimeType이 failure면 fallbackEncoding을 반환한다.
-
mimeType["
charset"]이 존재하지 않으면 fallbackEncoding을 반환한다. -
tentativeEncoding을 get an encoding 알고리즘에 mimeType["
charset"]을 넘겨 실행한 결과로 둔다. -
tentativeEncoding이 failure면 fallbackEncoding을 반환한다.
-
tentativeEncoding을 반환한다.
이 알고리즘은 mimeType이 failure일 수도 있게 하여, MIME 타입 추출과 쉽게 결합할 수 있도록 한다.
레거시로 명시된 이유는 현대 포맷은 반드시 UTF-8만 써야 하기 때문이다.
3.6.
`X-Content-Type-Options` 헤더
`X-Content-Type-Options`
응답 헤더는
response의
`Content-Type` 헤더가
요청의
destination에
적절한지 검사하도록 요구하는 데 사용될 수 있다.
헤더 목록(header list) list에 대해 nosniff 판정(determine nosniff)을 하려면 다음을 실행한다:
-
values를 get, decode, split을 list에서 `
X-Content-Type-Options` 에 대해 수행한 결과로 둔다. -
values가 null이면 false를 반환한다.
-
values[0]이 "
nosniff"와 ASCII 대소문자 구분 없이(ASCII case-insensitive) 일치하면 true를 반환한다. -
false를 반환한다.
웹 개발자와 적합성 검사기는 `X-Content-Type-Options`에 대해
아래의 값
ABNF를 반드시 사용해야 한다:
X-Content-Type-Options = "nosniff" ; case-insensitive
3.6.1. nosniff로 인해 response가 request에 대해 차단되어야 하는가?
다음 단계를 실행한다:
-
nosniff 판정(determine nosniff)을 response의 헤더 목록에 대해 호출했을 때 false라면 allowed를 반환한다.
-
mimeType을 헤더에서 MIME 타입 추출(extract MIME type)을 response의 헤더 목록에 대해 호출한 결과로 둔다.
-
destination을 request의 destination으로 둔다.
-
destination이 script-like이고 mimeType이 실패(failure)거나 자바스크립트 MIME 타입(JavaScript MIME type)이 아니면 blocked를 반환한다.
-
destination이 "
style"이고, mimeType이 실패(failure)거나 그 essence가 "text/css"가 아니면 blocked를 반환한다. -
allowed를 반환한다.
request의
destination 중
script-like이나
"style"만이 고려된다. 이는 악용 사례가 이 둘에 해당하기 때문이다.
또한 "image"에 대해선 배포된 컨텐트와 호환되지 않아 제외되었다.
3.7.
`Cross-Origin-Resource-Policy` 헤더
`Cross-Origin-Resource-Policy`
응답 헤더는
요청의
현재
URL의 origin을
요청의
origin과
검사하도록 요구할 때, 요청의
mode가
"no-cors"일 때 사용할 수 있다.
Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" / %s"cross-origin" ; case-sensitive
다음 입력을 받아 교차 출처 리소스 정책 검사(cross-origin resource policy check)를 수행하려면: origin origin, 환경 설정 객체(environment settings object) settingsObject, 문자열 destination, response response, 선택적 불리언 forNavigation을 받아 다음 단계를 실행한다:
-
forNavigation이 주어지지 않았으면 false로 둔다.
-
embedderPolicy를 settingsObject의 policy container의 embedder policy로 둔다.
-
cross-origin resource policy internal check를 origin, "
unsafe-none", response, forNavigation을 넘겨 호출했을 때 blocked를 반환한다면 blocked를 반환한다.이 단계는 아래의 Cross-Origin Embedder Policy와 관련 없는 위반사항은 보고하지 않도록 필요하다.
-
cross-origin resource policy internal check를 origin, embedderPolicy의 report only value, response, forNavigation으로 호출해서 blocked를 반환한다면, cross-origin embedder policy CORP violation report 큐잉을 response, settingsObject, destination, true로 실행한다.
-
cross-origin resource policy internal check를 origin, embedderPolicy의 value, response, forNavigation으로 호출해서 allowed를 반환한다면 allowed를 반환한다.
-
cross-origin embedder policy CORP violation report 큐잉을 response, settingsObject, destination, false로 실행한다.
-
blocked를 반환한다.
오직 HTML의 navigate 알고리즘만 forNavigation을 true로 주고 이 검사를 호출하는데 항상 중첩 탐색(nested navigation)에서 사용된다. 이외에는 response가 내부 응답(internal response) [opaque filtered response의]이거나, 응답(response)으로 [opaque filtered response의] 내부 응답이 될 것이다. [HTML]
origin origin, embedder policy value embedderPolicyValue, response response, 불리언 forNavigation을 입력으로 cross-origin resource policy internal check를 수행하려면:
-
forNavigation이 true이고 embedderPolicyValue가 "
unsafe-none"이면 allowed를 반환한다. -
policy를 헤더값 가져오기(get)로 response의 `
Cross-Origin-Resource-Policy` 헤더값을 가져온다.즉 `
Cross-Origin-Resource-Policy: same-site, same-origin` (콤마로 둘 다 있을 경우)는 실제론 아래에서 무조건 allowed가 된다. embedderPolicyValue가 "unsafe-none"인 한 어느 것도 매치되지 않기 때문이다. 하나 이상의 `Cross-Origin-Resource-Policy` 헤더가 있어도 효과는 같다. -
policy가 `
same-origin`, `same-site`, `cross-origin` 중 어느 것도 아니면 null로 설정한다. -
policy가 null이면 embedderPolicyValue 기준으로 분기한다:
- "
unsafe-none" -
아무 것도 하지 않는다.
- "
credentialless" -
아래 둘 중 하나라도 true면 policy를 `
same-origin`으로 설정한다:- response의 request-includes-credentials 가 true이거나,
- forNavigation이 true
- "
require-corp" -
policy를 `
same-origin`으로 설정한다.
- "
-
policy에 따라 분기한다:
- null
- `
cross-origin` - `
-
allowed를 반환한다.
- `
same-origin` -
origin이 동일 출처(same origin)이고, response의 URL의 origin과 동일하면 allowed 반환, 그렇지 않으면 blocked 반환.
- `
same-site` -
아래 모두 해당하면 allowed:
-
origin이 schemelessly same site이고, response의 URL의 origin과 같음.
-
origin의 스킴(scheme)이 "
https"이거나, response의 URL의 스킴이 "https"가 아님
위 조건을 모두 만족하면 allowed 반환, 아니면 blocked 반환.
`
Cross-Origin-Resource-Policy: same-site`는 보안 전송(secure transport)으로 전송된 응답이 비보안 요청 origin과 동일 사이트(host가 같아도)로 간주하지 않는다. 보안 전송된 응답은 반드시 보안 전송된 발신자(initiator)와만 매치된다. -
- null
response response, environment settings object settingsObject, 문자열 destination, 불리언 reportOnly가 입력일 때, cross-origin embedder policy CORP violation report 큐잉 알고리즘은 다음과 같다:
-
endpoint를 reportOnly가 true이면서 settingsObject의 policy container의 embedder policy의 report only reporting endpoint라면 그것으로, 아니면 reporting endpoint로 둔다.
-
serializedURL를 응답 URL 직렬화(serialize a response URL for reporting)를 response에 수행한 결과로 둔다.
-
disposition을 reportOnly가 true라면 "
reporting"으로, 아니면 "enforce"로 둔다. -
body를 다음 속성을 갖는 새 객체로 둔다:
key value " type"" corp"" blockedURL"serializedURL " destination"destination " disposition"disposition -
Generate and queue a report를, settingsObject의 글로벌 객체(global object), "
coep" 리포트 타입(report type), endpoint, body를 넘겨 실행한다. [REPORTING]
3.8. `Sec-Purpose` 헤더
`Sec-Purpose` HTTP 요청
헤더는 요청이 사용자가 즉시 사용할 리소스를 요청하는 것 외에 하나 이상의 목적을 가짐을 명시한다.
`Sec-Purpose` 헤더 필드는 구조화 헤더이며,
그 값은 토큰(token)이어야 한다.
정의된 유일한 토큰(token)은 prefetch이다.
이는 요청의 목적이 곧 필요할 것으로 예상되는 리소스를 미리 가져오기 위함임을 나타낸다.
서버는 이를 이용해 prefetch에 대한 캐싱 만료를 조정하거나, prefetch를 거부하거나, 페이지 방문 수 집계 시 다르게 처리할 수 있다.
4. 가져오기
아래 알고리즘은 가져오기(fetching)를 정의한다. 대략적으로, 이는 요청(request) 하나와 작업 도중 여러 시점에 실행될 하나 이상의 알고리즘을 취한다. 마지막에 열거된 두 알고리즘에는 응답이 전달된다. 처음 두 알고리즘은 업로드를 캡처하는 데 사용할 수 있다.
다음 단계들을 실행한다: fetch를 수행하기 위해, 주어진 요청 request, 선택적 알고리즘 processRequestBodyChunkLength, 선택적 알고리즘 processRequestEndOfBody, 선택적 알고리즘 processEarlyHintsResponse, 선택적 알고리즘 processResponse, 선택적 알고리즘 processResponseEndOfBody, 선택적 알고리즘 processResponseConsumeBody, 그리고 선택적 불리언 useParallelQueue (기본값 false)이 주어지면 아래 단계를 실행한다. 주어진다면, processRequestBodyChunkLength는 전송된 바이트 수를 나타내는 정수를 인수로 받는 알고리즘이어야 한다. 주어진다면, processRequestEndOfBody는 인수를 받지 않는 알고리즘이어야 한다. 주어진다면, processEarlyHintsResponse는 응답을 인수로 받는 알고리즘이어야 한다. 주어진다면, processResponse는 응답을 인수로 받는 알고리즘이어야 한다. 주어진다면, processResponseEndOfBody는 응답을 인수로 받는 알고리즘이어야 한다. 주어진다면, processResponseConsumeBody는 응답과 null, 실패, 또는 바이트 시퀀스를 인수로 받는 알고리즘이어야 한다.
사용자 에이전트는 진행 중인 fetch를 일시중단하도록 요청받을 수 있다. 사용자 에이전트는 일시중단 요청을 수락하거나 무시할 수 있다. 일시중단된 fetch는 재개될 수 있다. 사용자 에이전트는 진행 중인 fetch가 요청에 대한 HTTP 캐시의 응답을 갱신하고 있는 경우 일시중단 요청을 무시해야 한다.
사용자 에이전트는 요청의 캐시 모드가 "no-store"이거나 응답에 `Cache-Control: no-store`
헤더가 나타나면 해당 요청에 대한
HTTP 캐시 항목을 갱신하지 않는다. [HTTP-CACHING]
-
단언(Assert): request의 mode가 "
navigate"이거나 processEarlyHintsResponse가 null이다.초기 힌트(상태가 103인 응답)의 처리는 네비게이션에 대해서만 검증된다.
-
taskDestination를 null로 둔다.
-
crossOriginIsolatedCapability를 false로 둔다.
-
클라이언트로부터 요청 채우기를 주어진 request로 실행한다.
-
만약 request의 클라이언트가 null이 아니면, 다음을 실행한다:
-
crossOriginIsolatedCapability를 request의 클라이언트의 교차 출처 격리 능력으로 설정한다.
-
만약 useParallelQueue가 true이면, taskDestination를 새 병렬 큐 시작의 결과로 설정한다.
-
timingInfo를 새로운 fetch timing info로 정한다. 그 시작 시간과 리디렉션 이후 시작 시간은 조정된 공유 현재 시간이며 crossOriginIsolatedCapability를 고려하여 가져온다. 또한 렌더 차단(render-blocking)은 request의 render-blocking으로 설정된다.
-
fetchParams를 새로운 fetch params로 정한다. 그 request는 request이고, timing info는 timingInfo, process request body chunk length는 processRequestBodyChunkLength, process request end-of-body는 processRequestEndOfBody, process early hints response는 processEarlyHintsResponse, process response는 processResponse, process response consume body는 processResponseConsumeBody, process response end-of-body는 processResponseEndOfBody, task destination는 taskDestination, 그리고 cross-origin isolated capability는 crossOriginIsolatedCapability로 설정한다.
-
만약 request의 본문이 바이트 시퀀스라면, request의 본문을 request의 본문을 바디로서 설정한다.
-
다음 모든 조건이 참이면:
-
request의 URL의 스킴이 HTTP(S) 스킴이다.
-
request의 mode가 "
same-origin", "cors", 또는 "no-cors"이다. -
request의 클라이언트가 null이 아니고, request의 클라이언트의 글로벌 객체가
Window객체이다. -
request의 메서드가 `
GET`이다. -
request의 unsafe-request 플래그가 설정되어 있지 않거나 request의 헤더 목록이 비어 있다.
그렇다면:
-
단언(Assert): request의 원점(origin)이 request의 클라이언트의 origin과 동일 출처(same origin)임을 단언한다.
-
onPreloadedResponseAvailable를 다음과 같은 알고리즘으로 정한다: 주어진 응답 response에 대해 실행되는 알고리즘은 fetchParams의 preloaded response candidate를 response로 설정한다.
-
foundPreloadedResource를 request의 consume a preloaded resource를 request의 클라이언트에 대해 호출한 결과로 정한다. 호출에는 request의 URL, request의 destination, request의 mode, request의 credentials mode, request의 무결성 메타데이터, 그리고 onPreloadedResponseAvailable를 넘긴다.
-
만약 foundPreloadedResource가 true이고 fetchParams의 preloaded response candidate가 null이면, fetchParams의 해당 항목을 "
pending"으로 설정한다.
-
-
만약 request의 헤더 목록이 `
Accept`를 포함하지 않으면:-
value를 `
*/*`로 둔다. -
만약 request의 initiator가 "
prefetch"라면, value를 문서의 `Accept` 헤더 값으로 설정한다. -
그렇지 않으면, 사용자 에이전트는 request의 destination를 기준으로 다음 중 첫 번째 일치 항목으로 value를 설정해야 한다:
- "
document"- "
frame"- "
iframe" - "
- 문서의 `
Accept` 헤더 값 - "
image" - `
image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5` - "
json" - `
application/json,*/*;q=0.5` - "
style" - `
text/css,*/*;q=0.1`
- "
-
추가(Append) (`
Accept`, value)를 request의 헤더 목록에 수행한다.
-
-
만약 request의 헤더 목록이 `
Accept-Language`를 포함하지 않고 request의 클라이언트가 null이 아니면:-
emulatedLanguage를 WebDriver BiDi 모사 언어로 정한다. 이는 request의 클라이언트에 대한 값이다.
-
만약 emulatedLanguage가 null이 아니면:
-
encodedEmulatedLanguage를 emulatedLanguage의 isomorphic 인코딩으로 둔다.
-
추가(Append) (`
Accept-Language`, encodedEmulatedLanguage)를 request의 헤더 목록에 수행한다.
-
-
-
만약 request의 헤더 목록이 `
Accept-Language`를 포함하지 않으면, 사용자 에이전트는 추가 (`Accept-Language, 적절한 헤더 값)를 request의 헤더 목록에 수행해야 한다. -
만약 request의 내부 우선순위(request-internal-priority)가 null이면, request의 우선순위, initiator, destination, 및 render-blocking을 구현 방식에 따라 사용하여 request의 내부 우선순위를 구현 상 정의된 객체로 설정한다.
구현 상 정의된 객체는 HTTP/2의 스트림 가중치와 의존성, 적용되는 전송(예: HTTP/3)을 위한 Extensible Prioritization Scheme for HTTP에서 사용되는 우선순위, 또는 HTTP/1 페치의 디스패치 및 처리 우선순위를 정하는 데 사용되는 동등한 정보를 포함할 수 있다. [RFC9218]
-
만약 request가 서브리소스 요청(subresource request)이면:
-
record를 새로운 fetch record로 정한다. 그 request는 request이고 controller는 fetchParams의 controller이다.
-
추가(Append) record를 request의 클라이언트의 fetch group의 fetch records에 추가한다.
-
-
메인 fetch를 fetchParams로 실행한다.
-
fetchParams의 controller를 반환한다.
주어진 요청 request에 대해 클라이언트로부터 요청을 채우기를 수행하려면:
-
만약 request의 사용자 프롬프트를 위한 traversable가 "
client"이면:-
request의 사용자 프롬프트를 위한 traversable를 "
no-traversable"로 설정한다. -
만약 request의 클라이언트가 null이 아니면:
-
만약 global가
Window객체이고 global의 navigable이 null이 아니면, request의 사용자 프롬프트를 위한 traversable를 global의 navigable의 traversable navigable로 설정한다.
-
-
만약 request의 origin이 "
client"이면:-
단언(Assert): request의 클라이언트는 null이 아니다.
-
-
만약 request의 정책 컨테이너(policy container)가 "
client"이면:
4.1. 메인 fetch
main fetch를 실행하려면, fetch params fetchParams와 선택적 불리언 recursive (기본값 false)를 받아 다음 단계를 실행한다:
-
request를 fetchParams의 request로 둔다.
-
response를 null로 둔다.
-
request의 local-URLs-only flag가 설정되어 있고, request의 current URL이 local이 아니면, response를 네트워크 에러로 설정한다.
-
request가 잘못된 포트로 인해 차단되어야 하는지, request fetch가 혼합 콘텐츠로 인해 차단되어야 하는지, Content Security Policy에 의해 request가 차단되어야 하는지, 무결성 정책에 의해 request가 차단되어야 하는지 중 하나라도 blocked를 반환하면, response를 네트워크 에러로 설정한다.
-
request의 referrer policy가 빈 문자열이면, request의 referrer policy를 request의 policy container의 referrer policy로 설정한다.
-
request의 referrer가 "
no-referrer"가 아니면, request의 referrer를 request의 referrer 결정의 결과로 설정한다. [REFERRER]Referrer Policy에서 명시한 대로, 사용자 에이전트는 최종 사용자에게 request의 referrer를 "
no-referrer"로 오버라이드하거나 덜 민감한 정보만 노출하도록 선택권을 제공할 수 있습니다. -
request의 current URL의 scheme을 아래 조건이 모두 true이면 "
https"로 설정한다:- request의 current URL의 scheme이
"
http"임 - request의 current URL의 host가 도메인임
- request의 current URL의 host의
public suffix가 "
localhost" 또는 "localhost."가 아님 - request의 current URL의 host를
Known HSTS Host Domain
Name Matching으로 매칭한 결과,
includeSubDomains지시가 있는 슈퍼도메인 매칭 또는 congruent 매칭(지시 유무 상관없이)임 [HSTS] 또는 요청의 DNS 조회로 section 9.5에서 명시한 HTTPS RR이 매칭됨 [HSTS] [SVCB]
모든 DNS 동작은 일반적으로 구현 정의이므로, DNS 조회에 HTTPS RR이 포함되어 있는지 판단하는 방법 역시 구현 정의입니다. DNS 동작은 전통적으로 연결 얻기 시점까지 수행되지 않으므로, 사용자 에이전트는 더 일찍 DNS 동작을 수행하거나, 로컬 DNS 캐시를 참조하거나, fetch 알고리즘 내에서 더 늦게까지 기다렸다가 scheme 변경이 필요함을 발견해서 로직을 되돌릴 수도 있습니다.
- request의 current URL의 scheme이
"
-
recursive가 false이면, 남은 단계를 병렬로 실행한다.
-
response가 null이면, 다음에서 처음으로 일치하는 구문에 해당하는 단계를 실행한 결과를 response로 설정한다:
- fetchParams의 preloaded response candidate가 null이 아님
-
-
fetchParams의 preloaded response candidate가 "
pending"이 아닐 때까지 대기한다. -
Assert: fetchParams의 preloaded response candidate가 response임
-
fetchParams의 preloaded response candidate를 반환한다.
-
- request의 current URL의 origin이 request의 origin과 same origin이고, request의
response tainting이
"
basic"임- request의 current URL의 scheme이 "
data"임- request의 mode가 "
navigate", "websocket", 또는 "webtransport"인 경우 - request의 current URL의 scheme이 "
-
-
request의 response tainting을 "
basic"으로 설정한다. -
"
scheme-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.
HTML은 URL의 스킴이 "
data"인 경우, 해당 문서와 워커에 고유한 불투명 출처(opaque origin)를 할당합니다. 서비스 워커는 URL의 스킴이 HTTP(S) 스킴인 경우에만 생성될 수 있습니다. [HTML] [SW] -
- request의 mode가 "
same-origin"임 -
네트워크 에러를 반환한다.
- request의 mode가 "
no-cors"임 -
-
request의 redirect mode가 "
follow"가 아니면, 네트워크 에러를 반환한다. -
request의 response tainting을 "
opaque"로 설정한다. -
"
scheme-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.
-
- request의 current URL의 scheme이 HTTP(S) scheme이 아니면
-
네트워크 에러를 반환한다.
- request의 use-CORS-preflight flag가 설정됨
- request의 unsafe-request flag가 설정되어 있고, request의 method가 CORS-safelisted method가 아니거나, CORS-unsafe request-header names가 request의 header list에 비어있지 않음
-
-
request의 response tainting을 "
cors"로 설정한다. -
corsWithPreflightResponse를 "
http-fetch", fetchParams, 그리고 true를 주어 override fetch를 실행한 결과로 설정한다. -
corsWithPreflightResponse가 네트워크 에러면, 캐시 엔트리 삭제를 request로 실행한다.
-
corsWithPreflightResponse를 반환한다.
-
- 그 외의 경우
-
-
request의 response tainting을 "
cors"로 설정한다. -
"
http-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.
-
-
recursive가 true면 response를 반환한다.
-
response가 네트워크 에러가 아니고 response가 filtered response가 아니면:
-
request의 response tainting이 "
cors"이면:-
headerNames를 extracting header list values를 `
Access-Control-Expose-Headers`와 response의 header list로 실행한 결과로 둔다. -
request의 credentials mode가 "
include"가 아니고, headerNames가 `*`를 포함하면, response의 CORS-exposed header-name list를 response의 header list 내의 모든 고유 header name로 설정한다. -
그 외에 headerNames가 null 또는 실패가 아니면, response의 CORS-exposed header-name list를 headerNames로 설정한다.
headerNames 중 하나가 여전히 `
*`일 수 있지만, 이는 header의 name이 `*`인 경우에만 일치한다.
-
-
response를 filtered response로 설정한다. response를 내부 응답으로 두고, request의 response tainting에 따라 아래와 같이 한다:
- "
basic" - basic filtered response
- "
cors" - CORS filtered response
- "
opaque" - opaque filtered response
- "
-
-
internalResponse를 response가 네트워크 에러일 경우 response로, 아니면 response의 internal response로 둔다.
-
internalResponse의 URL list가 비어 있으면, request의 URL list의 복제본으로 설정한다.
-
internalResponse의 redirect taint를 request의 redirect-taint로 설정한다.
-
request의 timing allow failed flag가 설정되어 있지 않으면, internalResponse의 timing allow passed flag를 설정한다.
-
response가 네트워크 에러가 아니고, 아래 중 하나라도 blocked를 반환하면
이 경우 response와 internalResponse를 네트워크 에러로 설정한다.
-
response의 type이 "
opaque"이고, internalResponse의 status가 범위 상태이며, internalResponse의 범위 요청 플래그가 설정되어 있고, request의 헤더 목록이 `Range`를 포함하지 않는 경우, response와 internalResponse를 네트워크 오류로 설정합니다.전통적으로 API는 범위가 요청되지 않았더라도 범위가 지정된 응답을 허용합니다. 이는 이전의 범위 요청으로부터의 부분 응답이나 범위를 만족할 수 없는 응답이 범위 요청을 하지 않은 API에 제공되는 것을 방지합니다.
추가 세부 사항
위 단계는 다음과 같은 공격을 방지합니다:
미디어 요소가 교차 출처 HTML 리소스의 범위를 요청하는 데 사용됩니다. 이는 유효하지 않은 미디어이지만, 응답의 복제본에 대한 참조를 서비스 워커에 유지할 수 있습니다. 이후 이는 스크립트 요소의 fetch에 대한 응답으로 사용될 수 있습니다. 부분 응답이 유효한 JavaScript인 경우(전체 리소스는 그렇지 않더라도), 이를 실행하면 개인 데이터가 유출될 수 있습니다.
-
response가 네트워크 에러가 아니고, request의 method가 `
HEAD` 또는 `CONNECT`이거나, internalResponse의 status가 null body status이면, internalResponse의 body를 null로 설정하고, 그에 대한 enqueuing은 무시한다.이것은 HTTP를 위반하는 서버에 대한 에러 처리를 표준화합니다.
-
request의 integrity metadata가 빈 문자열이 아니면:
-
processBodyError를 다음 단계로 설정: fetch response handover를 fetchParams와 네트워크 에러로 실행한다.
-
response의 body가 null이면, processBodyError를 실행하고, 이 단계를 중단한다.
-
processBody를 bytes를 인자로 받아 다음 단계로 설정:
-
bytes가 request의 integrity metadata와 일치하지 않으면, processBodyError를 실행하고, 이 단계를 중단한다. [SRI]
-
fetch response handover를 fetchParams와 response로 실행한다.
-
-
body 완전 읽기를 response의 body, processBody와 processBodyError로 실행한다.
-
-
그 외의 경우, fetch response handover를 fetchParams와 response로 실행한다.
fetch response handover는 fetch params fetchParams와 response response를 받아 다음 단계를 실행한다:
-
timingInfo를 fetchParams의 timing info로 둔다.
-
response가 네트워크 에러가 아니고, fetchParams의 request의 client가 secure context이면, timingInfo의 server-timing headers를 response의 internal response의 header list에서 `
Server-Timing`을 get/decode/split한 결과로 설정한다.internal response를 사용하는 것은 `
Server-Timing` 헤더 데이터 노출이 `Timing-Allow-Origin` 헤더로 보호되기 때문에 안전하다.사용자 에이전트는 `
Server-Timing` 헤더를 non-secure context 요청에도 노출할 수 있다. -
만약 fetchParams의 request의 destination이 "
document"라면, fetchParams의 controller의 full timing info를 fetchParams의 timing info로 설정한다. -
processResponseEndOfBody를 다음 단계로 둔다:
-
unsafeEndTime을 unsafe shared current time으로 둔다.
-
fetchParams의 controller의 report timing steps를 global object global을 받아 다음 단계로 둔다:
-
fetchParams의 request의 URL의 scheme이 HTTP(S) scheme이 아니면 return.
-
timingInfo의 end time을 relative high resolution time으로, unsafeEndTime과 global을 인자로 설정한다.
-
cacheState를 response의 cache state로 둔다.
-
bodyInfo를 response의 body info로 둔다.
-
response의 timing allow passed flag가 설정되어 있지 않으면, timingInfo를 opaque timing info 생성의 결과로 설정하고, cacheState를 빈 문자열로 설정한다.
response가 네트워크 에러인 경우도 포함한다.
-
responseStatus를 0으로 둔다.
-
fetchParams의 request의 mode가 "
navigate"가 아니거나 response의 redirect taint가 "same-origin"이면:-
responseStatus를 response의 status로 설정한다.
-
mimeType을 response의 header list에서 extracting a MIME type의 결과로 둔다.
-
mimeType이 실패가 아니면, bodyInfo의 content type을 minimizing a supported MIME type의 결과로 mimeType을 넘겨 설정한다.
-
-
fetchParams의 request의 initiator type이 null이 아니면, mark resource timing을 timingInfo, fetchParams의 request의 URL, fetchParams의 request의 initiator type, global, cacheState, bodyInfo, responseStatus로 실행한다.
-
-
processResponseEndOfBodyTask를 다음 단계로 설정한다:
-
fetchParams의 process response end-of-body가 null이 아니면, fetchParams의 process response end-of-body를 response로 실행한다.
-
fetchParams의 request의 initiator type이 null이 아니고, fetchParams의 request의 client의 global object가 fetchParams의 task destination이면, fetchParams의 controller의 report timing steps를 fetchParams의 request의 client의 global object로 실행한다.
-
fetch task 큐에 넣기를 실행하여 processResponseEndOfBodyTask를 fetchParams의 task destination과 함께 실행한다.
-
-
fetchParams의 process response가 null이 아니면, fetch task 큐에 넣기를 실행하여 fetchParams의 process response를 response로, fetchParams의 task destination과 함께 실행한다.
-
internalResponse를 response가 네트워크 에러일 경우 response로, 아니면 response의 internal response로 둔다.
-
internalResponse의 body가 null이면, processResponseEndOfBody를 실행한다.
-
그 외의 경우:
-
transformStream을 새로운
TransformStream으로 둔다. -
identityTransformAlgorithm을 알고리즘으로 두고, chunk를 받아 transformStream에 enqueue한다.
-
transformStream 설정을 실행하여, transformAlgorithm을 identityTransformAlgorithm으로, flushAlgorithm을 processResponseEndOfBody로 설정한다.
-
internalResponse의 body의 stream을 internalResponse의 body의 stream을 transformStream에 파이프한 결과로 설정한다.
이
TransformStream은 스트림이 끝에 도달할 때 알림을 받기 위해 필요하며, 그 외에는 identity transform stream이다. -
-
fetchParams의 process response consume body가 null이 아니면:
-
processBody를 nullOrBytes를 인자로 받아, fetchParams의 process response consume body를 response와 nullOrBytes로 실행하는 단계로 설정한다.
-
processBodyError를 fetchParams의 process response consume body를 response와 failure로 실행하는 단계로 설정한다.
-
internalResponse의 body가 null이면, fetch task 큐에 넣기를 실행하여 processBody를 null로 실행하고, fetchParams의 task destination과 함께 실행한다.
-
그 외에는, body 완전 읽기를 internalResponse의 body, processBody, processBodyError, fetchParams의 task destination로 실행한다.
-
4.2. 오버라이드 fetch
override
fetch는 "scheme-fetch" 또는
"http-fetch" type, fetch params fetchParams, 그리고 선택적 boolean
makeCORSPreflight (기본값 false)를 입력으로 받는다:
-
request를 fetchParams의 request로 설정한다.
-
response를 request에 대해 potentially override response for a request를 실행한 결과로 설정한다.
-
response가 null이 아니면 response를 반환한다.
-
type에 따라 다음 단계 중 하나를 실행한다:
- "
scheme fetch" -
response를 fetchParams를 입력으로 scheme fetch를 실행한 결과로 설정한다.
- "
HTTP fetch" -
response를 fetchParams와 makeCORSPreflight를 입력으로 HTTP fetch를 실행한 결과로 설정한다.
- "
-
response를 반환한다.
이 potentially override response for a request 알고리즘은 request request를 받아, response 또는 null을 반환한다. 그 동작은 implementation-defined, 사용자 에이전트가 request에 대해 응답을 직접 반환하여 개입하거나, null을 반환하여 요청이 계속 진행되도록 허용한다.
기본적으로 이 알고리즘은 다음과 같이 단순하게 구현된다:
-
null을 반환한다.
사용자 에이전트는 일반적으로 이 기본 구현을 보다 복잡한 동작으로 오버라이드한다. 예를 들어, 사용자 에이전트는 사용자의 안전을 위해 일반적으로 `https://unsafe.example/`로의 요청을 차단하지만, `https://unsafe.example/widget.js`와 같은 널리 사용되는 리소스에 대해서는 호환을 위해 shim을 생성할 수 있다. 그 구현 예시는 아래와 같다:
-
request의 current url의 host의 등록 가능한 도메인이 "
unsafe.example"이면:-
request의 current url의 path가 « "
widget.js" »이면: -
network error를 반환한다.
-
-
null을 반환한다.
4.3. 스킴 fetch
스킴 fetch는 fetch params fetchParams를 입력으로 받는다:
-
fetchParams가 취소됨이면, fetchParams에 대해 적절한 네트워크 오류를 반환한다.
-
request를 fetchParams의 request로 설정한다.
-
request의 current URL의 scheme에 따라 다음 단계를 실행한다:
- "
about" -
request의 current URL의 path가 "
blank" 문자열이면, response를 새로 만들어 반환한다. status message는 `OK`, header list는 « (`Content-Type`, `text/html;charset=utf-8`) », body는 빈 바이트 시퀀스를 body로 변환한 값이다.URL "
about:config" 등은 네비게이션 처리 시 다루며, fetch 맥락에서는 네트워크 오류가 발생한다. - "
blob" -
-
blobURLEntry를 request의 current URL의 blob URL entry로 둔다.
-
request의 method가 `
GET`이 아니거나 blobURLEntry가 null이면, network error를 반환한다. [FILEAPI]`
GET` method 제한은 상호 운용 가능하다는 것 외에는 유용한 목적을 제공하지 않는다. -
requestEnvironment를, request를 주어 environment를 결정한 결과로 둔다.
-
isTopLevelSelfFetch를 false로 둔다.
-
request의 client가 null이 아니면:
-
global을 request의 client의 global object로 둔다.
-
다음 모든 조건이 참이면:
-
global은
Window객체이다; -
global의 navigable이 null이 아니다;
-
requestEnvironment의 creation URL이 equals로 request의 current URL과 같다,
그러면 isTopLevelSelfFetch를 true로 설정한다.
-
-
-
stringOrEnvironment를 다음 단계의 결과로 둔다:
-
request의 destination이 "
document"이면, "top-level-navigation"을 반환한다. -
isTopLevelSelfFetch가 true이면, "
top-level-self-fetch"를 반환한다. -
requestEnvironment를 반환한다.
-
-
blob을, blobURLEntry와 stringOrEnvironment를 주어 blob 객체를 얻는 결과로 둔다.
-
blob이
Blob객체가 아니면, network error를 반환한다. -
response를 새로운 response로 둔다.
-
fullLength를 blob의
size로 둔다. -
serializedFullLength를 fullLength를 serialized하고 isomorphic encoded한 값으로 둔다.
-
type을 blob의
type으로 둔다. -
request의 header list가 포함하지 않는다면 `
Range`:-
bodyWithType를 safely extracting blob의 결과로 둔다.
-
response의 status message를 `
OK`로 설정한다. -
response의 header list를 « (`
Content-Length`, serializedFullLength), (`Content-Type`, type) »로 설정한다.
-
-
그 외의 경우:
-
response의 range-requested flag를 설정한다.
-
rangeHeader를, request의 header list에서 `
Range`를 getting한 결과로 둔다. -
rangeValue를, rangeHeader와 true를 주어 parsing a single range header value의 결과로 둔다.
-
rangeValue가 failure이면, network error를 반환한다.
-
(rangeStart, rangeEnd)를 rangeValue로 둔다.
-
rangeStart가 null이면:
-
rangeStart를 fullLength − rangeEnd로 설정한다.
-
rangeEnd를 rangeStart + rangeEnd − 1로 설정한다.
-
-
그 외의 경우:
-
rangeStart가 fullLength 이상이면, network error를 반환한다.
-
rangeEnd가 null이거나 rangeEnd가 fullLength 이상이면, rangeEnd를 fullLength − 1로 설정한다.
-
-
slicedBlob을, blob, rangeStart, rangeEnd + 1, 그리고 type을 주어 slice blob을 호출한 결과로 둔다.
range 헤더는 포함(inclusive)된 바이트 범위를 나타내지만, slice blob 알고리즘의 입력 범위는 그렇지 않다. slice blob 알고리즘을 사용하려면 rangeEnd를 증가시켜야 한다.
-
slicedBodyWithType를 safely extracting slicedBlob의 결과로 둔다.
-
serializedSlicedLength를 slicedBlob의
size를 serialized하고 isomorphic encoded한 값으로 둔다. -
contentRange를, rangeStart, rangeEnd, fullLength를 주어 build a content range를 호출한 결과로 둔다.
-
response의 status를 206으로 설정한다.
-
response의 status message를 `
Partial Content`로 설정한다. -
response의 header list를 « (`
Content-Length`, serializedSlicedLength), (`Content-Type`, type), (`Content-Range`, contentRange) »로 설정한다.
-
-
response를 반환한다.
-
- "
data" -
-
dataURLStruct를, request의 current URL에 대해
data:URL 처리기를 실행한 결과로 둔다. -
dataURLStruct가 failure이면, network error를 반환한다.
-
새로운 response를 반환하는데, 그 status message는 `
OK`이고, header list는 « (`Content-Type`, mimeType) »이며, body 는 dataURLStruct의 body를 body로서 사용한 것이다.
-
- "
file" -
현재로서는 아쉽지만,
file:URLs 는 독자를 위한 연습 문제로 남겨둔다.확신이 서지 않으면, network error를 반환한다.
- HTTP(S) 스킴
-
fetchParams를 주어 HTTP fetch를 실행한 결과를 반환한다.
- "
-
network error를 반환한다.
환경 결정하기는 request request를 입력으로 받는다:
-
request의 reserved client가 null이 아니면, request의 reserved client를 반환한다.
-
null을 반환한다.
4.4. HTTP fetch
HTTP fetch는 fetch params fetchParams와 선택적 boolean makeCORSPreflight (기본값 false)를 입력으로 받아, 다음 단계들을 실행한다:
-
request를 fetchParams의 request로 설정한다.
-
response와 internalResponse를 null로 설정한다.
-
request의 service-workers mode가 "
all"이면:-
requestForServiceWorker를 request의 clone으로 설정한다.
-
requestForServiceWorker의 body가 null이 아니면:
-
transformStream을 새로운
TransformStream객체로 설정한다. -
transformAlgorithm을 chunk을 입력으로 아래 단계로 정의한다:
-
fetchParams가 취소됨이면, 이 단계를 중지한다.
-
chunk가
Uint8Array객체가 아니면 terminate를 fetchParams의 controller에 적용한다. -
그 외의 경우, enqueue를 사용해 chunk를 transformStream에 넣는다. 사용자 에이전트는 chunk를 구현 정의의 적절한 크기로 분할하여 각각 enqueue하거나, chunk들을 구현 정의의 적절한 크기로 결합하여 enqueue할 수 있다.
-
-
Set up을 사용해 transformStream을 transformAlgorithm이 transformAlgorithm이 되도록 설정한다.
-
requestForServiceWorker의 body의 stream을 requestForServiceWorker의 body의 stream을 pipeThrough로 transformStream에 연결한 결과로 설정한다.
-
-
serviceWorkerStartTime을 coarsened shared current time을 fetchParams의 cross-origin isolated capability로 실행한 결과로 설정한다.
-
fetchResponse를 handle fetch에 requestForServiceWorker, fetchParams의 controller 및 fetchParams의 cross-origin isolated capability와 함께 호출한 결과로 설정한다. [HTML] [SW]
-
만약 fetchResponse가 response라면:
-
response를 fetchResponse로 설정한다.
-
fetchParams의 timing info의 final service worker start time을 serviceWorkerStartTime으로 설정한다.
-
fetchParams의 timing info의 service worker timing info를 response의 service worker timing info로 설정한다.
-
request의 body가 null이 아니라면, cancel request의 body를 undefined와 함께 호출한다.
-
internalResponse를 response로, 만약 response가 filtered response가 아니라면 response로; 그렇지 않으면 response의 internal response로 설정한다.
-
다음 조건 중 하나라도 만족하면
-
response의 type이 "
error"인 경우 - request의 redirect mode가
"
manual"이 아니고, response의 type이 "opaqueredirect"인 경우 - request의 redirect mode가
"
follow"가 아니고, response의 URL list에 항목이 두 개 이상 있는 경우
이 경우 network error를 반환한다.
-
-
-
그 밖에, fetchResponse가 service worker timing info라면, fetchParams의 timing info의 service worker timing info를 fetchResponse로 설정한다.
-
-
response가 null이면:
-
makeCORSPreflight이 true이고 다음 조건 중 하나라도 참이면:
-
request의 method에 대해 method cache entry match가 없고, request의 method가 CORS-safelisted method가 아니거나 request의 use-CORS-preflight flag가 설정된 경우
-
request의 header list에서 CORS-unsafe request-header names 중 header-name cache entry match가 없는 항목이 하나 이상 있을 때
그렇다면:
-
preflightResponse를 CORS-프리플라이트 fetch를 request에 대해 실행한 결과로 설정한다.
-
preflightResponse가 network error이면 preflightResponse를 반환한다.
이 단계는 CORS-프리플라이트 캐시를 확인하고 적절한 엔트리가 없으면 CORS-프리플라이트 fetch를 수행하며, 성공 시 캐시를 채운다. CORS-프리플라이트 fetch의 목적은 fetch 리소스가 CORS 프로토콜을 인지하고 있음을 보장하는 데 있다. 캐시는 CORS-프리플라이트 fetch 횟수를 최소화하기 위해 존재한다.
-
-
request의 redirect mode가 "
follow"이면, request의 service-workers mode를 "none"으로 설정한다.네트워크에서 발생한 리다이렉트는(서비스 워커로부터 발생한 것이 아닌 경우) 서비스 워커에 노출되어서는 안 된다.
-
response와 internalResponse를 HTTP-네트워크-또는-캐시 fetch를 fetchParams에 대해 실행한 결과로 설정한다.
-
request의 response tainting가 "
cors"이고 CORS 체크를 request와 response에 대해 실행한 결과가 실패이면, network error를 반환한다.response의 status가 304 또는 407인 경우, 혹은 서비스 워커에서 온 response의 경우 CORS 검사가 적용되지 않으므로, 이 곳에서 적용된다.
-
TAO 체크를 request와 response에 대해 실행한 결과가 실패이면, request의 timing allow failed flag를 설정한다.
-
-
request의 response tainting 또는 response의 type이 "
opaque"이고, cross-origin resource policy check를 request의 origin, request의 client, request의 destination, 그리고 internalResponse로 수행한 결과가 blocked를 반환하면, network error를 반환한다.cross-origin resource policy check는 네트워크에서 오는 응답과 서비스 워커에서 오는 응답 모두에 대해 실행된다. 이는 CORS check와는 다른데, request의 client와 서비스 워커가 서로 다른 임베더 정책을 가질 수 있기 때문이다.
-
internalResponse의 status가 redirect status이면:
-
internalResponse의 status가 303이 아니고 request의 body가 null이 아니며 connection이 HTTP/2를 사용하는 경우, 사용자 에이전트는
RST_STREAM프레임을 전송해도 된다(권장됨).303은 일부 커뮤니티에서 특별한 의미를 가지므로 제외된다.
-
request의 redirect mode에 따라 다음 단계 실행:
- "
error" -
-
response를 network error로 설정한다.
-
- "
manual" -
-
request의 mode가 "
navigate"이면, fetchParams의 controller의 next manual redirect steps를 HTTP-리다이렉트 fetch를 fetchParams와 response로 실행하는 것으로 설정한다. -
그 외의 경우, response를 opaque-redirect filtered response로 설정하고 internal response는 internalResponse로 한다.
-
- "
follow" -
-
response를 HTTP-리다이렉트 fetch를 fetchParams와 response로 실행한 결과로 설정한다.
-
- "
-
-
response를 반환한다. 일반적으로 internalResponse의 body의 stream은 반환 후에도 계속 enqueue된다.
4.5. HTTP-리다이렉트 fetch
HTTP-리다이렉트 fetch는 fetch params fetchParams와 response response를 받아, 다음 단계를 실행한다:
-
request를 fetchParams의 request로 둔다.
-
internalResponse를, response가 filtered response가 아니면 response로, 그렇지 않으면 response의 internal response로 둔다.
-
locationURL를, internalResponse의 location URL을 request의 current URL의 fragment를 주어 얻은 값으로 둔다.
-
locationURL가 null이면, response를 반환한다.
-
locationURL가 failure이면, network error를 반환한다.
-
locationURL의 scheme이 HTTP(S) scheme이 아니면, network error를 반환한다.
-
request의 redirect count가 20이면, network error를 반환한다.
-
request의 redirect count를 1 증가시킨다.
-
request의 mode가 "
cors"이고, locationURL이 credentials를 포함하며, request의 origin이 locationURL의 origin과 same origin이 아니면, network error를 반환한다. -
request의 response tainting이 "
cors"이고 locationURL이 credentials를 포함하면, network error를 반환한다.이는 교차 출처 리소스가 동일 출처 URL로 리디렉트하는 경우를 포착한다.
-
internalResponse의 status가 303이 아니고, request의 body가 null이 아니며, request의 body의 source 가 null이면, network error를 반환한다.
-
다음 중 하나가 참이면
-
internalResponse의 status가 301 또는 302이고 request의 method가 `
POST`인 경우 -
internalResponse의 status가 303이고 request의 method가 `
GET` 또는 `HEAD`가 아닌 경우
그렇다면:
-
각각의 headerName에 대해, request-body-header name 목록에서 delete를 사용하여 request의 header list에서 headerName을 삭제한다.
-
-
request의 current URL의 origin이 locationURL의 origin과 same origin이 아니면, 각각의 headerName에 대해, CORS non-wildcard request-header name 목록에서 delete를 사용하여 request의 header list에서 headerName을 삭제한다.
즉, 초기 요청 이후에 다른 origin이 보이는 순간, `
Authorization` 헤더가 제거된다. -
request의 body가 null이 아니면, safely extracting을 사용하여 request의 body의 source를 추출한 결과의 body로 request의 body를 설정한다.
-
timingInfo를 fetchParams의 timing info로 둔다.
-
timingInfo의 redirect end time과 post-redirect start time을, coarsened shared current time으로 설정하되, 이는 fetchParams의 cross-origin isolated capability를 주어 얻는다.
-
timingInfo의 redirect start time이 0이면, timingInfo의 redirect start time을 timingInfo의 start time으로 설정한다.
-
set request’s referrer policy on redirect를 request와 internalResponse에 대해 호출한다. [REFERRER]
-
recursive를 true로 둔다.
-
request의 redirect mode가 "
manual"이면, 다음을 수행한다: -
fetchParams와 recursive를 주어 main fetch를 실행한 결과를 반환한다.
이는 request의 main fetch를 호출하여 response tainting을 올바르게 설정해야 한다.
4.6. HTTP-네트워크-또는-캐시 fetch
다음이 주어졌을 때 HTTP-network-or-cache fetch를 수행하려면, fetch params fetchParams, 선택적 불리언 isAuthenticationFetch (기본값 false), 및 선택적 불리언 isNewConnectionFetch (기본값 false)를 사용하여 다음 단계를 실행한다:
일부 구현은 HTTP Caching에 따라 부분 콘텐츠 캐싱을 지원할 수 있다. 그러나 브라우저 캐시에서는 널리 지원되지 않는다. [HTTP-CACHING]
-
request를 fetchParams의 request로 하자.
-
httpFetchParams를 null로 하자.
-
httpRequest를 null로 하자.
-
response를 null로 하자.
-
storedResponse를 null로 하자.
-
httpCache를 null로 하자.
-
revalidatingFlag를 unset 상태로 두자.
-
다음 단계를 실행하되, abort when fetchParams가 canceled인 경우 중단한다:
-
만약 request의 traversable for user prompts가 "
no-traversable"이고 request의 redirect mode가 "error"이면, httpFetchParams를 fetchParams로, httpRequest를 request로 설정한다. -
그렇지 않으면:
-
httpRequest를 request의 clone으로 설정한다.
구현체는 request의 body의 stream을 tee하는 것을 피하는 것을 권장한다. 특히 request의 body의 source가 null일 때는 단일 바디만 필요하기 때문이다. 예를 들어, request의 body의 source가 null이면, 리다이렉트와 인증은 페치 실패로 이어질 수 있다.
-
httpFetchParams를 fetchParams의 복사본으로 설정한다.
-
httpFetchParams의 request를 httpRequest로 설정한다.
사용자 프롬프트나 리다이렉트가 가능하면, 사용자 응답이나 리다이렉트 대상이 결정된 후에 요청을 새로운 헤더 집합으로 다시 전송해야 할 수 있다. 그 시점에 원래 요청 바디가 이미 부분적으로 전송되었을 수 있으므로, 우리는 여분의 사본을 확보하기 위해 미리 요청(바디 포함)을 복제해야 한다.
-
-
includeCredentials를 다음 중 하나라도 true이면 true로 하자:
- request의 credentials mode가
"
include"인 경우 - request의 credentials mode가
"
same-origin"이고 request의 response tainting이 "basic"인 경우
그렇지 않으면 false이다.
- request의 credentials mode가
"
-
만약 Cross-Origin-Embedder-Policy가 credentials 허용이 request에 대해 false를 반환하면, includeCredentials를 false로 설정한다.
-
contentLength를 httpRequest의 body의 length로 하되, 만약 httpRequest의 body가 null이면 null로 하자.
-
contentLengthHeaderValue를 null로 하자.
-
만약 httpRequest의 body가 null이고 httpRequest의 method가 `
POST` 또는 `PUT`이면, contentLengthHeaderValue를 `0`으로 설정한다. -
만약 contentLength가 null이 아니면, contentLengthHeaderValue를 contentLength의 직렬화된 및 isomorphic 인코딩된 값으로 설정한다.
-
만약 contentLengthHeaderValue가 null이 아니면, append (`
Content-Length`, contentLengthHeaderValue)를 httpRequest의 header list에 추가한다. -
만약 contentLength가 null이 아니고 httpRequest의 keepalive가 true이면, 다음을 수행한다:
-
inflightKeepaliveBytes를 0으로 하자.
-
group를 httpRequest의 client의 fetch group로 하자.
-
inflightRecords를 group에 있는 fetch records 중에서 request의 keepalive가 true이고 done flag가 unset인 것들의 집합으로 하자.
-
For each fetchRecord에 대해 inflightRecords에 대해 다음을 수행한다:
-
만약 contentLength와 inflightKeepaliveBytes의 합이 64 kibibytes를 초과하면, network error를 반환한다.
위 제한은 바디를 포함하고 environment settings object보다 오래 살아남을 수 있는 요청들이 크기가 제한되고 무기한 허용되지 않도록 보장한다.
-
-
만약 httpRequest의 referrer가 URL이면:
-
referrerValue를 httpRequest의 referrer의 serialized 및 isomorphic 인코딩된 값으로 하자.
-
Append (`
Referer`, referrerValue)을 httpRequest의 header list에 추가한다.
-
-
요청 `
Origin` 헤더 추가를 httpRequest에 대해 수행한다. -
만약 httpRequest의 initiator가 "
prefetch"이면, 구조화된 필드 값을 설정하고 (`Sec-Purpose`, 토큰prefetch)을 httpRequest의 header list에 추가한다. -
만약 httpRequest의 header list가 `
User-Agent`를 포함하지 않는다면, 사용자 에이전트는 다음을 수행해야 한다:-
userAgent를 httpRequest의 client의 환경 기본 `
User-Agent` 값로 하자. -
Append (`
User-Agent`, userAgent)를 httpRequest의 header list에 추가한다.
-
-
만약 httpRequest의 cache mode가 "
default"이고 httpRequest의 header list가 `If-Modified-Since`, `If-None-Match`, `If-Unmodified-Since`, `If-Match` 또는 `If-Range` 중 하나를 포함하면, httpRequest의 cache mode를 "no-store"로 설정한다. -
만약 httpRequest의 cache mode가 "
no-cache"이고, httpRequest의 prevent no-cache cache-control header modification flag가 unset이며, httpRequest의 header list가 `Cache-Control`를 포함하지 않으면, append (`Cache-Control`, `max-age=0`)을 httpRequest의 header list에 추가한다. -
만약 httpRequest의 cache mode가 "
no-store" 또는 "reload"이면, 다음을 수행한다:-
만약 httpRequest의 header list가 `
Pragma`를 포함하지 않으면, append (`Pragma`, `no-cache`)를 httpRequest의 header list에 추가한다. -
만약 httpRequest의 header list가 `
Cache-Control`를 포함하지 않으면, append (`Cache-Control`, `no-cache`)를 httpRequest의 header list에 추가한다.
-
-
만약 httpRequest의 header list가 `
Range`를 포함하면, append (`Accept-Encoding`, `identity`)를 httpRequest의 header list에 추가한다.이는 인코딩된 response의 일부로 content codings를 처리할 때 실패를 방지합니다.
또한, 많은 서버들이 비-identity 인코딩이 허용될 때 잘못해서 `
Range` 헤더를 무시하는 경우가 있습니다. -
HTTP에 따라 httpRequest의 header list를 수정한다. 만약 주어진 header의 name을 httpRequest의 header list가 이미 포함하면, 해당 헤더를 append하지 말라.
이 부분을 더 규범적으로 만들 수 있으면 좋겠다. 현재로서는 `
Accept-Encoding`, `Connection`, `DNT`, 및 `Host` 같은 헤더들은 필요에 따라 추가된다.`
Accept`, `Accept-Charset`, 및 `Accept-Language`는 이 시점에 포함되어서는 안 된다.`
Accept`와 `Accept-Language`는 이미 포함되어 있다 (단,fetch()를 사용하는 경우는 기본적으로 후자가 포함되지 않는다), 그리고 `Accept-Charset`은 바이트 낭비이다. 자세한 내용은 HTTP header layer division를 보라. -
만약 includeCredentials가 true이면, 다음을 수행한다:
-
요청 `
Cookie` 헤더 추가를 httpRequest에 대해 수행한다. -
만약 httpRequest의 header list가 `
Authorization`를 포함하지 않으면, 다음을 수행한다:-
authorizationValue를 null로 둔다.
-
httpRequest에 대한 authentication entry가 존재하고, httpRequest의 use-URL-credentials flag가 설정되어 있지 않거나 httpRequest의 current URL이 credentials를 포함하지 않는 경우, authorizationValue를 authentication entry로 설정한다.
-
그 외의 경우, httpRequest의 current URL이 credentials를 포함하고 isAuthenticationFetch가 true이면, authorizationValue를 httpRequest의 current URL로 설정하고, `
Authorization` 값으로 변환한다. -
authorizationValue가 null이 아니면, append (`
Authorization`, authorizationValue)를 httpRequest의 header list에 추가한다.
-
-
-
만약 proxy-authentication entry가 있다면, 적절히 사용한다.
이는 의도적으로 httpRequest의 credentials mode에 의존하지 않는다.
-
httpCache를 HTTP 캐시 파티션 결정의 결과로 설정한다, 주어진 httpRequest를 사용하여.
-
만약 httpCache가 null이면, httpRequest의 cache mode를 "
no-store"로 설정한다. -
만약 httpRequest의 cache mode가 "
no-store"도 아니고 "reload"도 아니면, 다음을 수행한다:-
storedResponse를 httpCache에서 응답을 선택한 결과로 설정한다. 이 선택은 필요할 경우 검증을 요구할 수 있으며, HTTP Caching의 "Constructing Responses from Caches" 장을 따른다. [HTTP-CACHING]
HTTP에 의해 `
Vary` 헤더를 고려한다. -
만약 storedResponse가 non-null이면, 다음을 수행한다:
-
만약 cache mode가 "
default"이고, storedResponse가 stale-while-revalidate response이며 httpRequest의 client가 non-null이면:-
response를 storedResponse로 설정한다.
-
response의 cache state를 "
local"로 설정한다. -
revalidateRequest를 request의 clone으로 하자.
-
revalidateRequest의 cache mode를 "
no-cache"로 설정한다. -
revalidateRequest의 prevent no-cache cache-control header modification flag을 설정한다.
-
revalidateRequest의 service-workers mode를 "
none"로 설정한다. -
In parallel로, 새로운 fetch params을 사용하여 main fetch를 실행한다. 그 새 fetch params의 request는 revalidateRequest이다.
이 fetch는 단지 httpCache의 상태를 갱신하기 위한 것이며, 그 응답은 또 다른 캐시 접근까지 사용되지 않는다. 오래된 응답은 현재 요청에 대한 응답으로 사용된다. 이 fetch는 클라이언트 문맥에서 발행되므로 클라이언트가 사라지면 요청은 종료된다.
-
-
그렇지 않으면:
-
만약 storedResponse가 stale response이면, revalidatingFlag를 설정한다.
-
만약 revalidatingFlag가 설정되어 있고 httpRequest의 cache mode가 "
force-cache"도 아니고 "only-if-cached"도 아니면:-
만약 storedResponse의 header list가 `
ETag`를 포함하면, append (`If-None-Match`, `ETag`의 value)를 httpRequest의 header list에 추가한다. -
만약 storedResponse의 header list가 `
Last-Modified`를 포함하면, append (`If-Modified-Since`, `Last-Modified`의 value)를 httpRequest의 header list에 추가한다.
또한 HTTP Caching의 "Sending a Validation Request" 장을 보라. [HTTP-CACHING]
-
-
그렇지 않으면 response를 storedResponse로 설정하고, response의 cache state를 "
local"로 설정한다.
-
-
-
-
-
If aborted이면, fetchParams에 대한 적절한 network error를 반환한다.
-
만약 response가 null이면, 다음을 수행한다:
-
만약 httpRequest의 cache mode가 "
only-if-cached"이면, network error를 반환한다. -
forwardResponse를 HTTP-network fetch를 httpFetchParams, includeCredentials, 및 isNewConnectionFetch로 실행한 결과로 하자.
-
만약 httpRequest의 method가 unsafe이고, forwardResponse의 status가 200에서 399 사이(포함)이면, 적절한 httpCache의 저장된 응답들을 무효화(invalidate)하고, storedResponse를 null로 설정한다. 이는 HTTP Caching의 "Invalidating Stored Responses" 장을 따른다. [HTTP-CACHING]
-
만약 revalidatingFlag가 설정되어 있고 forwardResponse의 status가 304이면:
-
forwardResponse의 header list를 사용하여 storedResponse의 header list를 갱신한다. 이는 HTTP Caching의 "Freshening Stored Responses upon Validation" 장을 따른다. [HTTP-CACHING]
이는 캐시에 저장된 응답도 업데이트한다.
-
response를 storedResponse로 설정한다.
-
response의 cache state를 "
validated"로 설정한다.
-
-
만약 response가 null이면, 다음을 수행한다:
-
response를 forwardResponse로 설정한다.
-
httpRequest와 forwardResponse를 httpCache에 저장한다. 이는 HTTP Caching의 "Storing Responses in Caches" 장을 따른다. [HTTP-CACHING]
만약 forwardResponse가 network error이면, 이는 사실상 네트워크 오류를 캐시하는 것으로, 때때로 "negative caching"으로 알려진 동작을 한다.
관련된 body info는 응답과 함께 캐시에 저장된다.
-
-
-
만약 httpRequest의 header list가 `
Range`를 포함하면, response의 range-requested flag를 설정한다. -
response의 request-includes-credentials를 includeCredentials로 설정한다.
-
만약 response의 status가 401이고, httpRequest의 response tainting이 "
cors"가 아니며, includeCredentials가 true이고, request의 traversable for user prompts가 traversable navigable이면:-
테스트 필요: 여러 `
WWW-Authenticate` 헤더, 누락, 파싱 문제. -
만약 request의 body가 non-null이면, 다음을 수행한다:
-
만약 request의 use-URL-credentials flag가 unset이거나 isAuthenticationFetch가 true이면, 다음을 수행한다:
-
만약 fetchParams가 canceled이면, fetchParams에 대한 appropriate network error를 반환한다.
-
username과 password를 엔드 유저에게 request의 traversable for user prompts에서 각각 물어본 결과로 설정하자.
-
Set the username를 호출하여 request의 current URL과 username을 설정한다.
-
Set the password를 호출하여 request의 current URL과 password를 설정한다.
-
-
response를 HTTP-network-or-cache fetch를 fetchParams와 true를 주어 실행한 결과로 설정한다.
-
-
만약 response의 status가 407이면, 다음을 수행한다:
-
만약 request의 traversable for user prompts가 "
no-traversable"이면, network error를 반환한다. -
테스트 필요: 여러 `
Proxy-Authenticate` 헤더, 누락, 파싱 문제. -
만약 fetchParams가 canceled이면, fetchParams에 대한 appropriate network error를 반환한다.
-
request의 traversable for user prompts에서 적절히 엔드 유저를 프롬프트하고, 결과를 proxy-authentication entry로 저장한다. [HTTP]
프록시 인증에 관한 나머지 세부사항은 HTTP에서 정의된다.
-
response를 HTTP-network-or-cache fetch를 fetchParams로 실행한 결과로 설정한다.
-
-
다음이 모두 참이면
-
response의 status가 421인 경우
-
isNewConnectionFetch가 false인 경우
-
request의 body가 null이거나, 또는 request의 body가 non-null이고 request의 source가 non-null인 경우
그러면:
-
만약 fetchParams가 canceled이면, fetchParams에 대한 appropriate network error를 반환한다.
-
response를 HTTP-network-or-cache fetch를 fetchParams, isAuthenticationFetch, 및 true로 실행한 결과로 설정한다.
-
-
만약 isAuthenticationFetch가 true이면, request와 주어진 realm에 대한 authentication entry를 생성한다.
-
response를 반환한다. 일반적으로 response의 body의 stream은 반환 후에도 계속해서 큐에 들어온다.
4.7. HTTP-네트워크 fetch
HTTP-네트워크 fetch는 fetch params fetchParams, 선택적 boolean includeCredentials (기본값 false), 선택적 boolean forceNewConnection (기본값 false)를 입력으로 받아, 다음 단계를 실행한다:
-
request를 fetchParams의 request로 설정한다.
-
response를 null로 설정한다.
-
timingInfo를 fetchParams의 timing info로 설정한다.
-
networkPartitionKey를 네트워크 파티션 키 결정하기를 request에 대해 실행한 결과로 설정한다.
-
newConnection을 forceNewConnection이 true이면 "
yes", 아니면 "no"로 설정한다. -
request의 mode에 따라 분기한다:
- "
websocket" -
connection을 WebSocket 연결 획득을 request의 current URL에 대해 실행한 결과로 설정한다.
- "
webtransport" -
connection을 WebTransport 연결을 획득한 결과로 설정하며, 이때 networkPartitionKey와 request를 전달한다.
- 그 외의 경우
-
connection을 연결 획득을 networkPartitionKey, request의 current URL, includeCredentials, newConnection을 사용하여 실행한 결과로 설정한다.
- "
-
다음 단계를 실행하되, abort when fetchParams가 취소됨이면 중단한다:
-
connection이 실패이면 network error를 반환한다.
-
timingInfo의 최종 연결 타이밍 정보를 연결 타이밍 정보 클램프 및 조정하기를 connection의 타이밍 정보, timingInfo의 리다이렉트 후 시작 시간, fetchParams의 cross-origin 격리 기능으로 실행한 결과로 설정한다.
-
connection이 HTTP/1.x 연결이고 request의 body가 null이 아니며 request의 body의 source가 null이면 network error를 반환한다.
-
timingInfo의 최종 네트워크 요청 시작 시간을 공유 현재 시간(조정됨)을 fetchParams의 cross-origin 격리 기능으로 실행한 결과로 설정한다.
-
response를 connection에서 request를 사용하여 HTTP 요청을 만들어 얻은 결과로 설정하되, 다음 주의사항을 따른다:
-
HTTP의 관련 요구사항을 따른다. [HTTP] [HTTP-CACHING]
-
request의 body가 null이 아니고 request의 body의 source가 null이면, 사용자 에이전트는 최대 64키비바이트의 버퍼를 가지고 request의 body의 일부를 그 버퍼에 저장할 수 있다. 만약 그 버퍼 크기를 초과해서 request의 body를 읽어야 하고, 요청을 재전송해야 한다면, 대신 network error를 반환한다.
-
다음이 참일 동안:
-
timingInfo의 최종 네트워크 응답 시작 시간을 공유 현재 시간(조정됨)을 fetchParams의 cross-origin 격리 기능으로 실행한 결과로 설정하되, 사용자 에이전트의 HTTP 파서가 응답의 첫 바이트(예: HTTP/2의 프레임 헤더 바이트 또는 HTTP/1.x의 응답 상태 줄)를 수신한 직후에 실행한다.
-
모든 HTTP 응답 헤더가 전송될 때까지 대기한다.
-
status를 HTTP 응답의 상태 코드로 설정한다.
-
status가 100~199 범위에 포함되면:
-
timingInfo의 첫 임시 네트워크 응답 시작 시간이 0이면, timingInfo의 첫 임시 네트워크 응답 시작 시간을 timingInfo의 최종 네트워크 응답 시작 시간으로 설정한다.
-
status가 103이고 fetchParams의 process early hints response가 null이 아니면, fetch task 큐잉을 실행하여 fetchParams의 process early hints response를 response와 함께 실행한다.
이러한 종류의 HTTP 응답은 결국 "최종" HTTP 응답으로 이어진다.
-
-
Fetch와 HTTP의 정확한 계층화는 아직 정리될 필요가 있으며, 여기서 response는 response와 HTTP 응답을 모두 의미한다.
HTTP 요청으로 인해 TLS 클라이언트 인증서 다이얼로그가 발생하면:
-
request의 프롬프트를 위한 탐색 가능가 탐색 가능 객체라면, 그 대화 상자를 request의 프롬프트를 위한 탐색 가능에서 사용할 수 있도록 한다.
-
그렇지 않으면 network error를 반환한다.
request의 body body를 전송하려면 다음 단계를 실행한다:
-
body가 null이고 fetchParams의 process request end-of-body가 null이 아니면, fetch task 큐잉을 fetchParams의 process request end-of-body와 fetchParams의 task destination으로 실행한다.
-
그렇지 않고 body가 null이 아니면:
-
processBodyChunk를 bytes를 입력으로 다음 단계로 정의한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
병렬로 bytes를 전송한다.
-
fetchParams의 process request body chunk length가 null이 아니면, fetchParams의 process request body chunk length를 bytes의 길이로 실행한다.
-
-
processEndOfBody를 다음 단계로 정의한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
fetchParams의 process request end-of-body가 null이 아니면, fetchParams의 process request end-of-body를 실행한다.
-
-
processBodyError를 e를 입력으로 다음 단계로 정의한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
e가 "
AbortError"DOMException이면 컨트롤러 중단을 fetchParams의 controller에 실행한다. -
그 외에는 컨트롤러 종료를 fetchParams의 controller에 실행한다.
-
-
body 점진적 읽기를 request의 body, processBodyChunk, processEndOfBody, processBodyError, fetchParams의 task destination으로 실행한다.
-
-
-
-
-
connection이 HTTP/2를 사용하면
RST_STREAM프레임을 전송한다. -
fetchParams에 대한 적절한 네트워크 오류를 반환한다.
-
-
buffer를 빈 바이트 시퀀스로 설정한다.
이는 사용자 에이전트의 네트워크 계층 내부 버퍼를 의미한다.
-
stream을 새로운
ReadableStream으로 설정한다. -
pullAlgorithm을 다음 단계로 정의한다:
-
promise를 새로운 promise로 설정한다.
-
다음 단계를 병렬로 실행한다:
-
buffer의 크기가 사용자 에이전트가 선택한 하한보다 작고 진행 중인 fetch가 중단됨이라면, fetch 재개를 실행한다.
-
buffer가 비어 있지 않을 때까지 대기한다.
-
fetch task 큐잉을 실행하여 다음 단계를 fetchParams의 task destination으로 실행한다.
-
bytes에서 pull을 buffer에서 stream으로 실행한다.
-
stream이 errored 상태이면 컨트롤러 종료를 fetchParams의 controller에 실행한다.
-
resolve promise를 undefined로 실행한다.
-
-
-
promise를 반환한다.
-
-
cancelAlgorithm을 reason을 입력받아 컨트롤러 중단을 fetchParams의 controller에 reason과 함께 실행하는 알고리즘으로 설정한다.
-
byte 읽기 지원으로 stream 설정을 stream에 대해 실행하되, pullAlgorithm을 pullAlgorithm으로, cancelAlgorithm을 cancelAlgorithm으로 설정한다.
-
includeCredentials가 true이면, 사용자 에이전트는 응답 Set-Cookie 헤더 파싱 및 저장을 request와 response로 실행해야 한다.
-
다음 단계를 병렬로 실행한다:
-
다음 단계를 abort when fetchParams가 취소됨이면 중단한다:
-
다음이 참일 동안:
-
response의 메시지 body에서 하나 이상의 바이트가 전송되었다면:
-
bytes를 전송된 바이트로 설정한다.
-
codings를 헤더 리스트 값 추출을 `
Content-Encoding`과 response의 header list에 대해 실행한 결과로 설정한다. -
filteredCoding을 "
@unknown"으로 설정한다. -
codings가 null 또는 실패이면 filteredCoding을 빈 문자열로 설정한다.
-
그 외에 codings의 size가 1보다 크면 filteredCoding을 "
multiple"로 설정한다. -
그 외에 codings[0]이 빈 문자열이거나, 사용자 에이전트가 지원하고, 바이트 대소문자 구분 없이 HTTP Content Coding Registry에 포함된 엔트리와 일치하면, filteredCoding을 바이트 소문자화 codings[0]으로 설정한다. [IANA-HTTP-PARAMS]
-
response의 body info의 content encoding을 filteredCoding으로 설정한다.
-
response의 body info의 encoded size를 bytes의 길이만큼 증가시킨다.
-
bytes를 콘텐츠 코딩 처리를 codings과 bytes로 실행한 결과로 설정한다.
이로 인해 `
Content-Length` 헤더의 신뢰성이 저하될 수 있다. -
response의 body info의 decoded size를 bytes의 길이만큼 증가시킨다.
-
bytes가 실패이면 컨트롤러 종료를 fetchParams의 controller에 실행한다.
-
bytes를 buffer에 추가한다.
-
buffer의 크기가 사용자 에이전트가 선택한 상한보다 크면, 진행 중인 fetch를 중단하도록 사용자 에이전트에 요청한다.
-
-
그 외에 response의 메시지 body 바이트 전송이 정상적으로 완료되고 stream이 readable이면, stream 닫기를 stream에 실행하고 병렬 실행 단계를 중단한다.
-
-
-
-
fetchParams가 aborted이면:
-
response의 aborted flag를 설정한다.
-
stream이 readable이면, stream error를 stream에 실행하고, 중단 이유 역직렬화를 fetchParams의 controller의 serialized abort reason과 구현 정의 realm으로 실행한 결과로 실행한다.
-
-
그 외에 stream이 readable이면, stream error를 stream에
TypeError로 실행한다. -
connection이 HTTP/2를 사용하면
RST_STREAM프레임을 전송한다. -
그 외에는, 다음 fetch에 성능 저하가 없다면 사용자 에이전트가 connection을 닫아야 한다.
예를 들어, 재사용 가능한 연결에서 몇 바이트만 남았다는 것을 알고 있다면 닫지 않는 것이 더 좋을 수 있다. 이 경우 연결을 닫고 다음 fetch에서 핸드셰이크를 다시 하는 것이 오히려 더 나쁠 수 있다.
-
이 단계는 병렬로 실행되며, 이 시점에서는 response의 body가 관련 있는지 알 수 없다(response가 리다이렉트일 수 있음).
-
-
response를 반환한다. 일반적으로 response의 body의 stream은 반환 후에도 계속 enqueue된다.
4.8. CORS-프리플라이트 fetch
이 알고리즘은 CORS 프로토콜을 이해하는지 사용자 에이전트가 확인하는 구현이다. 이른바 CORS-프리플라이트 요청이다. 성공하면 CORS-프리플라이트 캐시를 채워 이런 fetch의 수를 최소화한다.
CORS-preflight fetch를 수행하려면, request request가 주어졌을 때, 다음 절차를 실행한다:
-
preflight를 새 request로 두되, method는 `
OPTIONS`이고, URL list는 clone한 request의 URL list, initiator는 request의 initiator, destination는 request의 destination, origin은 request의 origin, referrer는 request의 referrer, referrer policy는 request의 referrer policy, mode는 "cors", 그리고 response tainting은 "cors"로 한다.preflight의 service-workers mode는 중요하지 않다. 본 알고리즘은 HTTP-network-or-cache fetch를 사용하며, HTTP fetch는 사용하지 않는다.
-
Append (`
Accept`, `*/*`)를 preflight의 header list에 추가한다. -
Append (`
Access-Control-Request-Method`, request의 method)를 preflight의 header list에 추가한다. -
headers를, request의 header list로부터 CORS-unsafe request-header names로 둔다.
-
headers가 비어있지 않다면:
-
value를 headers 내 항목들을 `
,`로 구분하여 연결한 값으로 한다. -
Append (`
Access-Control-Request-Headers`, value)를 preflight의 header list에 추가한다.
이 부분은 의도적으로 combine을 사용하지 않는다. 0x2C 뒤에 0x20이 오는 방식이 구현에 없기 때문이다.
-
-
response를, HTTP-network-or-cache fetch를 새 fetch params로 수행하되, request는 preflight로 한다.
-
request와 response에 대하여 CORS check가 성공하고, response의 status가 ok status라면:
CORS check는 preflight가 아니라 request에 대해 실행하며, 올바른 credentials mode가 사용되도록 보장한다.
-
methods를, extracting header list values를 `
Access-Control-Allow-Methods`와 response의 header list로 수행한 결과로 한다. -
headerNames를, extracting header list values를 `
Access-Control-Allow-Headers`와 response의 header list로 수행한 결과로 한다. -
methods나 headerNames가 failure라면, network error를 반환한다.
-
methods가 null이고 request의 use-CORS-preflight flag 가 설정되어 있다면, methods를 request의 method 하나만 포함하는 새 리스트로 한다.
CORS-preflight fetch가 request의 use-CORS-preflight flag로 인해 발생했다면, 캐시됨을 보장한다.
-
request의 method가 methods에 없고, request의 method가 CORS-safelisted method가 아니며, request의 credentials mode가 "
include"이거나 methods에 `*`가 없다면, network error를 반환한다. -
request의 header list의 이름 중 하나가 CORS non-wildcard request-header name이고, byte-case-insensitive 비교 시 headerNames의 어느 항목과도 일치하지 않으면, network error를 반환한다.
-
각 unsafeName에 대하여, CORS-unsafe request-header names 중 request의 header list에서, unsafeName이 headerNames의 항목과 byte-case-insensitive 비교로 일치하지 않고, request의 credentials mode가 "
include"이거나 headerNames에 `*`가 없다면, network error를 반환한다. -
max-age를, extracting header list values를 `
Access-Control-Max-Age`와 response의 header list로 수행한 결과로 한다. -
max-age가 failure 또는 null이라면, max-age를 5로 설정한다.
-
max-age가 max-age의 한도보다 크면, max-age를 그 한도 값으로 맞춘다.
-
UA가 cache를 제공하지 않으면 response를 반환한다.
-
methods의 각 method에서, method cache entry match가 request 기준으로 존재하면, 해당 엔트리의 max-age를 max-age로 설정한다.
-
methods의 각 method에서, method cache entry match가 request 기준으로 없으면, 새 캐시 엔트리 생성을 request, max-age, method, null로 한다.
-
headerNames의 각 headerName에서, header-name cache entry match가 request 기준으로 존재하면, 해당 엔트리의 max-age를 max-age로 설정한다.
-
headerNames의 각 headerName에서, header-name cache entry match가 request 기준으로 없으면, 새 캐시 엔트리 생성을 request, max-age, null, headerName으로 한다.
-
response를 반환한다.
-
-
그 외에는 network error를 반환한다.
4.9. CORS-프리플라이트 캐시
유저 에이전트는 CORS-preflight 캐시를 가진다. CORS-preflight 캐시는 리스트 형태의 캐시 엔트리들로 구성된다.
캐시 엔트리는 다음으로 구성된다:
- 키 (a 네트워크 파티션 키)
- 바이트 직렬화 origin (바이트 시퀀스)
- URL (URL)
- max-age (초 단위 숫자)
- credentials (불리언)
- 메서드 (null, `
*`, 또는 메서드) - 헤더 이름 (null, `
*`, 또는 헤더 이름)
캐시 엔트리는 저장된 이후, max-age 필드의 초만큼 지나면 삭제되어야 한다. 또한 캐시 엔트리는 그 전에도 삭제될 수 있다.
새 캐시 엔트리 생성을 하려면, request, max-age, method, headerName이 주어질 때, 다음 단계를 진행한다:
-
entry를 캐시 엔트리로 생성하고, 다음과 같이 초기화한다:
- 키
- 바이트 직렬화 origin
- URL
-
request의 current URL
- max-age
-
max-age
- credentials
-
request의 credentials mode가 "
include"이면 true, 아니면 false - 메서드
-
method
- 헤더 이름
-
headerName
-
entry를 사용자 에이전트의 CORS-preflight 캐시에 추가한다.
캐시 엔트리 삭제 를 하려면 request가 주어졌을 때, 사용자 에이전트의 CORS-preflight 캐시에 들어있는 캐시 엔트리 중에서, key가 request로 네트워크 파티션 키 결정의 결과와 같고, byte-serialized origin이 request origin을 바이트 직렬화한 결과와 같으며, URL이 request의 current URL과 같은 캐시 엔트리를 제거한다.
캐시 엔트리 entry가 request와 다음 조건을 만족하면, 캐시 엔트리 일치가 존재하는 것으로 한다: entry의 키가 request로 네트워크 파티션 키 결정의 결과와 같고, entry의 바이트 직렬화 origin이 request origin을 바이트 직렬화한 결과와 같으며, entry의 URL이 request의 current URL과 같고, 그리고 다음 중 하나를 만족할 때
- entry의 credentials가 true인 경우
- entry의 credentials가 false이고 request의
credentials mode가 "
include"가 아닌 경우
참으로 한다.
method와 request를 쓸 때,
사용자 에이전트의 CORS-preflight 캐시 내에
method와 캐시
엔트리 일치를 만족하고,
그 메서드가
method 또는 `*`인 캐시 엔트리가 있으면,
메서드 캐시 엔트리
일치가 존재하는 것으로 한다.
headerName과 request를 쓸 때, 사용자 에이전트의 CORS-preflight 캐시 내에, 캐시 엔트리 일치와 request를 만족하고, 다음 중 하나를 만족하는 캐시 엔트리가 있으면, 헤더 이름 캐시 엔트리 일치가 존재하는 것으로 한다:
- 그 헤더 이름이 byte-case-insensitive하게 headerName과 일치하는 경우
- 그 헤더
이름이 `
*`이고, headerName이 CORS non-wildcard request-header name이 아닌 경우
참으로 한다.
4.10. CORS 체크
CORS 체크는 request와 response에 대해 다음 단계를 실행한다:
-
origin을 가져오기로 `
Access-Control-Allow-Origin`을 response의 header list에서 가져온 값으로 설정한다. -
origin이 null이면 실패를 반환한다.
null은 `
null`와 다르다. -
request의 credentials mode가 "
include"가 아니고 origin이 `*`이면 성공을 반환한다. -
요청 origin 바이트 직렬화를 request로 실행한 결과가 origin과 다르면 실패를 반환한다.
-
request의 credentials mode가 "
include"가 아니면 성공을 반환한다. -
credentials를 가져오기로 `
Access-Control-Allow-Credentials`를 response의 header list에서 가져온 값으로 설정한다. -
credentials가 `
true`이면 성공을 반환한다. -
실패를 반환한다.
4.11. TAO 체크
TAO check를 request와 response에 대해 수행하려면, 다음 단계를 실행한다:
-
request의 timing allow failed flag가 설정되어 있으면, 실패를 반환한다.
-
values를, `
Timing-Allow-Origin` 헤더를 가져와 디코딩 및 분할한 response의 header list에 대한 결과로 한다. -
values가 "
*"를 포함하면, 성공을 반환한다. -
values가, request origin을 직렬화한 값을 request로 얻어 포함하면, 성공을 반환한다.
-
request의 mode가 "
navigate"이고 request의 current URL의 origin이 request의 origin과 동일 출처가 아니면, 실패를 반환한다.이 단계는 nested navigable의 네비게이션을 위해 필요하다. 이 경우 request의 origin은 컨테이너 문서의 origin이 되고, TAO check는 실패를 반환한다. 네비게이션 타이밍은 TAO check 결과를 검증하지 않기 때문에, nested document에서는 전체 타이밍 정보를 볼 수 있지만, 컨테이너 문서에서는 볼 수 없다.
-
request의 response tainting이 "
basic"이면 성공을 반환한다. -
실패를 반환한다.
4.12. 지연 fetch
지연 페칭(deferred fetching)은 호출자가 fetch가 가능한 한 마지막 순간에 호출되도록 요청할 수 있게 해준다. 즉, fetch group이 종료되거나, 타임아웃이 지난 뒤에 호출된다.
지연 fetch 작업
소스(deferred fetch
task source)는, 지연 fetch의 결과를 업데이트하기 위해 사용하는 작업
소스(task
source)이다. 사용자 에이전트는 이 작업
소스에 속한 작업을 다른 작업
소스보다, 특히 DOM 조작 작업 소스와 같이 스크립트가 실행될 수 있는 작업 소스보다 우선 처리해야 한다. 이것은
스크립트가 fetch 결과에 의존하기 전에 최신 fetchLater() 호출의 상태가 반영되도록 하기 위함이다.
지연 fetch 대기열에 넣기를 수행하려면,
request
request,
null이나
DOMHighResTimeStamp
인 activateAfter,
인자를 받지 않는 알고리즘 onActivatedWithoutTermination이 주어진다:
-
클라이언트로부터 request를 채운다 (request 전달).
-
request의 service-workers 모드를 "
none"으로 설정한다. -
request의 keepalive를 true로 설정한다.
-
deferredRecord를 새 deferred fetch record로 생성하고, request는 request, notify invoked는 onActivatedWithoutTermination으로 한다.
-
Append deferredRecord를, request의 client의 fetch group의 지연 fetch 기록 리스트에 추가한다.
-
activateAfter가 null이 아니면, 다음 단계를 병렬로 실행:
-
사용자 에이전트는 다음 조건 중 하나가 만족될 때까지 기다린다:
-
activateAfter 밀리초가 지났을 때
-
브라우저가 백그라운드로 전환된다거나 request의 client의 전역 객체(global object)가
Window객체로 연결된 document가 오랜 시간 동안 "hidden" visibility state라면, 스크립트 실행 기회를 곧 상실할 것으로 판단된 경우
-
-
지연 fetch 처리 (deferredRecord).
-
-
deferredRecord를 반환한다.
요청 총 길이(total request length)를 계산하려면 request request가 주어졌을 때:
지연 fetch 처리를 fetch group fetchGroup에 대해 실행하려면:
-
각 지연 fetch 기록 deferredRecord를, fetchGroup의 지연 fetch 기록에서 순회하며, 지연 fetch 처리를 deferredRecord에 대해 수행한다.
지연 fetch 처리 deferredRecord에 대해:
-
deferredRecord의 invoke state가 "
pending"이 아니면 return. -
deferredRecord의 invoke state를 "
sent"로 설정한다. -
글로벌 태스크를 큐에 추가한다. 대상은 지연 fetch 작업 소스이고, deferredRecord의 request의 client의 global object에 deferredRecord의 notify invoked 를 실행한다.
4.12.1. 지연 fetch 할당량
이 절은 비규범적이다.
지연 fetch 할당량은 최상위 traversable(즉 "탭") 단위로 할당되며, 총 640키비바이트이다. 최상위 문서와 동일 출처의 직접 중첩 문서들이 이 할당량을 사용하여 지연 fetch를 큐잉하거나, 일부를 교차 출처 중첩 문서로 위임할 수 있다(permissions policy 사용).
기본적으로 640키비바이트 중 128키비바이트가 교차 출처 중첩 문서로 할당량 위임에 쓰이며, 각 중첩 문서는 8키비바이트를 예약한다.
최상위 문서 및 그 중첩 문서는 permissions policy를 통해 교차 출처 자식 문서에 얼마나 할당량을 위임할지 제어할 수
있다. 기본적으로
"deferred-fetch-minimal"
정책은 모든 origin에 대해 활성화되어 있고,
"deferred-fetch"
정책은 최상위 문서의 origin에 대해서만 활성화되어 있다. 특정 origin 또는 중첩 문서에 대해
"deferred-fetch"
정책을 relax하면 해당 중첩 문서에 64키비바이트를 할당할 수 있다. 반대로
"deferred-fetch-minimal"
정책을 origin 또는 중첩 문서에 제한하면, 해당 문서가 기본적으로 받을 8키비바이트 예약이 방지된다. 그리고 최상위 문서 자체에 대해
"deferred-fetch-minimal"
정책을 비활성화하면, 위임된 128키비바이트 전체 할당량이 640키비바이트 메인 풀로 다시 합쳐진다.
어떤 문서에 대해 할당된 전체 할당량 중, 동일 리포팅 origin(즉 request의 URL의 origin)에 대해 동시에 사용할 수 있는 것은 64키비바이트까지이다. 이는 특정 서드파티 라이브러리가 실제로 보낼 데이터가 없이 할당량만 선점하는 상황을 방지한다.
아래의 fetchLater() 호출은 요청 자체가 한 보고 오리진에 할당된 64키비바이트
할당량을 초과하므로 예외가 발생합니다. 요청의 크기에는 URL과 body, header list, referrer가 모두 포함됩니다.
fetchLater(a_72_kb_url);
fetchLater("https://origin.example.com", {headers: headers_exceeding_64kb});
fetchLater(a_32_kb_url, {headers: headers_exceeding_32kb});
fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
fetchLater(a_62_kb_url /* with a 3kb referrer */);
다음 시퀀스에서 처음 두 요청은 성공하지만, 세 번째는 예외가 발생합니다. 처음 두 번은 전체 640키비바이트 할당량을 초과하지 않지만, 세 번째 요청은
https://a.example.com에 대한 보고 오리진 할당량을 초과하기 때문에 예외가 발생합니다.
fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://a.example.com");
동일 출처 중첩 문서는 부모의 할당량을 공유합니다. 하지만 교차 출처 또는 교차 agent iframe은 기본적으로 8kb만 할당받습니다. 따라서 아래 예에서 처음 세 번 호출은 성공하고, 마지막은 예외가 발생합니다.
// In main page
fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
// In same-origin nested document
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
// In cross-origin nested document at https://fratop.example.com
fetchLater("https://a.example.com", {body: a_5kb_body});
fetchLater("https://a.example.com", {body: a_12kb_body});
이전 예에서 예외가 발생하지 않게 하려면, 최상위 문서가 https://fratop.example.com에 일부 할당량을 위임할 수 있습니다. 예를 들어 다음 헤더를
제공하면 됩니다:
Permissions-Policy: deferred-fetch=(self "https://fratop.example.com")
각 중첩 문서는 자체 할당량을 예약합니다. 따라서 다음 예는 각 프레임이 8키비바이트를 예약하므로 정상적으로 동작합니다:
// In cross-origin nested document at https://fratop.example.com/frame-1
fetchLater("https://a.example.com", {body: a_6kb_body});
// In cross-origin nested document at https://fratop.example.com/frame-2
fetchLater("https://a.example.com", {body: a_6kb_body});
아래 트리는 트리 내 다른 중첩 문서에 할당량이 어떻게 분배되는지 보여줍니다:
-
https://top.example.com(permissions policy:Permissions-policy: deferred-fetch=(self "https://ok.example.com"))-
https://top.example.com/frame: 최상위 traversable과 동일 출처이므로 할당량을 공유함.-
https://x.example.com: 8키비바이트 할당.
-
-
https://x.example.com: 8키비바이트 할당.-
https://top.example.com: 0. 최상위 traversable과 동일 출처이지만, 교차 출처 중간 단계가 있으므로 자동으로 할당량을 공유하지 않는다.
-
-
https://ok.example.com/good: "deferred-fetch" 정책으로 64키비바이트 할당.-
https://x.example.com: 할당량 없음. 오직 최상위 traversable과 동일 출처 문서만 "deferred-fetch-minimal" 정책으로 8키비바이트를 할당할 수 있다.
-
-
https://ok.example.com/redirect에서https://x.example.com으로 네비게이션: 할당량 없음.https://ok.example.com에 예약된 64키비바이트는https://x.example.com에 사용할 수 없다. -
https://ok.example.com/back에서https://top.example.com으로 네비게이션: 동일 출처이므로 최상위 traversable과 할당량을 공유함.
-
위 예에서, 최상위 traversable과 동일 출처 자손들은 384키비바이트 할당량을 공유합니다. 그 값 계산은 다음과 같습니다:
-
640키비바이트가 최상위 traversable에 처음 할당됩니다.
-
128키비바이트가 "
deferred-fetch-minimal" 정책에 예약됩니다. -
64키비바이트가
https://ok.example/good네비게이션에 예약됩니다. -
64키비바이트가
https://ok.example/redirect네비게이션에 예약되고, 네비게이션하면 잃게 됩니다. https://ok.example.com/back는 64키비바이트를 예약하지 않았습니다. 최상위 traversable의 오리진으로 돌아갔기 때문입니다.-
640 − 128 − 64 − 64 = 384키비바이트.
이 명세는 "deferred-fetch" 문자열로 식별되는 정책 제어 기능을 정의합니다. 그 기본 허용 리스트는 "self"입니다.
이 명세는 "deferred-fetch-minimal"
문자열로 식별되는 정책 제어 기능을 정의합니다. 그 기본 허용 리스트는 "*"입니다.
deferred-fetch-minimal에 예약된 할당량은
128키비바이트입니다.
각 navigable container는 예약된 지연 fetch 할당량을 갖습니다. 가능한 값은 최소 할당량(8키비바이트)과 일반 할당량(0 또는 64키비바이트)입니다. 별다른 언급이 없으면 0입니다.
사용 가능 지연 fetch 할당량을 얻으려면, document document와 origin-또는-null origin을 받아:
-
controlDocument를 document의 지연 fetch 제어 문서로 둔다.
-
navigable을 controlDocument의 node navigable로 둔다.
-
isTopLevel을 controlDocument의 node navigable이 최상위 traversable이면 true, 아니면 false로 둔다.
-
deferredFetchAllowed를 controlDocument가 사용 허가됨이고, 정책 제어 기능 "
deferred-fetch"도 허가됨이면 true, 아니면 false. -
deferredFetchMinimalAllowed를 controlDocument가 사용 허가됨이고, 정책 제어 기능 "
deferred-fetch-minimal"도 허가됨이면 true, 아니면 false. -
quota를 다음과 같이 결정된 첫 번째 일치 조건의 결과로 둔다:
- isTopLevel이 true이고 deferredFetchAllowed가 false임
- 0
- isTopLevel이 true이고 deferredFetchMinimalAllowed가 false임
-
640키비바이트
640kb면 누구에게나 충분한 용량입니다.
- isTopLevel이 true임
-
512키비바이트
기본값 640키비바이트에서 deferred-fetch-minimal에 예약된 할당량 만큼 차감됨
- deferredFetchAllowed가 true이고, navigable의 navigable container의 예약된 지연 fetch 할당량이 일반 할당량이면
- 일반 할당량
- deferredFetchMinimalAllowed가 true이고, navigable의 navigable container의 예약된 지연 fetch 할당량이 최소 할당량이면
- 최소 할당량
- 그 외의 경우
- 0
-
quotaForRequestOrigin을 64키비바이트로 둔다.
-
각 navigable에 대해, controlDocument의 node navigable의 포함 자손 navigable들 중 active document의 지연 fetch 제어 문서가 controlDocument인 것만 대상으로:
-
각 container에 대해, navigable의 active document의 shadow-including inclusive descendants 중 navigable container인 것: quota를 container의 예약된 지연 fetch 할당량만큼 차감한다.
-
각 지연 fetch 레코드 deferredRecord에 대해, navigable의 active document의 관련 설정 객체의 fetch group의 deferred fetch records에 대해:
-
-
quota가 0 이하이면 0을 반환한다.
-
quota가 quotaForRequestOrigin보다 작으면 quota를 반환한다.
-
quotaForRequestOrigin을 반환한다.
지연 fetch 할당량 예약을 실행하려면, navigable container container와 origin originToNavigateTo를 받아:
이 알고리즘은 탐색 시, 탐색의 소스 문서가 navigable의 부모 문서일 때 호출된다. 권한 정책에 따라 컨테이너 및 그 navigable에 대해 64kb 또는 8kb의 할당량을 잠재적으로 예약한다. 실제로 예약된 할당량이 사용됐는지는 컨테이너 문서에서 관찰할 수 없다. 이 알고리즘은 컨테이너의 문서가 탐색된 컨테이너에 할당량을 위임할 수 있고, 예약된 할당량은 그 경우에만 적용되며, 공유될 경우 무시됨을 가정한다. 할당량이 예약되었고 문서가 결국 부모와 동일 출처가 되면, 할당량은 해제된다.
-
container의 예약된 지연 fetch 할당량을 0으로 설정한다.
-
controlDocument를 container의 node document의 지연 fetch 제어 문서로 둔다.
-
"
deferred-fetch"에 대한 상속된 정책이 container와 originToNavigateTo에 대해"Enabled"이고, 사용 가능 지연 fetch 할당량이 controlDocument에 대해 일반 할당량 이상이면, container의 예약된 지연 fetch 할당량을 일반 할당량으로 설정하고 반환한다. -
아래 조건이 모두 true이면:
-
controlDocument의 node navigable이 최상위 traversable임
-
"
deferred-fetch-minimal"에 대한 상속된 정책이 container와 originToNavigateTo에 대해"Enabled" -
controlDocument의 node navigable의 자손 navigables에서, remove하여 navigable의 navigable container의 예약된 지연 fetch 할당량이 최소 할당량이 아닌 것을 제외한 후, 크기가 deferred-fetch-minimal에 예약된 할당량 / 최소 할당량 미만임
이 경우 container의 예약된 지연 fetch 할당량을 최소 할당량으로 설정한다.
-
지연 fetch 할당량 해제 가능을 실행하려면, document document를 받아, document의 node navigable의 container document가 null이 아니고, 그 origin이 document와 동일 출처이면, document의 node navigable의 navigable container의 예약된 지연 fetch 할당량을 0으로 설정한다.
이 알고리즘은 문서가 생성될 때 호출된다. 동일 출처 중첩 문서는 어차피 부모의 할당량을 공유하므로 할당량을 예약하지 않도록 한다. 이는 문서 생성 시에만 호출될 수 있는데, origin은 리다이렉트가 처리된 후에만 알 수 있기 때문이다.
지연 fetch 제어 문서를 얻으려면, document document를 받아:
-
document의 node navigable의 container document가 null이거나, 문서의 origin이 document와 동일 출처가 아니면, document를 반환한다. 그 외에는, 지연 fetch 제어 문서를 document의 node navigable의 container document로 실행한 결과를 반환한다.
5. Fetch API
fetch() 메서드는 리소스 가져오기를 위한 비교적 저수준의 API입니다. XMLHttpRequest보다
약간 더 넓은 영역을 다루지만, 현재는 요청 진행 상황(응답 진행 상황 아님)에 있어 부족한 부분이 있습니다.
fetch() 메서드를 사용하면 리소스를 가져오고 그 내용을 Blob으로
추출하는 것이 매우 간단합니다:
fetch("/music/pk/altes-kamuffel.flac")
.then(res => res.blob()).then(playBlob)
특정 응답 헤더만 로그로 남기고 싶다면:
fetch("/", {method:"HEAD"})
.then(res => log(res.headers.get("strict-transport-security")))
교차 출처 리소스의 특정 응답 헤더를 확인한 뒤 응답을 처리하려면:
fetch("https://pk.example/berlin-calling.json", {mode:"cors"})
.then(res => {
if(res.headers.get("content-type") &&
res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) {
return res.json()
} else {
throw new TypeError()
}
}).then(processJSON)
URL 쿼리 파라미터를 다루고 싶다면:
var url = new URL("https://geo.example.org/api"),
params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)
바디 데이터를 점진적으로 받고 싶다면:
function consume(reader) {
var total = 0
return pump()
function pump() {
return reader.read().then(({done, value}) => {
if (done) {
return
}
total += value.byteLength
log(`received ${value.byteLength} bytes (${total} bytes in total)`)
return pump()
})
}
}
fetch("/music/pk/altes-kamuffel.flac")
.then(res => consume(res.body.getReader()))
.then(() => log("전체 바디를 메모리에 보존하지 않고 모두 소비함!"))
.catch(e => log("문제가 발생함: " + e))
5.1. Headers 클래스
typedef (sequence <sequence <ByteString >>or record <ByteString ,ByteString >); [HeadersInit Exposed =(Window ,Worker )]interface {Headers constructor (optional HeadersInit );init undefined append (ByteString ,name ByteString );value undefined delete (ByteString );name ByteString ?get (ByteString );name sequence <ByteString >getSetCookie ();boolean has (ByteString );name undefined set (ByteString ,name ByteString );value iterable <ByteString ,ByteString >; };
Headers 객체는
연관된
헤더 리스트 (즉,
header list)를
가진다.
이 리스트는 처음에 비어 있다. 이 값은 다른 객체의 header list를 가리킬 수도 있다. 예를 들어,
Request 객체가
보여주듯이
request의 헤더 리스트를 가리킬
수 있다.
Headers 객체는
guard도 가지며, 이는 헤더 guard입니다. 헤더 guard는
"immutable", "request",
"request-no-cors", "response", "none" 중 하나입니다.
headers = new Headers([init])-
새
Headers객체를 생성합니다. init을 사용해 내부 헤더 리스트를 채울 수 있습니다. 아래 예시 참고. headers . append(name, value)-
headers에 헤더를 추가합니다.
headers . delete(name)-
headers에서 헤더를 제거합니다.
headers . get(name)-
name인 모든 헤더 값들을 문자열로 반환하며, 값들은 콤마와 공백으로 구분됩니다.
headers . getSetCookie()-
이름이 `
Set-Cookie`인 모든 헤더 값을 리스트로 반환합니다. headers . has(name)-
name인 헤더가 존재하는지 여부를 반환합니다.
headers . set(name, value)-
이름이 name인 첫 번째 헤더 값을 value로 대체하고, 동일한 이름의 남은 헤더는 모두 제거합니다.
for(const [name, value] of headers)-
headers를 반복(iterate)할 수 있습니다.
"request-no-cors"의 단계는 공유되지 않습니다. delete()에서
항상 성공하는 가짜 값(CORS 안전 목록 요청 헤더에 대해)이 있을 수 없기 때문입니다.
추가를 header
(name, value)에 대해 Headers 객체
headers에 실행하려면:
-
value 정규화를 value에 실행한다.
-
유효성 검사 (name, value)를 headers에 대해 실행한 결과가 false면 return한다.
-
headers의 guard가 "
request-no-cors"이면:-
temporaryValue가 null이면 temporaryValue를 value로 설정한다.
-
그 외에는 temporaryValue에 0x2C 0x20을 이어 붙이고, value를 이어 붙인다.
-
(name, temporaryValue)가 no-CORS 안전 목록 요청 헤더가 아니면 return 한다.
-
headers의 guard가 "
request-no-cors"이면 권한 없는 no-CORS 요청 헤더 제거를 headers에 실행한다.
채우기를 Headers 객체
headers와 객체 object로 실행하려면:
권한 없는 no-CORS 요청 헤더 제거를
Headers 객체
(headers)에 실행하려면:
-
각 headerName에 대해 권한 있는 no-CORS 요청 헤더 이름들에서:
이 단계는 권한 없는 코드가 헤더를 수정할 때 호출된다.
delete(name) 메서드 단계:
-
유효성 검사 (name, ``)를 this에 실행한 결과가 false면 return한다.
임의의 헤더 값을 전달해도 부작용이 없어야 한다.
-
this의 guard가 "
request-no-cors"이고, name이 no-CORS 안전 목록 요청 헤더 이름이 아니고, name이 권한 있는 no-CORS 요청 헤더 이름이 아니면 return한다. -
this의 guard가 "
request-no-cors"이면 권한 없는 no-CORS 요청 헤더 제거를 this에 실행한다.
getSetCookie() 메서드 단계:
set(name, value)
메서드 단계:
반복할 값 쌍은 정렬 및 결합을 this의 헤더 리스트에 실행한 결과이다.
5.2. BodyInit 유니언
typedef (Blob or BufferSource or FormData or URLSearchParams or USVString );XMLHttpRequestBodyInit typedef (ReadableStream or XMLHttpRequestBodyInit );BodyInit
안전 추출을 타입이 지정된 body를
바이트
시퀀스 또는 BodyInit 객체
object에서 추출하려면 다음 단계를 수행한다:
-
object가
ReadableStream객체라면:-
Assert: object는 흔들림(disturbed)도 아니고 locked도 아니다.
-
-
추출을 object에 실행한 결과를 반환한다.
안전 추출 동작은 예외를 던지지 않는 추출의 부분집합이다.
추출을
타입이 지정된 body로
바이트
시퀀스 또는 BodyInit 객체
object에서,
선택적 불리언 keepalive(기본값 false)로 실행하려면 다음 단계를 수행한다:
-
stream을 null로 둔다.
-
object가
ReadableStream객체라면 stream을 object로 설정한다. -
그 외에 object가
Blob객체라면, stream을 object의 get stream 실행 결과로 설정한다. -
그 외에는 stream을 새
ReadableStream객체로 두고, 바이트 읽기 지원으로 set up을 stream에 실행한다. -
Assert: stream은
ReadableStream객체다. -
action을 null로 둔다.
-
source를 null로 둔다.
-
length를 null로 둔다.
-
type을 null로 둔다.
-
object 타입에 따라 다음을 실행한다:
Blob-
source를 object로 설정한다.
length를 object의
size로 설정한다.object의
type속성이 빈 바이트 시퀀스가 아니면, type을 해당 값으로 설정한다. - 바이트 시퀀스
-
source를 object로 설정한다.
BufferSource-
source를 object가 가진 바이트의 복사본으로 설정한다.
FormData-
action을 다음 단계로 설정:
multipart/form-data인코딩 알고리즘을 object의 entry list와 UTF-8로 실행.source를 object로 설정한다.
length를 불명확, 개선은 html/6424 참고로 설정한다.
type을 `
multipart/form-data; boundary=` +multipart/form-data경계 문자열로 설정한다. URLSearchParams-
source를
application/x-www-form-urlencodedserializer를 object의 list에 실행한 결과로 설정한다.type을 `
application/x-www-form-urlencoded;charset=UTF-8`으로 설정한다. - 스칼라 값 문자열
-
source를 UTF-8 인코딩을 object에 실행한 결과로 설정한다.
type을 `
text/plain;charset=UTF-8`로 설정한다. ReadableStream-
keepalive가 true면 TypeError를 던진다.
object가 흔들림(disturbed)이나 locked이면 TypeError를 던진다.
-
source가 바이트 시퀀스라면, action을 source를 반환하는 단계로 설정하고, length를 source의 길이로 둔다.
-
action이 null이 아니면, 아래 단계를 병렬로 실행한다:
-
action을 실행한다.
바이트가 하나 이상 사용 가능하고 stream이 errored가 아니면, enqueue를, Uint8Array 생성을 사용하여 사용 가능한 바이트를 stream에 추가한다.
action 실행이 끝나면, close를 stream에 실행한다.
-
-
body를 body의 새 인스턴스로 두고, stream은 stream, source는 source, length는 length로 설정한다.
-
(body, type)을 반환한다.
5.3. Body 믹스인
interface mixin {Body readonly attribute ReadableStream ?body ;readonly attribute boolean bodyUsed ; [NewObject ]Promise <ArrayBuffer >arrayBuffer (); [NewObject ]Promise <Blob >blob (); [NewObject ]Promise <Uint8Array >bytes (); [NewObject ]Promise <FormData >formData (); [NewObject ]Promise <any >json (); [NewObject ]Promise <USVString >text (); };
네트워크 계층에 의존하면 안 되는 포맷(예: HTML)은 여기서 노출하지 않습니다. 대신 HTML 파서 API가 스트림을 받도록 설계될 수 있습니다.
Body 인터페이스 믹스인을 포함한 객체는
body (null 또는 body)를 가진다.
Body 인터페이스 믹스인을 포함한 객체는
사용 불가로
간주되는데, body가 null이 아니고,
body의 stream이 disturbed 또는
locked인 경우를 말한다.
requestOrResponse . body-
requestOrResponse의 body를
ReadableStream으로 반환합니다. requestOrResponse . bodyUsed-
requestOrResponse의 body가 읽혔는지 여부를 반환합니다.
requestOrResponse . arrayBuffer()-
requestOrResponse의 body를
ArrayBuffer로 반환하는 promise를 반환합니다. requestOrResponse . blob()-
requestOrResponse의 body를
Blob으로 반환하는 promise를 반환합니다. requestOrResponse . bytes()-
requestOrResponse의 body를
Uint8Array로 반환하는 promise를 반환합니다. requestOrResponse . formData()-
requestOrResponse의 body를
FormData로 반환하는 promise를 반환합니다. requestOrResponse . json()-
requestOrResponse의 body를 JSON으로 파싱해 반환하는 promise를 반환합니다.
requestOrResponse . text()-
requestOrResponse의 body를 문자열로 반환하는 promise를 반환합니다.
body 소비
알고리즘은 Body
믹스인을 포함한 객체 object와,
바이트 시퀀스를 받아 JS 값이나 예외를 반환하는 알고리즘 convertBytesToJSValue를
받아 다음을 수행한다:
-
object가 사용 불가면, TypeError로 reject된 promise를 반환한다.
-
promise를 새 promise로 둔다.
- errorSteps를 error를 받아 promise를 reject하는 단계로 둔다.
- successSteps를 바이트 시퀀스 data를 받아, promise를 resolve하는 단계로 둔다. convertBytesToJSValue를 data에 실행해 예외가 발생하면 errorSteps를 실행한다.
-
그 외에는 완전히 읽기를 object의 body, successSteps, errorSteps, object의 관련 글로벌 객체로 실행한다.
-
promise를 반환한다.
arrayBuffer() 메서드의 단계는,
consume
body를
this와 아래 단계를
인자로 실행한 결과를 반환한다.
아래 단계는 byte sequence bytes가 주어졌을 때:
생성 결과를 반환한다.
ArrayBuffer
의 bytes로 this의 relevant realm에서 생성한다.
위 메서드는 RangeError로
reject될 수 있다.
blob() 메서드의 단계는
consume body를
this와 아래 단계를
인자로 실행한 결과를 반환한다.
아래 단계는 byte sequence bytes가 주어졌을 때:
Blob
객체를 반환하며, 내용은 bytes이고,
type
attribute는 get the MIME type의
this 결과이다.
bytes() 메서드의 단계는,
consume body를
this와 아래 단계를
인자로 실행한 결과를 반환한다.
아래 단계는 byte sequence bytes가 주어졌을 때:
생성 결과를 반환한다.
Uint8Array
의 bytes로 this의 relevant realm에서 생성한다.
위 메서드는 RangeError로
reject될 수 있다.
formData() 메서드의 단계는,
consume body를
this와 아래 단계를
인자로 실행한 결과를 반환한다.
아래 단계는 byte sequence bytes가 주어졌을 때:
-
mimeType을 get the MIME type의 this 결과로 한다.
-
mimeType이 null이 아니면 mimeType의 essence에 따라 분기한다:
- "
multipart/form-data" -
-
bytes를 파싱한다. mimeType의 `
boundary` 파라미터 값을 사용하고, Returning Values from Forms: multipart/form-data에 정의된 규칙을 따른다. [RFC7578]`
Content-Disposition` 헤더에 `filename` 파라미터가 있는 각 파트는, 값이 entry인File객체로 파싱한다.File객체의name속성은 해당 파트의 `filename` 파라미터 값이어야 한다.type속성은 해당 파트의 `Content-Type` 헤더가 있으면 그 값이고, 없으면 `text/plain`이어야 한다. ([RFC7578] 4.4절의 기본값)`
Content-Disposition` 헤더에 `filename` 파라미터가 없는 각 파트는, 값이 entry인 BOM 없는 UTF-8 디코드 내용을 가진다. 이 과정은 `Content-Type` 헤더 및 `charset` 파라미터의 존재 여부와 상관없이 수행된다.`
Content-Disposition` 헤더의 `name` 파라미터 값이 `_charset_`인 파트도 다른 파트와 동일하게 파싱된다. 인코딩에는 영향을 주지 않는다. -
파싱 결과로 얻은 각 entry를 entry list에 append하는, 새
FormData객체를 반환한다.
위는 `
multipart/form-data` 처리에 필요한 대략적 설명이며, 더 상세한 파싱 명세는 작성되어야 한다. 자원봉사 환영. -
- "
application/x-www-form-urlencoded" -
-
entries를 parsing bytes의 결과로 한다.
-
entry list가 entries인, 새
FormData객체를 반환한다.
-
- "
json() 메서드의 단계는,
consume body를
this와
바이트로부터 JSON 파싱을 실행한 결과를 반환한다.
위 메서드는 SyntaxError로
reject될 수 있다.
text() 메서드의 단계는,
consume body를
this와
UTF-8 디코드를 실행한 결과를 반환한다.
5.4. Request 클래스
typedef (Request or USVString ); [RequestInfo Exposed =(Window ,Worker )]interface {Request constructor (RequestInfo ,input optional RequestInit = {});init readonly attribute ByteString method ;readonly attribute USVString url ; [SameObject ]readonly attribute Headers headers ;readonly attribute RequestDestination destination ;readonly attribute USVString referrer ;readonly attribute ReferrerPolicy referrerPolicy ;readonly attribute RequestMode mode ;readonly attribute RequestCredentials credentials ;readonly attribute RequestCache cache ;readonly attribute RequestRedirect redirect ;readonly attribute DOMString integrity ;readonly attribute boolean keepalive ;readonly attribute boolean isReloadNavigation ;readonly attribute boolean isHistoryNavigation ;readonly attribute AbortSignal signal ;readonly attribute RequestDuplex duplex ; [NewObject ]Request clone (); };Request includes Body ;dictionary {RequestInit ByteString ;method HeadersInit ;headers BodyInit ?;body USVString ;referrer ReferrerPolicy ;referrerPolicy RequestMode ;mode RequestCredentials ;credentials RequestCache ;cache RequestRedirect ;redirect DOMString ;integrity boolean ;keepalive AbortSignal ?;signal RequestDuplex ;duplex RequestPriority ;priority any ; // can only be set to null };window enum {RequestDestination ,"" ,"audio" ,"audioworklet" ,"document" ,"embed" ,"font" ,"frame" ,"iframe" ,"image" ,"json" ,"manifest" ,"object" ,"paintworklet" ,"report" ,"script" ,"sharedworker" ,"style" ,"track" ,"video" ,"worker" };"xslt" enum {RequestMode ,"navigate" ,"same-origin" ,"no-cors" };"cors" enum {RequestCredentials ,"omit" ,"same-origin" };"include" enum {RequestCache ,"default" ,"no-store" ,"reload" ,"no-cache" ,"force-cache" };"only-if-cached" enum {RequestRedirect ,"follow" ,"error" };"manual" enum {RequestDuplex };"half" enum {RequestPriority ,"high" ,"low" };"auto"
"serviceworker"는
JavaScript에서 관찰할 수 없으므로 RequestDestination에서 생략됩니다. 하지만 구현에서는 여전히 destination으로 지원해야 합니다. "websocket"과
"webtransport"는 JavaScript에서 사용할 수 없거나 관찰할 수 없으므로 RequestMode에서 생략됩니다.
Request 객체는
request(request 객체)을 가진다.
Request 객체는 또한
headers(null 또는 Headers 객체, 초기값은
null)을 가진다.
Request 객체는 signal(null 또는 AbortSignal
객체, 초기값은 null)을 가진다.
Request 객체의
body는
request의
body이다.
request = new Request(input [, init])-
새 request를 반환하며, input이 문자열일 경우
url속성은 input이 된다. input이Request객체일 경우,url속성은 input의 값이 된다.init 인수는 다음과 같이 속성을 설정할 수 있는 객체이다:
method- request의
method를 설정하는 문자열. headersHeaders객체, 객체 리터럴, 또는 2-요소 배열의 배열로, request의headers를 설정.bodyBodyInit객체 또는 null. request의 body를 설정.referrer- 동일 출처 URL, "
about:client", 또는 빈 문자열이어야 하며, request의 referrer를 설정. referrerPolicy- referrer policy이며,
request의
referrerPolicy를 설정. mode- 해당 요청이 CORS를 사용할지, 동일 출처로 제한할지를 지정하는 문자열.
request의
mode를 설정. input이 문자열이면, 기본값은 "cors"임. credentials- 자격 증명을 항상, 절대, 또는 동일 출처로만 보낼지 여부와,
응답에서 받은 자격 증명을 사용할지를 결정하는 문자열.
request의
credentials를 설정. input이 문자열이면, 기본값은 "same-origin"임. cache- 해당 요청이 브라우저의 캐시와 상호작용하는 방식을 지정하는 문자열로,
request의
cache를 설정. redirect- request가 리디렉션을 따를지, 에러로 처리할지, 또는 리디렉션(opaque 방식)으로 반환할지를
결정하는 문자열. request의
redirect를 설정. integrity- request로 가져올 리소스의 암호화 해시값.
request의
integrity를 설정. keepalive- 불리언 값으로,
request의
keepalive를 설정. signalAbortSignal를 받아 request의signal를 설정.window- null만 허용되며, request를 어떤
Window와도 연관시키지 않기 위해 사용됨. duplex- "
half"만 유효하며, 요청 전체를 보낸 뒤 응답을 처리하는 half-duplex fetch 를 시작할 때 사용. "full"은 미래의 full-duplex fetch(요청 전체를 보내기 전에도 응답을 처리 가능)를 위해 예약됨.body가ReadableStream객체인 경우 이 속성을 반드시 지정해야 한다. "full" 관련 논의는 issue #1254 참고. priority- 문자열로, request의 priority를 설정.
request . method- request의 HTTP method를 반환하며, 기본값은 "
GET"임. request . url- request의 URL을 문자열로 반환.
request . headers- request에 연결된 헤더를 담은
Headers객체를 반환. 네트워크 계층에서 사용자 에이전트가 추가하는 헤더(예: "Host")는 여기서는 반영되지 않는다. request . destination- request가 요청하는 리소스의 종류(예: "
document" 또는 "script")를 반환. request . referrer- request의 referrer를 반환.
init에서 명시적으로 설정하면 동일 출처 URL 또는 빈 문자열,
그렇지 않으면 "
about:client"이 된다. fetch 중에는 실제 요청의 `Referer` 헤더 값을 결정하는 데 사용됨. request . referrerPolicy- request에 연결된 referrer policy를 반환. fetch 중 request의 referrer 값을 계산하는 데 쓰임.
request . mode- request에 연결된 mode를 반환. CORS를 사용할지, 동일 출처로 제한할지에 대한 문자열임.
request . credentials- request에 연결된 credentials mode를 반환. 자격 증명을 항상, 절대 혹은 동일 출처에만 보낼지 나타내는 문자열임.
request . cache- request에 연결된 cache mode를 반환. fetch 시 브라우저의 캐시와 어떻게 상호작용할지에 대한 문자열임.
request . redirect- request에 연결된 redirect mode를 반환. fetch 중 리디렉션을 어떻게 처리할지에 대한 문자열임. request는 기본적으로 리디렉션을 따른다.
request . integrity- request로 가져오는 리소스의 무결성 검증용 암호 해시(metadata) 반환. 값은 여러 해시가 공백 문자로 구분된 문자열. [SRI]
request . keepalive- request가 생성된 전역(global) 환경이 종료되어도 해당 요청이 살아남을 수 있는지에 대한 true/false 여부 반환.
request . isReloadNavigation- request가 새로고침 네비게이션용인지 true/false로 반환.
request . isHistoryNavigation- request가 히스토리 네비게이션(즉, 뒤로/앞으로)이었는지 true/false로 반환.
request . signal- request와 연결된
AbortSignal객체를 반환. 해당 객체는 request가 abort(취소)되었는지 및 abort 이벤트 핸들러를 나타냄. request . duplex- "
half"를 반환. 즉, 요청 전체를 보낸 다음에 응답을 처리하는 half-duplex fetch임을 의미. 미래에는 "full"도 반환될 수 있음. 즉, 요청이 끝나기 전에 응답을 처리하는 full-duplex fetch를 구분할 수도 있음. "full" 관련 내용은 issue #1254 참고. request . clone()-
request의 복제본을 반환.
생성을 실행하려면, Request
객체를 만들 때,
request
request,
headers guard
guard,
AbortSignal
객체 signal, 그리고 realm realm을 받아 다음을 수행한다:
new Request(input, init)
생성자 단계:
-
request를 null로 둔다.
-
fallbackMode를 null로 둔다.
-
baseURL을 this의 관련 설정 객체의 API 기본 URL로 둔다.
-
signal을 null로 둔다.
-
input이 문자열이면:
-
그 외에는:
-
traversableForUserPrompts를 "
client"로 둔다. -
request의 사용자 프롬프트용 traversable가 환경 설정 객체이고, 그 origin이 origin과 동일 출처면, traversableForUserPrompts를 request의 사용자 프롬프트용 traversable로 설정한다.
-
init["
window"]가 있으면, traversableForUserPrompts를 "no-traversable"로 설정한다. -
request를 다음 속성으로 하는 request 새 객체로 둔다:
- URL
- request의 URL.
- method
- request의 method.
- header list
- request의 header list의 복사본.
- unsafe-request flag
- 설정됨.
- client
- this의 관련 설정 객체.
- 사용자 프롬프트용 traversable
- traversableForUserPrompts.
- internal priority
- request의 internal priority.
- origin
- request의 origin. 이 origin 전파는 서비스 워커가 탐색 요청을 처리할 때만 중요하다. 이 경우에는 요청의 origin이 현재 client와 달라질 수 있다.
- referrer
- request의 referrer.
- referrer policy
- request의 referrer policy.
- mode
- request의 mode.
- credentials mode
- request의 credentials mode.
- cache mode
- request의 cache mode.
- redirect mode
- request의 redirect mode.
- integrity metadata
- request의 integrity metadata.
- keepalive
- request의 keepalive.
- reload-navigation flag
- request의 reload-navigation flag.
- history-navigation flag
- request의 history-navigation flag.
- URL list
- request의 URL list의 복제본.
- initiator type
- "
fetch".
-
init이 비어있지 않으면:
-
request의 mode가 "
navigate"이면 "same-origin"으로 설정한다. -
request의 reload-navigation flag를 해제한다.
-
request의 history-navigation flag를 해제한다.
-
request의 origin을 "
client"로 설정한다. -
request의 referrer를 "
client"로 설정한다. -
request의 referrer policy를 빈 문자열로 설정한다.
-
request의 URL을 request의 current URL로 설정한다.
서비스 워커가 요청을 "리다이렉트"할 때, 예를 들어 교차 출처 스타일시트의 이미지에서, 요청을 수정하면 더 이상 원본이 아닌(즉, 교차 출처 스타일시트가 아닌) 서비스 워커가 "리다이렉트"한 것처럼 보이도록 한다. 이는 원본이 동일한 종류의 요청을 생성하지 못할 수도 있기 때문에 필요하다. 원본을 신뢰하는 서비스가 있다면 이를 악용할 수 있지만, 현실적으로는 드문 일이다.
-
-
init["
referrerPolicy"]가 있으면, request의 referrer policy를 그 값으로 설정한다. -
mode가 "
navigate"이면 TypeError를 던진다. -
mode가 null이 아니면 request의 mode를 mode로 설정한다.
-
init["
credentials"]가 있으면, request의 credentials mode를 그 값으로 설정한다. -
init["
cache"]가 있으면, request의 cache mode를 그 값으로 설정한다. -
request의 cache mode가 "
only-if-cached"이고, request의 mode가 "same-origin"이 아니면, TypeError를 던진다. -
init["
redirect"]가 있으면, request의 redirect mode를 그 값으로 설정한다. -
init["
integrity"]가 있으면, request의 integrity metadata를 그 값으로 설정한다. -
-
request의 internal priority가 null이 아니면, request의 internal priority를 구현 정의 방식으로 갱신한다.
-
-
signals를 signal이 null이 아니면 « signal »로, 아니면 « »로 둔다.
-
this의 signal을 종속 abort signal 생성을 signals와
AbortSignal, this의 관련 realm으로 실행한 결과로 설정한다. -
this의 headers를 새로운
Headers객체로, this의 관련 realm을 사용하고, 헤더 리스트는 request의 header list, guard는 "request"로 설정한다. -
init이 비어있지 않으면:
헤더가 이 모드에서 허용되지 않는 헤더가 있을 수 있으므로 정제(sanitized)된다. 그렇지 않으면 이전에 정제되었거나 권한 있는 API에서 설정된 이후 수정되지 않은 상태이다.
-
inputBody를 input이
Request객체이면, input의 request의 body로, 아니면 null로 둔다. -
init["
body"]가 있고 null이 아니거나 inputBody가 null이 아니고, request의 method가 `GET` 또는 `HEAD`이면 TypeError를 던진다. -
initBody를 null로 둔다.
-
inputOrInitBody를 initBody가 null이 아니면 initBody로, 아니면 inputBody로 둔다.
-
inputOrInitBody가 null이 아니고 그 source가 null이면:
-
finalBody를 inputOrInitBody로 둔다.
-
initBody가 null이고 inputBody가 null이 아니면:
method getter 단계는 this의
request의
method를
반환한다.
url getter 단계는 this의
request의
URL을 serialize하여 반환한다.
headers getter 단계는
this의 headers를 반환한다.
destination getter 단계는 this의
request의
destination을 반환한다.
referrer getter 단계:
referrerPolicy getter 단계는
this의 request의
referrer
policy를 반환한다.
mode getter 단계는 this의
request의
mode를 반환한다.
credentials getter 단계는
this의 request의
credentials
mode를 반환한다.
cache getter 단계는 this의
request의
cache
mode를 반환한다.
redirect getter 단계는
this의 request의
redirect mode를 반환한다.
integrity getter 단계는
this의 request의
integrity
metadata를 반환한다.
keepalive getter 단계는
this의 request의
keepalive를
반환한다.
isReloadNavigation getter 단계는
this의
request의
reload-navigation flag가 설정되어 있으면 true, 아니면
false를 반환한다.
isHistoryNavigation getter 단계는
this의
request의
history-navigation flag가
설정되어 있으면 true, 아니면 false를 반환한다.
signal getter 단계는 this의
signal을 반환한다.
This의 signal은 항상 생성자에서와 복제할 때 초기화됩니다.
duplex getter 단계는
"half"를 반환한다.
clone() 메서드 단계는 다음과 같습니다:
-
clonedSignal을 « this의 signal »에서 종속 abort signal 생성의 결과로 설정합니다.
AbortSignal과 this의 relevant realm을 사용합니다. -
clonedRequestObject를 creating
Request객체의 결과로 설정합니다. clonedRequest, this의 headers의 guard, clonedSignal 그리고 this의 relevant realm을 인자로 합니다. -
clonedRequestObject를 반환합니다.
5.5. Response 클래스
[Exposed =(Window ,Worker )]interface {Response constructor (optional BodyInit ?=body null ,optional ResponseInit = {}); [init NewObject ]static Response error (); [NewObject ]static Response redirect (USVString ,url optional unsigned short = 302); [status NewObject ]static Response json (any ,data optional ResponseInit = {});init readonly attribute ResponseType type ;readonly attribute USVString url ;readonly attribute boolean redirected ;readonly attribute unsigned short status ;readonly attribute boolean ok ;readonly attribute ByteString statusText ; [SameObject ]readonly attribute Headers headers ; [NewObject ]Response clone (); };Response includes Body ;dictionary {ResponseInit unsigned short = 200;status ByteString = "";statusText HeadersInit ; };headers enum {ResponseType ,"basic" ,"cors" ,"default" ,"error" ,"opaque" };"opaqueredirect"
Response
객체는
response(response 객체)을 가진다.
Response
객체는 또한 headers(null 또는 Headers 객체, 초기값은
null)을 가진다.
Response
객체의 body는
response의 body이다.
response = new Response(body = null [, init])-
response의 body가 body이고, status, status message, headers는 init으로 설정된
Response를 생성한다. response = Response . error()-
네트워크 오류
Response를 생성한다. response = Response . redirect(url, status = 302)-
url로 status 상태로 리다이렉트하는
Response를 생성한다. response = Response . json(data [, init])-
body가 JSON 인코딩된 data이고, status, status message, headers가 init으로 설정된
Response를 생성한다. response . type-
response의 타입을 반환한다(예: "
cors"). response . url-
response의 URL을 반환하며, 없으면 빈 문자열을 반환한다.
response . redirected-
response가 리다이렉트를 통해 얻어졌는지 여부를 반환한다.
response . status-
response의 status를 반환한다.
response . ok-
response의 status가 ok status라면 true를 반환한다.
response . statusText-
response의 status message를 반환한다.
response . headers-
response의 headers를
Headers객체로 반환한다. response . clone()-
response의 복제본을 반환한다.
생성하기는 Response
객체를 만들기 위해,
response
response, headers
guard guard, 그리고
realm
realm을 입력으로 받아 다음 단계를 실행한다:
-
responseObject의 response를 response로 설정한다.
-
responseObject의 headers를 새로운
Headers객체(realm 사용)로 설정하고, headers list는 response의 headers list, guard는 guard로 한다. -
responseObject를 반환한다.
다음이 주어졌을 때 initialize a
response를 수행하려면, Response 객체
response,
ResponseInit
init, 그리고 null 또는 body with type인 body를 사용하여 다음 단계를 실행한다:
-
만약 init["
status"] 가 200에서 599 사이(포함)가 아니면, throwRangeError를 발생시킨다. -
만약 init["
statusText"] 가 빈 문자열이 아니고 reason-phrase 토큰 생성 규칙과 일치하지 않으면, throwTypeError를 발생시킨다. -
response의 response의 status message를 init["
statusText"]로 설정한다. -
만약 init["
headers"] 가 존재하면, fill 알고리즘을 사용하여 response의 headers를 init["headers"]로 채운다. -
만약 body가 non-null이면, 다음을 수행한다:
-
만약 response의 status가 null body status이면, throw
TypeError를 발생시킨다.101 및 103은 다른 곳에서의 사용 때문에 null body status에 포함된다. 이들은 이 단계에 영향을 미치지 않는다.
-
만약 body의 type이 non-null이고 response의 header list가 포함하지 않는다면 `
Content-Type`, append (`Content-Type`, body의 type)를 response의 header list에 추가한다.
-
new Response(body, init)
생성자 단계는 다음과 같습니다:
-
this의 headers를 새로운
Headers객체로 설정합니다. 이 객체는 this의 relevant realm을 사용하며, header list는 this의 response의 header list이고, guard는 "response"입니다. -
bodyWithType을 null로 설정합니다.
-
body가 null이 아니면, bodyWithType을 extracting body의 결과로 설정합니다.
-
initialize a response를 this, init, bodyWithType를 인자로 수행합니다.
정적 error() 메서드 단계는,
새로운 network
error,
"immutable", 그리고 current realm을 입력으로 생성하기를 실행한 결과를 반환한다.
정적
redirect(url, status) 메서드 단계는
다음과 같다:
-
parsedURL을 파싱을 url과 current settings object의 API base URL로 실행한 결과로 설정한다.
-
parsedURL이 실패이면 TypeError 예외를 throw한다.
-
status가 redirect status가 아니면 RangeError 예외를 throw한다.
-
responseObject를 생성된
Response객체의 결과로서, 새로운 response, "immutable", 그리고 현재 realm을 받아서 설정한다. -
value를 parsedURL을 직렬화하고 isomorphic encode한 결과로 설정한다.
-
append (`
Location`, value)를 responseObject의 response의 header list에 추가한다. -
responseObject를 반환한다.
정적
json(data, init) 메서드 단계는 다음과 같다:
-
bytes를 serialize a JavaScript value to JSON bytes를 data에 대해 실행한 결과로 설정한다.
-
body를 extracting bytes의 결과로 설정한다.
-
responseObject를 생성하기를 새로운 response, "
response", current realm으로 실행한 결과로 설정한다. -
response 초기화를 responseObject, init, (body, "
application/json")로 실행한다. -
responseObject를 반환한다.
type getter 단계는 this의
response의 type을 반환하는 것입니다.
url getter 단계는
this의 response의 URL이 null이면
빈 문자열을 반환하고, 그렇지 않으면 this의
response의 URL을
serialized 하며, exclude fragment를 true로 설정합니다.
redirected getter 단계는
this의 response의 URL list의 size가
1보다 크면 true를 반환하고, 아니면 false를 반환합니다.
리다이렉트 결과로 생성된 responses를 필터링하려면 API에서 직접 처리하세요. 예:
fetch(url, { redirect:"error" }).
이렇게 하면 잠재적으로 안전하지 않은 response가 실수로 노출되는 것을 방지할 수 있습니다.
status getter 단계는
this의 response의 status를 반환하는 것입니다.
ok getter 단계는
this의 response의 status가 ok status면 true, 아니면 false를 반환합니다.
statusText getter 단계는
this의 response의 status
message를 반환하는 것입니다.
headers getter 단계는
this의 headers를 반환하는 것입니다.
clone() 메서드 단계는 다음과 같습니다:
5.6. fetch 메서드
partial interface mixin WindowOrWorkerGlobalScope { [NewObject ]Promise <Response >fetch (RequestInfo ,input optional RequestInit = {}); };init dictionary :DeferredRequestInit RequestInit {DOMHighResTimeStamp ; }; [activateAfter Exposed =Window ]interface {FetchLaterResult readonly attribute boolean activated ; };partial interface Window { [NewObject ,SecureContext ]FetchLaterResult fetchLater (RequestInfo ,input optional DeferredRequestInit = {}); };init
fetch(input, init)
메서드 단계는 다음과 같습니다:
-
p를 새로운 promise로 설정합니다.
-
requestObject를
Request생성자를 input과 init을 인자로 호출한 결과로 설정합니다. 만약 예외가 발생하면, reject p에 그 예외를 넘기고 p를 반환합니다. -
request를 requestObject의 request로 설정합니다.
-
requestObject의 signal이 aborted인 경우, 다음을 수행합니다:
-
fetch() 호출을 중단합니다. p, request, null, 그리고 requestObject의 signal의 abort reason을 사용합니다.
-
p를 반환합니다.
-
-
globalObject를 request의 client의 global object로 설정합니다.
-
globalObject가
ServiceWorkerGlobalScope객체라면, request의 service-workers mode를 "none"으로 설정합니다. -
responseObject를 null로 설정합니다.
-
relevantRealm을 this의 relevant realm으로 설정합니다.
-
locallyAborted를 false로 설정합니다.
이렇게 하면 fetch를 호출한 동일한 스레드에서 abort 요청이 들어올 때 promise를 예측 가능한 타이밍으로 reject할 수 있습니다.
-
controller를 null로 설정합니다.
-
다음 abort 단계를 추가합니다. requestObject의 signal에:
-
locallyAborted를 true로 설정합니다.
-
Assert: controller는 null이 아닙니다.
-
Abort controller를 requestObject의 signal의 abort reason과 함께 중단합니다.
-
fetch() 호출을 중단합니다. p, request, responseObject, 그리고 requestObject의 signal의 abort reason을 사용합니다.
-
-
controller를 fetch를 호출한 결과로 설정합니다. request와 processResponse를 인자로 하며, response가 다음 단계일 때:
-
locallyAborted가 true면, 이 단계들을 중단합니다.
-
response의 aborted flag가 설정되어 있으면, 다음을 수행합니다:
-
deserializedError를 serialize된 abort reason을 역직렬화한 결과로 설정합니다. controller의 serialized abort reason과 relevantRealm을 인자로 합니다.
-
fetch() 호출을 중단합니다. p, request, responseObject, deserializedError를 인자로 합니다.
-
이 단계들을 중단합니다.
-
-
response가 network error이면 reject p에
TypeError를 넘기고 이 단계들을 중단합니다. -
responseObject를 creating
Response객체의 결과로 설정합니다. response, "immutable", relevantRealm을 인자로 합니다. -
Resolve p를 responseObject로 완료합니다.
-
-
p를 반환합니다.
fetch() 호출을 중단하기
promise, request, responseObject, error를 받아 다음을 수행한다:
FetchLaterResult
객체는 activated getter 단계를 가지며,
이는 boolean을 반환하는 알고리즘이다.
activated getter 단계는
this의
activated getter 단계의 결과를 반환하는 것입니다.
fetchLater(input, init)
메서드 단계는 다음과 같습니다:
-
requestObject를
Request생성자를 input과 init 인수로 호출한 결과로 설정한다. -
requestObject의 signal이 aborted라면, signal의 abort reason을 throw 한다.
-
request를 requestObject의 request로 설정한다.
-
activateAfter를 null로 설정한다.
-
init이 주어지고 init["
activateAfter"] 존재하는 경우, activateAfter를 init["activateAfter"]로 설정한다. -
activateAfter가 0보다 작으면
RangeError를 throw 한다. -
this의 relevant global object의 associated document가 fully active가 아니라면
TypeError를 throw 한다. -
request의 URL의 scheme이 HTTP(S) scheme이 아니라면
TypeError를 throw 한다. -
request의 URL이 potentially trustworthy URL이 아니라면,
TypeError를 throw 한다. -
request의 body가 null이 아니고, request의 body의 length가 null이라면,
TypeError를 throw 한다.body가
ReadableStream객체이면 deferred될 수 없다. -
quota를 available deferred-fetch quota로 설정한다. request의 client와 request의 URL의 origin을 기준으로 한다.
-
requested를 request의 total request length로 설정한다.
-
quota가 requested보다 작으면 throw한다.
QuotaExceededErrorquota는 quota이고 requested는 requested이다. -
activated를 false로 설정한다.
-
deferredRecord를 queue a deferred fetch를 request, activateAfter 및 다음 단계를 인수로 하여 호출한 결과로 설정한다: activated를 true로 설정한다.
-
다음 abort 단계를 requestObject의 signal에 추가한다: deferredRecord의 invoke state를 "
aborted"로 설정한다. -
새
FetchLaterResult객체를 반환한다. activated getter steps는 activated를 반환한다.
다음 호출은 문서가 종료될 때 가져올 요청을 큐에 추가합니다:
fetchLater( "https://report.example.com" , {
method: "POST" ,
body: JSON. stringify( myReport),
headers: { "Content-Type" : "application/json" }
})
다음 호출은 5초 후에도 이 요청을 큐에 추가하며, 반환된 값으로 호출자가 실제로 활성화되었는지 관찰할 수 있습니다. 사용자 에이전트가 타이머를 제한하는 경우에도 요청은 반드시 호출됩니다.
const result = fetchLater( "https://report.example.com" , {
method: "POST" ,
body: JSON. stringify( myReport),
headers: { "Content-Type" : "application/json" },
activateAfter: 5000
});
function check_if_fetched() {
return result. activated;
}
FetchLaterResult
객체는 AbortSignal
과 함께 사용할 수 있습니다. 예시:
let accumulated_events = [];
let previous_result = null ;
const abort_signal = new AbortSignal();
function accumulate_event( event) {
if ( previous_result) {
if ( previous_result. activated) {
// 요청이 이미 활성화되었으므로, 새롭게 시작할 수 있습니다.
accumulated_events = [];
} else {
// 이 요청을 중단하고, 모든 이벤트로 새로운 요청을 시작합니다.
signal. abort();
}
}
accumulated_events. push( event);
result = fetchLater( "https://report.example.com" , {
method: "POST" ,
body: JSON. stringify( accumulated_events),
headers: { "Content-Type" : "application/json" },
activateAfter: 5000 ,
abort_signal
});
}
다음 fetchLater() 호출은 모두 예외를 발생시킵니다:
// 오직 신뢰할 수 있는 URL 만 지원됩니다.
fetchLater( "http://untrusted.example.com" );
// 지연된 요청의 길이는 반드시 미리 알아야 합니다.
fetchLater( "https://origin.example.com" , { body: someDynamicStream});
// 지연된 fetch는 활성 윈도우에서만 동작합니다.
const detachedWindow = iframe. contentWindow;
iframe. remove();
detachedWindow. fetchLater( "https://origin.example.com" );
지연 fetch 할당량 예시를 참고하면 지연 fetch 할당량이 어떻게 동작하는지 알 수 있습니다.
5.7. 가비지 컬렉션
사용자 에이전트는 종료가 스크립트로 관찰될 수 없는 경우 진행 중인 fetch를 종료할 수 있습니다.
"스크립트로 관찰 가능"하다는 것은 fetch()의 인자와 반환값을 통해 관찰할 수 있다는
의미입니다. 서버와의 사이드 채널 통신과 같은 다른 방식은 포함되지 않습니다.
서버가 가비지 컬렉션을 관찰할 수 있는 사례는 WebSocket
및 XMLHttpRequest
객체에서 이미 존재합니다.
사용자 에이전트는 종료가 관찰될 수 없으므로 fetch를 종료할 수 있습니다.
fetch( "https://www.example.com/" )
사용자 에이전트는 종료가 promise를 통해 관찰될 수 있으므로 fetch를 종료할 수 없습니다.
window. promise = fetch( "https://www.example.com/" )
연관된 body가 관찰될 수 없으므로 사용자 에이전트가 fetch를 종료할 수 있습니다.
window. promise = fetch( "https://www.example.com/" ). then( res => res. headers)
종료가 관찰될 수 없으므로 사용자 에이전트가 fetch를 종료할 수 있습니다.
fetch( "https://www.example.com/" ). then( res => res. body. getReader(). closed)
promise 객체에 핸들러를 등록하여 종료를 관찰할 수 있으므로 사용자 에이전트가 fetch를 종료할 수 없습니다.
window. promise = fetch( "https://www.example.com/" )
. then( res => res. body. getReader(). closed)
핸들러 등록을 통해 종료가 관찰될 수 있으므로 사용자 에이전트가 fetch를 종료할 수 없습니다.
fetch( "https://www.example.com/" )
. then( res => {
res. body. getReader(). closed. then(() => console. log( "stream closed!" ))
})
(위의 비관찰성 예시는 body.getReader()
등 내장 속성과 함수가 덮어써지지 않았다고 가정합니다.)
6. data: URL
data: URL에 대한 설명은 RFC 2397을 참고하십시오. 이 절은 배포된 컨텐츠와의 호환을 위해 해당 RFC의 표준 처리 요구사항을 대체합니다. [RFC2397]
data: URL
구조체는 구조체이며,
MIME 타입 (MIME type)과
본문 (바이트 시퀀스)를 포함합니다.
data:
URL 처리기는 URL
dataURL을 받아 아래 절차를 실행합니다:
-
input을 URL serializer를 dataURL에 대해 exclude fragment 옵션을 true로 하여 실행한 결과로 둡니다.
-
input에서 맨 앞의 "
data:"를 제거합니다. -
position을 input의 시작 위치로 지정합니다.
-
mimeType을, U+002C(,)이 아닌 코드포인트 시퀀스를 수집하여 position 기준으로 얻습니다.
-
선행/후행 ASCII 공백을 mimeType에서 제거합니다.
이것은 U+0020(SPACE) 코드포인트만 제거합니다.
-
position이 input의 끝을 지난 위치라면, 실패를 반환합니다.
-
position을 1만큼 증가시킵니다.
-
encodedBody를 input의 나머지로 둡니다.
-
body를 percent-decoding을 encodedBody에 대해 실행한 결과로 둡니다.
-
mimeType이 U+003B(;)로 끝나고, 그 뒤에 0개 이상의 U+0020(SPACE), 그 뒤에 "
base64"와 ASCII 대소문자 구분 없이 일치한다면:-
stringBody를 isomorphic decode를 body에 대해 실행한 결과로 둡니다.
-
body를 forgiving-base64 decode를 stringBody에 대해 실행한 결과로 갱신합니다.
-
body가 실패라면 실패를 반환합니다.
-
mimeType의 마지막 6 코드포인트를 제거합니다.
-
후행 U+0020(SPACE) 코드포인트를 mimeType에서 제거합니다.
-
mimeType의 마지막 U+003B(;)도 제거합니다.
-
-
mimeType이 "
;"로 시작하면, mimeType 앞에 "text/plain"을 붙입니다. -
mimeTypeRecord를 MIME 타입 파싱을 mimeType에 대해 수행한 결과로 둡니다.
-
mimeTypeRecord가 실패라면, mimeTypeRecord를
text/plain;charset=US-ASCII로 둡니다. -
아래 필드로 새
data:URL 구조체를 반환합니다: MIME 타입은 mimeTypeRecord, 본문은 body입니다.
배경 읽기
이 섹션과 하위 섹션들은 참고용입니다.
HTTP 헤더 레이어 구분
fetch 관점에서 API 레이어(HTML의 img, CSS의 background-image), 초기 fetch 레이어, 서비스 워커 레이어,
네트워크 & 캐시 레이어가 있습니다. `Accept` 및 `Accept-Language`는 초기 fetch 레이어(일반적으로 사용자
에이전트에 의해)에서 설정됩니다. 대부분의 사용자 에이전트가 제어하는 다른 헤더들, 예를 들어 `Accept-Encoding`, `Host`,
`Referer`는 네트워크 & 캐시 레이어에서 설정됩니다. 개발자는 API 레이어 또는 서비스 워커 레이어(일반적으로 Request 객체를 통해)에서
헤더를 설정할 수 있습니다. 개발자는 금지된 요청 헤더에 거의 접근할 수 없으나, `Accept`는 제어할 수 있고,
`Referer`는 제한하거나 생략할 수 있는 수단이 있습니다.
원자적 HTTP 리다이렉트 처리
리다이렉트(즉, response의 status 또는 internal response의(있는 경우) status가 리다이렉트 상태인 경우)는 API에 노출되지 않는다. 리다이렉트를 노출하면 교차 사이트 스크립팅 공격으로는 얻을 수 없는 정보를 누설할 수 있다.
https://example.org/auth로 fetch할 때 HttpOnly로
표시된 Cookie가 포함되면 https://other-origin.invalid/4af955781ea1c84a3b11로 리다이렉트될 수 있습니다.
이 새로운 URL에는 비밀이 포함되어 있습니다. 리다이렉트를 노출하면 해당 비밀이 교차 사이트 스크립팅 공격을 통해 얻어질 수 있습니다.
기본 안전 CORS 프로토콜 설정
IP 인증 또는 방화벽을 통해 데이터가 보호되는 리소스(아직도 꽤 흔함)의 경우 CORS 프로토콜을 사용하는 것은 안전하지 않습니다. (이 때문에 CORS 프로토콜이 만들어졌습니다.)
그러나, 다음 헤더를 사용하는 것은 안전합니다:
Access-Control-Allow-Origin: *
리소스가 추가 정보를 쿠키나 HTTP 인증에 따라 노출한다 해도, 위 헤더를 사용하면 그 정보를 노출하지 않습니다. API(XMLHttpRequest
등)와 마찬가지로 curl, wget에도 동일하게 공유됩니다.
즉, curl이나 wget으로 웹에 연결된 임의의 장치에서 리소스에 접근할 수 없다면 위 헤더를 포함하지 않아야 합니다. 그러나 접근 가능하다면 포함해도 괜찮습니다.
CORS 프로토콜과 HTTP 캐시
CORS 프로토콜 요구사항이 `Access-Control-Allow-Origin`을
* 또는 정적 origin으로 설정하는 것보다 더 복잡하다면, `Vary`를 사용해야 합니다.
[HTML] [HTTP] [HTTP-CACHING]
Vary: Origin
특히, 서버가 특정 리소스에 대해 Access-Control-Allow-Origin을 CORS 요청에만
응답하도록 구성되고, `Vary`가 사용되지 않는다면을 고려해보세요. 사용자 에이전트가 해당 리소스에 대해 비-CORS 요청(예: navigation 요청의
결과)으로 응답을 받으면, 응답에 `Access-Control-Allow-Origin`이 없고 해당 응답을
캐시합니다. 이후 CORS 요청이 오면 해당 비-CORS 요청에서 캐시된 응답을 사용하고, `Access-Control-Allow-Origin`이 없습니다.
그러나 동일 시나리오에서 `Vary: Origin`을 사용하면 사용자 에이전트가 `Access-Control-Allow-Origin`이 포함된 응답을
fetch하게 되며, 비-CORS 요청에서 캐시된 응답(헤더 없음)은 사용하지 않습니다.
반면, 특정 리소스에 대해 `Access-Control-Allow-Origin`을
* 또는 정적 origin으로 설정했다면, 서버를 항상 해당 리소스 응답에 `Access-Control-Allow-Origin`을 포함하도록
구성하고 비-CORS 요청 및 CORS 요청 모두에 대해 보내야 하며, `Vary`는 사용하지 않아야 합니다.
웹소켓(WebSockets)
연결을 설정하는 과정에서 WebSocket
객체는 특별한 종류의
fetch를 시작한다(여기서 request의 mode가
"websocket"임). 이를 통해 많은 fetch 정책 결정(예: HTTP Strict Transport Security (HSTS))을 공유할
수 있다. 궁극적으로 fetch는 WebSockets에 호출되어 전용 연결을 획득하게 된다. [WEBSOCKETS]
[HSTS]
과거에는 Fetch에서 WebSocket 연결 획득하기와 WebSocket 연결 설정하기를 직접 정의했으나, 현재는 둘 다 WebSockets에서 정의된다. [WEBSOCKETS]
다른 표준에서 fetch 사용하기
본질적으로 fetch란 request와 response의 교환이다. 실제로는 표준에서 올바르게 도입하고 사용하기에 다소 복잡한 메커니즘이다. 이 절에서는 이에 대한 조언을 제공한다.
항상 도메인 전문가의 리뷰를 요청하세요.
작업 진행 중입니다.
request 설정하기
패칭의 첫 단계는 리퀘스트(request)를 생성하고 그 항목들을 채우는 것이다.
먼저, request의 URL과 method를
HTTP 정의에 따라 설정한다. 만약 `POST` 또는 `PUT` request가
바디가 필요하다면, request의
body를 바이트 배열(byte sequence)이나
body의 stream이
생성한 ReadableStream인
새 body로 설정한다. [HTTP]
request의 destination은
destination table의 지침을 따라 선택한다. Destinations는
Content Security Policy에 영향을 미치며,
`Sec-Fetch-Dest`
헤더 등 실질적인 효과가 있으니 단순한 메타데이터가 아니다. 만약 새 기능에 destination이 필요하고
destination table에 없다면,
이슈를
제기하여 논의하자. [CSP]
request의 client는
현재 동작 중인
environment settings object로 설정한다.
Web에 노출된 API들은 보통 Web IDL로 정의되어 있고,
Web IDL 인터페이스를 구현하는 모든 객체는
relevant settings object가 존재한다. 예를 들어,
어떤 request가
엘리먼트에 연결되어 있다면,
request의 client는
해당 엘리먼트의 node document의 relevant settings object여야 한다.
JavaScript, HTML, CSS 또는 다른 Document
서브리소스에서 직접적으로 웹에 노출된 기능들은 반드시
client가
존재해야 한다.
만약 fetch가 웹에 직접 노출되지 않는 경우,
즉,
현재 Window나
Worker에
의존하지 않고 백그라운드로 전송된다면,
request의
client는
null로 두고,
request의 origin,
policy container, service-workers
mode, 그리고
referrer는 알맞은 값으로 직접 설정해야 한다. 예컨대,
미리 environment settings object에서 복사한다. 이런 복잡한 경우에는
Content Security Policy나 referrer policy를 어떻게 처리할지 반드시 자세히 정의해야 한다. 또한
콜백( Invoking fetch and processing responses 참고 )이
parallel queue로 포스트되므로 동시성도 신경써야 한다.
[REFERRER] [CSP]
크로스 오리진 리소스를 어떻게 처리할지 미리 신중히 생각하라. 어떤 기능들은 동일
출처 내에서만 동작할 수 있다. 이 경우 request의 mode를
"same-origin"으로 설정하라. 그 외의 경우, 새로운 웹 노출 기능들은 거의 항상
mode를
"cors"로 설정해야 한다. 기능이 웹에 노출되지 않거나,
또는 CORS 없이 크로스 오리진 리소스를 패칭해야 할 특별한 사유가 있다면,
이슈를 제출
해서 논의하라.
크로스 오리진 요청이라면 credentials를 포함할지
여부도 결정해야 하며,
포함해야 한다면 request의 credentials
mode를
"include"로 설정하라.
패치가 Resource Timing에 보고되어야 하는지, 만약 그렇다면 어떤 initiator type이 쓰이는지 결정하라. initiator type을 request에 넘기면, fetch가 끝나고 response가 모두 내려받아졌을 때 Resource Timing에 자동 보고된다. [RESOURCE-TIMING]
요청에 추가적인 HTTP 헤더가 필요하다면, header list를
해당 헤더들을 포함한 header
list로 두어라.
예컨대 « (`My-Header-Name`, `My-Header-Value`) » 처럼.
커스텀 헤더 전송은 CORS-preflight fetch가 필요할 수 있으니 주의가 필요하다.
기본 캐싱 동작을 오버라이드하고 싶다면,
예를 들어 이 request에 대해 캐싱을
비활성화하려면,
request의 cache mode를 "default" 이외의 값으로 설정하라.
리퀘스트가 리다이렉트를 지원해야 하는지도 결정하라. 그렇지 않으면
redirect mode에 "error"를 설정하라.
request의 나머지 파라미터들도 참고해서 필요한 게 있는지 확인하라. 이런 파라미터들은 덜 자주 쓰이며, 특별한 목적에 사용되는 경우가 많으며, 이 표준의 § 2.2.5 Requests에 상세 문서가 있다.
fetch 호출 및 응답 처리
request 외에도 fetch 연산은 여러 가지 선택적 인자를 받을 수 있습니다. 알고리즘을 받는 인자의 경우: 해당 알고리즘은 태스크(또는 병렬 큐(parallel queue), useParallelQueue가 true라면)에서 호출됩니다.
request가 준비되면, fetch에 어떤 알고리즘을 넘기는 게 좋을지, 즉 response를 어떻게 처리하고 어느 시점에 콜백을 받을지 결정하면 됩니다:
- 완료 시점 콜백(Upon completion)
-
대부분의 호출자는 response를 이 방식으로 처리합니다. 예를 들어 스크립트나 스타일 리소스 등입니다. response의 body를 전체 읽어서 byte sequence로 전달하고, 그 뒤 호출자가 처리합니다.
response를 완료 시점에 처리하려면, fetch의 processResponseConsumeBody 인자로 알고리즘을 전달하면 됩니다. 이 알고리즘은 response와, 완전히 읽은 body를 나타내는 두 번째 인자를 받습니다. 두 번째 인자는 다음 의미를 가집니다:
- null
- response의 body가 null임을 뜻하며, 이는 네트워크 에러(network error)이거나 null body status인 경우입니다.
- failure
- response의 body 전체를 읽으려다 실패한 경우입니다. (예: I/O 에러)
- byte sequence
-
response의 internal response의 body 전체를 성공적으로 읽은 경우.
"
no-cors" request의 경우에도 전체 byte sequence가 넘겨질 수 있습니다. 이 때 요청 origin에서는 내용 접근이 보장되지 않으므로 직접 노출을 피해야 합니다. 예를 들어 "no-cors" response로 이미지를 표시할 수는 있으나, 임베딩된 문서의 스크립트에 이미지 내용을 직접 노출해서는 안 됩니다.
-
request를 생성한다. request의 URL은
https://stuff.example.com/이고, client는 this의 relevant settings object로 설정. -
Fetch request를 실행한다. processResponseConsumeBody를 다음 단계로 설정하고, 인자로 response response와 null 또는 failure 혹은 byte sequence contents을 넘긴다:
-
contents가 null 또는 failure이면 오류를 사용자에게 보여준다.
-
그 외에는 response의 메타데이터를 참고해 contents를 파싱하고 원하는 작업을 수행한다.
-
- 헤더 도착 후, 조각 단위로(chunk-by-chunk)
-
비디오 재생, 이미지 점진적 로딩 등에서는 응답을 스트리밍하여 한 번에 한 조각씩 처리하고 싶은 경우가 있을 수 있습니다. 이 경우 response는 헤더가 처리되자마자 호출자에게 넘기고 이후 호출자가 스트림을 직접 처리합니다.
조각 단위로 response를 처리하려면, fetch의 processResponse에 알고리즘을 전달하세요. 전달된 알고리즘은 응답의 헤더가 수신되었을 시 response를 인자로 받아, response의 body의 stream을 직접 읽어야 합니다. 편의를 위해, processResponseEndOfBody에도 알고리즘을 전달할 수 있습니다. 이 알고리즘은 전체 응답 바디를 다 읽었을 때 호출됩니다. processResponseConsumeBody와는 달리 processResponse 또는 processResponseEndOfBody에 알고리즘을 넘긴다고 해서 반드시 응답 전체가 읽힌다는 보장은 없으니, 호출자가 직접 읽어야 합니다.
processResponse 인자는 response의 header list와 status 만을 처리하고 body는 처리하지 않는 시나리오에도 유용합니다. 대표적 예시로 ok status가 아닌 응답 처리 등이 있습니다.
-
request를 생성한다. request의 URL은
https://stream.example.com/이고, client는 this의 relevant settings object로 설정. -
Fetch request를 실행한다. processResponse에 아래 단계를 넘긴다. 이 알고리즘은 response response를 인자로 받는다:
-
response가 network error면 사용자에게 오류를 표시한다.
-
그 외에는 get a reader로 response의 body stream을 읽고, extracting a MIME type을 통해 response의 headers list에서 MIME 타입을 찾아서 알맞게 처리한다.
-
-
- 응답 무시(Ignore the response)
-
어떤 경우에는 response 자체가 필요 없을 수 있습니다. 예를 들어
navigator.sendBeacon()등이 그렇습니다. fetch에서 응답 콜백은 선택 사항이므로 넘기지 않으면 fetch는 응답을 기대하지 않습니다. 이때 response의 body의 stream은 버려지며, 호출자는 불필요한 다운로드 걱정을 하지 않아도 됩니다.Fetch a request whose URL is
https://fire-and-forget.example.com/, method가 `POST`, client는 this의 relevant settings object인 요청을 예로 들 수 있습니다.
응답 처리용 콜백 외에도 fetch는 고급 기능용 콜백도 더 받을 수 있습니다. processEarlyHintsResponse는 상태 코드가 103인 response에 특별히 쓰이며 현재는 네비게이션에서만 사용됩니다. processRequestBodyChunkLength와 processRequestEndOfBody는 요청 바디 업로드 진행 상황을 호출자에게 알려줍니다.
fetch 연산은 호출한 스레드에서 시작되어, 내부 작업을 병렬로 진행합니다. 위에서 언급한 콜백들은 기본적으로 주어진 이벤트 루프 (기본값은 client의 global object)에 포스트됩니다. 응답을 직접 병렬로 처리하고 메인 스레드와의 상호 작용을 직접 제어하고 싶으면, fetch를 useParallelQueue를 true로 두어 사용하세요.
진행 중인 fetch 조작하기
이미 시작된 fetch 연산을 조작하려면, fetch controller를 사용한다. fetch controller는 fetch 호출 시 반환된다. 예를 들어, 사용자의 동작이나 페이지 로직에 따라 abort를, 브라우저 내부 사정에 따라 terminate를 실행할 수 있다.
종료 및 중단 외에도, 호출자는 타이밍 보고(initiator type을 전달하지 않은 경우)나 전체 타이밍 정보 추출도 할 수 있다(이 기능은
네비게이션에서만 사용됨). fetch
controller는 또한 request의 redirect mode가
"manual"일 때 다음 수동 리다이렉트 처리에도 사용된다.
감사의 글
감사합니다: Adam Barth, Adam Lavin, Alan Jeffrey, Alexey Proskuryakov, Andreas Kling, Andrés Gutiérrez, Andrew Sutherland, Andrew Williams, Ángel González, Anssi Kostiainen, Arkadiusz Michalski, Arne Johannessen, Artem Skoretskiy, Arthur Barstow, Arthur Sonzogni, Asanka Herath, Axel Rauschmayer, Ben Kelly, Benjamin Gruenbaum, Benjamin Hawkes-Lewis, Benjamin VanderSloot, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Bryan Smith, Caitlin Potter, Cameron McCormack, Carlo Cannas, 白丞祐 (Cheng-You Bai), Chirag S Kumar, Chris Needham, Chris Rebert, Clement Pellerin, Collin Jackson, Daniel Robertson, Daniel Veditz, Dave Tapuska, David Benjamin, David Håsäther, David Orchard, Dean Jackson, Devdatta Akhawe, Domenic Denicola, Dominic Farolino, Dominique Hazaël-Massieux, Doug Turner, Douglas Creager, Eero Häkkinen, Ehsan Akhgari, Emily Stark, Eric Lawrence, Eric Orth, Feng Yu, François Marier, Frank Ellerman, Frederick Hirsch, Frederik Braun, Gary Blackwood, Gavin Carothers, Glenn Maynard, Graham Klyne, Gregory Terzian, Guohui Deng(邓国辉), Hal Lockhart, Hallvord R. M. Steen, Harris Hancock, Henri Sivonen, Henry Story, Hiroshige Hayashizaki, Honza Bambas, Ian Hickson, Ilya Grigorik, isonmad, Jake Archibald, James Graham, Jamie Mansfield, Janusz Majnert, Jeena Lee, Jeff Carpenter, Jeff Hodges, Jeffrey Yasskin, Jensen Chappell, Jeremy Roman, Jesse M. Heines, Jianjun Chen, Jinho Bang, Jochen Eisinger, John Wilander, Jonas Sicking, Jonathan Kingston, Jonathan Watt, 최종찬 (Jongchan Choi), Jordan Stephens, Jörn Zaefferer, Joseph Pecoraro, Josh Matthews, jub0bs, Julian Krispel-Samsel, Julian Reschke, 송정기 (Jungkee Song), Jussi Kalliokoski, Jxck, Kagami Sascha Rosylight, Keita Suzuki, Keith Yeung, Kenji Baheux, Lachlan Hunt, Larry Masinter, Liam Brummitt, Linus Groh, Louis Ryan, Luca Casonato, Lucas Gonze, Łukasz Anforowicz, 呂康豪 (Kang-Hao Lu), Maciej Stachowiak, Malisa, Manfred Stock, Manish Goregaokar, Marc Silbey, Marcos Caceres, Marijn Kruisselbrink, Mark Nottingham, Mark S. Miller, Martin Dürst, Martin O’Neal, Martin Thomson, Matt Andrews, Matt Falkenhagen, Matt Menke, Matt Oshry, Matt Seddon, Matt Womer, Mhano Harkness, Michael Ficarra, Michael Kohler, Michael™ Smith, Mike Pennisi, Mike West, Mohamed Zergaoui, Mohammed Zubair Ahmed, Moritz Kneilmann, Ms2ger, Nico Schlömer, Nicolás Peña Moreno, Nidhi Jaju, Nikhil Marathe, Nikki Bee, Nikunj Mehta, Noam Rosenthal, Odin Hørthe Omdal, Olli Pettay, Ondřej Žára, O. Opsec, Patrick Meenan, Perry Jiang, Philip Jägenstedt, R. Auburn, Raphael Kubo da Costa, Robert Linder, Rondinelly, Rory Hewitt, Ross A. Baker, Ryan Sleevi, Sam Atkins, Samy Kamkar, Sébastien Cevey, Sendil Kumar N, Shao-xuan Kang, Sharath Udupa, Shivakumar Jagalur Matt, Shivani Sharma, Sigbjørn Finne, Simon Pieters, Simon Sapin, Simon Wülker, Srirama Chandra Sekhar Mogali, Stephan Paul, Steven Salat, Sunava Dutta, Surya Ismail, Tab Atkins-Bittner, Takashi Toyoshima, 吉野剛史 (Takeshi Yoshino), Thomas Roessler, Thomas Steiner, Thomas Wisniewski, Tiancheng "Timothy" Gu, Tobie Langel, Tom Schuster, Tomás Aparicio, triple-underscore, 保呂毅 (Tsuyoshi Horo), Tyler Close, Ujjwal Sharma, Vignesh Shanmugam, Vladimir Dzhuvinov, Wayne Carr, Xabier Rodríguez, Yehuda Katz, Yoav Weiss, Yoshisato Yanagisawa, Youenn Fablet, Yoichi Osato, 평野裕 (Yutaka Hirano), 그리고 Zhenbin Xu 모두에게 감사드립니다.
이 표준은 Anne van Kesteren (Apple, annevk@annevk.nl)가 작성했습니다.
지적 재산권
Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 이 문서는 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스로 제공됩니다. 일부가 소스 코드에 포함되는 경우, 해당 소스 코드 부분은 BSD 3-Clause License로 제공됩니다.
이 문서는 현행 표준입니다. 특허 검토 버전에 관심 있으신 분들은 현행 표준 검토 초안을 참조하세요.