목표
이 표준의 목표는 웹 플랫폼 전반에 걸쳐 패칭을 통합하고, 이에 관련된 모든 것에 대해 일관된 처리를 제공하는 것입니다. 여기에는 다음이 포함됩니다:
- 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의 용어를 사용합니다. [ABNF] [ENCODING] [HTML] [HTTP] [MIMESNIFF] [STREAMS] [URL] [WEBIDL] [WEBSOCKETS]
ABNF는 HTTP에서 확장된 ABNF(특히
#
의 추가)와 RFC 7405를 의미합니다. [RFC7405]
인증 정보(Credentials)는 HTTP 쿠키, TLS 클라이언트 인증서, 그리고 인증 항목(HTTP 인증용)입니다. [COOKIES] [TLS] [HTTP]
fetch params는 struct로, fetch 알고리즘에서 부기 용도로 사용됩니다. 다음과 같은 항목을 가집니다:
- request
- request.
- process request body chunk length
(기본값 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.
- 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으로 큐잉합니다.
정수 직렬화(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
` 헤더용).
문서
`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까지(포함)의 상태입니다.
리다이렉트 상태(redirect status)는 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 ,
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를 덮어쓸 때 사용될 수 있습니다.
요청은 연관된
mode를 가집니다. 값은
"same-origin
", "cors
", "no-cors
",
"navigate
", 또는 "websocket
"입니다. 별도의 언급이 없으면 "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)을 설정할 때만 사용되는 특수 모드입니다.
기본 요청의 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의 render-blocking 메커니즘에서만 사용된다. [HTML]
요청은 연관된 URL 목록(URL list)을 가진다. (리스트이며, 하나 이상의 URL을 포함) 별도 언급이 없으면 요청의 URL을 복사해 리스트로 만든다.
요청은 연관된 current URL을 가진다. 이는 URL 리스트의 마지막 항목을 가리킨다.
요청은 연관된 redirect count 를 가진다. 별도 언급이 없으면 0이다.
요청은
연관된
response tainting
을 가진다. 값은 "basic
", "cors
", "opaque
" 중 하나이며, 별도 언급이 없으면
"basic
"이다.
요청은 연관된 prevent no-cache cache-control header modification flag 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
요청은 연관된 done flag 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
요청은 연관된 timing allow failed flag를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.
요청의 URL 목록, current URL, redirect count, response tainting, done flag, timing allow failed flag는 fetch 알고리즘에서 부가적인 부기용으로 사용된다.
서브리소스 요청(subresource
request)
은 요청 중
destination이 "audio
",
"audioworklet
",
"font
", "image
", "json
", "manifest
",
"paintworklet
", "script
", "style
", "track
",
"video
", "xslt
", 또는 빈 문자열일 때를 말한다.
비-서브리소스
요청(non-subresource request)
은 요청 중
destination이 "document
",
"embed
",
"frame
", "iframe
", "object
", "report
",
"serviceworker
", "sharedworker
", "worker
" 중 하나일 때를 말한다.
탐색 요청(navigation
request)
은 요청 중
destination이
"document
", "embed
", "frame
", "iframe
",
"object
" 중 하나인 경우를 말한다.
이 용어들의 사용은 handle fetch를 참고하라. [SW]
redirect-taint를
request
request에 대해 계산하려면 다음 단계를 따른다. 반환값은 "same-origin
", "same-site
",
"cross-site
" 중 하나이다.
-
lastURL을 null로 둔다.
-
taint를 "
same-origin
"으로 둔다. -
-
lastURL이 null이면 lastURL을 url로 설정하고 continue한다.
-
url의 origin이 lastURL의 origin과 same site가 아니고, request의 origin이 lastURL의 origin과 same site가 아니면, "
cross-site
"를 반환한다. -
url의 origin이 lastURL의 origin과 same origin이 아니고, request의 origin이 lastURL의 origin과 same origin이 아니면, taint를 "
same-site
"로 설정한다. -
lastURL을 url로 설정한다.
-
-
taint를 반환한다.
요청 origin 직렬화(Serializing a request origin)는 request request가 주어졌을 때 다음을 실행한다:
-
request의 redirect-taint가 "
same-origin
"이 아니면, "null
"을 반환한다.
요청 origin 바이트 직렬화(Byte-serializing a request origin)는 request request가 주어졌을 때, 요청 origin 직렬화의 결과를 등가 인코딩(isomorphic encoded)하여 반환한다.
복제(clone)를 request request에 대해 실행하려면 다음을 따른다:
range 헤더 추가(add a range header)를 request request에, 정수 first와 옵션 정수 last와 함께 하려면 다음을 따른다:
-
Assert: last가 주어졌다면, first가 last 이하임을 확인한다.
-
rangeValue를 `
bytes=
`로 둔다. -
0x2D (-)를 rangeValue에 추가한다.
-
헤더 append(`
Range
`, rangeValue)를 request의 header list에 추가한다.
range 헤더는 양끝 포함 바이트 범위를 나타낸다. 즉, first가 0이고 last가 500이면 501 바이트 범위다.
여러 응답을 하나의 논리 리소스로 결합하는 기능은 역사적으로 보안 버그의 원인이었다. 부분 응답을 다루는 기능을 설계할 때는 반드시 보안 리뷰를 받을 것.
보고용 응답 URL 직렬화(serialize a response URL for reporting)는 response response에 대해 다음을 실행한다:
-
url을 response의 URL list[0]의 복사본으로 둔다.
이는 response의 URL이 아니다. 리다이렉트 대상 정보 노출을 피하기 위함(이와 유사한 CSP 보고에 대한 고려도 참고). [CSP]
-
username 설정을 url과 빈 문자열로 실행한다.
-
password 설정을 url과 빈 문자열로 실행한다.
-
직렬화(serialization)를 url에 대해(단, fragment 제외 옵션 포함) 반환한다.
Cross-Origin-Embedder-Policy가 credentials를 허용하는지 확인하려면, request request가 주어졌을 때 다음을 실행한다:
-
request의 mode가 "
no-cors
"가 아니면 true를 반환한다. -
request의 client가 null이면 true를 반환한다.
-
request의 client의 policy container의 embedder policy의 value가 "
credentialless
"가 아니면 true를 반환한다. -
request의 origin이 request의 current URL의 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
")를 가진다. 별도 언급이 없으면 빈 문자열이다.
이 값은 서비스 워커와 리소스 타이밍에서 사용하기 위한 것이다. [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 그룹(fetch group)을 가지며, fetch group을 보유한다.
fetch group은 fetch에 대한 정보를 보유한다.
fetch group은 연관된 정보를 가진다:
- fetch 레코드(fetch records)
- 리스트(list)이며, fetch record를 포함한다.
- 지연 fetch 레코드(deferred fetch records)
- 리스트(list)이며, deferred fetch record를 포함한다.
fetch record는 struct이며, 다음 항목(items)을 가진다:
- request
- request.
- controller
- fetch controller 또는 null.
deferred fetch record는 struct이며, 나중에 fetch를 실행하는 데 필요한 상태를 저장하는데 사용된다(예: 문서가 언로드되거나 fully active가 아니게 될 때 등). 다음 항목(items)을 가진다:
- request
- request.
- notify invoked
- 인자를 받지 않는 알고리즘.
- invoke state (기본값 "
pending
") - "
pending
", "sent
", "aborted
" 중 하나.
fetch group fetchGroup이 종료된 경우:
-
각 fetch record record가 fetchGroup의 fetch records에 있다면, record의 controller가 null이 아니고, record의 request의 done flag가 unset이고, 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) 알고리즘은
네트워크 파티션 키
key, URL url,
불리언 credentials, 옵션 new connection setting new (기본값
"no
"),
옵션 불리언 requireUnreliable (기본값 false)로 호출한다:
-
new가 "
no
"면:-
connections를 연결 풀에서 key가 key, origin이 url의 origin, credentials가 credentials인 connection 집합으로 한다.
-
connections가 비어 있지 않고 requireUnreliable이 false면 그 중 하나를 반환한다.
-
connections 중에서 불안정 전송(unreliable transport, 예: HTTP/3)을 지원하는 connection이 있으면 그것을 반환한다.
-
-
proxies를 url에 대한 프록시를 구현 정의 방식으로 찾은 결과로 한다. 프록시가 없으면 proxies는 « "
DIRECT
" »가 된다.이 단계에서는 Web Proxy Auto-Discovery Protocol(WPAD)이나 proxy auto-config(PAC) 등 비표준 기술도 사용된다. "
DIRECT
" 값은 해당 url에 프록시를 사용하지 않음을 의미한다. -
timingInfo를 새로운 connection timing info로 둔다.
-
각 proxies의 proxy에 대해:
-
timingInfo의 domain lookup start time을 unsafe shared current time으로 설정한다.
-
proxy가 "
DIRECT
"면, hosts를 resolve an origin 알고리즘에 key와 url의 origin을 넘겨 얻은 결과로 설정한다. -
hosts가 failure면 continue한다.
-
timingInfo의 domain lookup end time을 unsafe shared current time으로 설정한다.
-
connection을 아래 단계로 얻는다: create a connection 알고리즘에 key, url의 origin, credentials, proxy, 구현 정의 host (from hosts), timingInfo, requireUnreliable를 넘겨서, 여러 번 병렬로 실행하고 하나 이상이 성공할 때까지 기다린다. 구현 정의 방식으로 반환값 하나를 선택해 반환한다. 나머지 connection들은 닫을 수 있다.
즉, 구현체는 IP 주소 여러 개를 pick & race 하거나, IPv6를 우선하거나, 타임아웃 시 재시도하는 등 다양한 전략을 쓸 수 있다.
-
connection이 failure면 continue한다.
-
new가 "
yes-and-dedicated
"가 아니면 append로 connection을 연결 풀에 추가한다. -
connection을 반환한다.
-
-
failure를 반환한다.
이 부분은 의도적으로 다소 모호하게 작성되어 있는데, 연결 관리에는 구현자 재량에 맡기는 것이 더 적합한 많은 미묘한 점들이 있기 때문이다.
이렇게 설명하는 것은 <link rel=preconnect>
기능을 설명하고, 연결이 인증 정보(credentials)를 기준으로 구분된다는 점을 명확히 하기 위함이다. 후자는
예를 들어, TLS 세션 식별자가 연결 중 인증 정보(credentials)가 false인 것과 연결 중 인증 정보(credentials)가 true인 것
사이에 재사용되지 않는다는 점을 명확히 한다.
연결 생성(create a connection) 알고리즘은 네트워크 파티션 키 key, origin origin, 불리언 credentials, 문자열 proxy, host host, connection timing info timingInfo, 불리언 requireUnreliable이 주어졌을 때 다음을 실행한다:
-
timingInfo의 connection start time을 unsafe shared current time으로 설정한다.
-
connection을 새 connection으로 만들고, key는 key, origin은 origin, credentials는 credentials, timing info는 timingInfo로 한다. record connection timing info를 connection에 대해 실행하고, connection을 이용해 host에 HTTP 연결을 수립한다(프록시, origin을 고려). 단, 아래 주의사항에 유의: [HTTP] [HTTP1] [TLS]
-
requireUnreliable가 true면 불안정 전송(예: HTTP/3) 가능한 연결만 수립한다. [HTTP3]
-
불안정 전송 연결을 수립할 때 WebTransport에 필요한 옵션을 활성화한다. HTTP/3의 경우, 초기
SETTINGS
프레임에SETTINGS_ENABLE_WEBTRANSPORT=1
,H3_DATAGRAM=1
을 포함한다. [WEBTRANSPORT-HTTP3] [HTTP3-DATAGRAM] -
credentials가 false면 TLS 클라이언트 인증서를 보내지 않는다.
-
연결 수립에 실패(예: UDP, TCP, TLS 오류)하면 failure를 반환한다.
-
-
timingInfo의 ALPN negotiated protocol을 connection의 ALPN Protocol ID로 설정한다. 단, 아래 주의사항에 유의: [RFC7301]
-
프록시를 사용할 경우, 터널 연결이 성립하면 해당 터널링 프로토콜의 ALPN Protocol ID로, 아니면 프록시까지의 첫 홉의 ALPN Protocol ID로 설정한다.
-
실험적·비공식 프로토콜을 쓰면, 실제 사용된 ALPN Protocol ID를 사용해야 한다. ALPN이 협상에 사용되지 않았다면 다른 설명 문자열을 써도 된다.
timingInfo의 ALPN negotiated protocol은 네트워크 프로토콜을 식별하기 위한 정보이며, ALPN이 협상에 쓰이지 않아도 실제 사용 프로토콜의 ALPN ID를 써야 한다.
ALPN Protocol ID 목록은 IANA에서 관리한다. ALPN Protocol IDs 참고.
-
-
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에 대해 실행한 결과로 둔다.
-
key가 null이면 null을 반환한다.
-
key와 연관된 고유한 HTTP 캐시를 반환한다. [HTTP-CACHING]
2.9. 포트 차단(Port blocking)
새로운 프로토콜은 ALPN을 사용해 TLS를 통해 프로토콜을 협상함으로써 포트 차단의 필요성을 피할 수 있다. 이 경우 HTTP 요청을 통해 프로토콜이 위조될 수 없다. [RFC7301]
request request에 대해 나쁜 포트(bad port)로 인해 차단되어야 하는지 여부를 결정하려면:
-
url을 request의 current URL로 둔다.
-
url의 scheme이 HTTP(S) scheme이고, 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를 same-site 모드 결정 알고리즘을 request에 대해 실행한 결과로 둔다.
-
isSecure는 request의 current URL의 scheme이 "
https
"이면 true, 아니면 false로 둔다. -
httpOnlyAllowed를 true로 둔다.
이는 fetch에서 호출되었기 때문에 true다. (예: document.cookie getter에서는 다를 수 있음)
-
cookies를 retrieve cookies 알고리즘에 isSecure, request의 current URL의 host, request의 current URL의 path, httpOnlyAllowed, sameSite를 넘겨 호출한 결과로 둔다.
쿠키 저장소는 정렬된 쿠키 목록을 반환한다
-
cookies가 비어있으면 리턴한다.
-
value를 serialize cookies 알고리즘에 cookies를 넘겨 실행한 결과로 둔다.
-
Append (`
Cookie
`, value)를 request의 header list에 추가한다.
3.1.2. `Set-Cookie
` 헤더
응답 `Set-Cookie
` 헤더 파싱 및 저장(parse and
store response `Set-Cookie
` headers) 알고리즘은
request
request와 response response가 주어졌을 때 다음을 따른다:
-
사용자 에이전트가 request에 대해 쿠키를 비활성화하도록 설정되어 있다면 리턴한다.
-
allowNonHostOnlyCookieForPublicSuffix를 false로 둔다.
-
isSecure를 request의 current URL의 scheme이 "
https
"이면 true, 아니면 false로 둔다. -
httpOnlyAllowed를 true로 둔다.
이는 fetch에서 호출되어 true임(document.cookie getter 등에서는 다름).
-
sameSiteStrictOrLaxAllowed를 same-site 모드 결정 알고리즘이 request에 대해 "
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의 current URL의 host, request의 current URL의 path, httpOnlyAllowed, allowNonHostOnlyCookieForPublicSuffix, sameSiteStrictOrLaxAllowed를 넘겨 실행한다.
-
Garbage collect cookies 알고리즘에 request의 current URL의 host를 넘겨 실행한다.
`
Set-Cookie
` 헤더는 병합될 수 없으므로 각각 독립적으로 처리된다. 이는 다른 어떤 헤더에도 허용되지 않는다. -
3.1.3. 쿠키 인프라(Cookie infrastructure)
same-site 모드 결정(determine the same-site mode) 알고리즘은 request request에 대해 다음을 따른다:
-
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의 has cross-site ancestor가 true라면, "
unset-or-less
"를 반환한다. -
request의 redirect-taint가 "
cross-site
"라면, "unset-or-less
"를 반환한다. -
"
strict-or-less
"를 반환한다.
3.2. `Origin
` 헤더
`Origin
`
요청 헤더는
fetch가 어디에서 시작되었는지를 나타낸다.
`Origin
` 헤더는 경로(path)를 노출하지 않는
`Referer
` [sic] 헤더의 변형이다.
이는 HTTP fetch 중 request의
response tainting이 "cors
"이거나,
request의 method가
`GET
` 또는 `HEAD
`가 아닌 경우에 사용된다.
호환성 문제로 인해 모든 fetch에 포함되지는
않는다.
가능한 값은 요청 origin의 바이트 직렬화(byte-serializing a request origin) 알고리즘이 request에 대해 반환하는 모든 값이다.
이 정의는 The Web Origin Concept의 정의를 대체한다. [ORIGIN]
요청
`Origin
` 헤더 추가(append a request `Origin
` header) 알고리즘은
request
request가 주어졌을 때 다음을 실행한다:
-
serializedOrigin을 요청 origin의 바이트 직렬화 알고리즘을 request에 대해 실행한 결과로 둔다.
-
request의 response tainting이 "
cors
"이거나, request의 mode가 "websocket
"이면, append (`Origin
`, serializedOrigin)을 request의 header list에 추가한다. -
그렇지 않고 request의 method가 `
GET
` 또는 `HEAD
`가 아니라면:-
request의 mode가 "
cors
"가 아니면, request의 referrer policy에 따라 분기한다:- "
no-referrer
" -
serializedOrigin을 `
null
`로 설정한다. - "
no-referrer-when-downgrade
"- "
strict-origin
"- "
strict-origin-when-cross-origin
" - "
-
request의 origin이 tuple origin이고, 그 scheme이 "
https
"이며, request의 current URL의 scheme이 "https
"가 아니면, serializedOrigin을 `null
`로 설정한다. - "
same-origin
" -
request의 origin이 request의 current URL의 origin과 동일 출처(same origin)가 아니면, serializedOrigin을 `
null
`로 설정한다. - 그 외
- 아무것도 하지 않는다.
- "
-
append (`
Origin
`, serializedOrigin)을 request의 header list에 추가한다.
-
request의 referrer policy는 fetcher가 서버와 origin을 명시적으로 공유하도록 설정하지 않은 모든 fetch에 대해 고려된다(예: CORS 프로토콜 사용 등).
3.3. CORS 프로토콜
교차 출처 응답 공유를 허용하고 HTML의
form
요소로 가능한 것보다 더 다양한 fetch를 허용하기
위해 CORS 프로토콜이 존재한다.
이는 HTTP 위에 계층화되어 있으며, 응답이 다른 origin과 공유될 수 있음을 선언하는 것을 허용한다.
방화벽(인트라넷) 뒤의 응답에서 데이터가 유출되는 것을 막기 위해 opt-in 메커니즘이어야 한다. 또한 request에 credentials가 포함되어 있을 때는 민감한 데이터 유출을 방지하기 위해서도 opt-in이어야 한다.
이 절에서는 서버 개발자를 위한 CORS 프로토콜을 설명한다. 사용자 에이전트에 대한 요구 사항은 fetch 알고리즘에 포함되어 있으며, 새로운 HTTP 헤더 문법을 제외한다.
3.3.1. 일반
CORS 프로토콜은 응답이 교차 출처로 공유 가능한지 나타내는 일련의 헤더로 구성된다.
HTML의
form
요소로 가능한 것보다 더 복잡한 request의 경우, CORS-사전 요청(CORS-preflight request)을 수행하여, request의
current 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-사전 요청이 아닌 CORS 요청에 대한 성공적인 HTTP 응답의 status는 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에 대해 와일드카드로 동작한다.
이런 request에 대해
`*
`인 헤더 이름이나 method만을 일치시킬 방법은 없다.
3.3.5. CORS 프로토콜과 credentials
request의
credentials mode가 "include
"일 때는 fetch에 credentials를 포함하는 것 외에도 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-사전 요청에는 credentials이 절대로 포함되지 않는다.
따라서 서버 개발자는 credentials로 "오염된" 응답을 공유할지 여부, 그리고 CORS-사전 요청이 credentials을 포함할 수 있도록 허용할지 결정해야 한다. 일반적으로, credentials를 포함해 응답을 공유하거나 요청을 허용하는 것은 매우 위험하며, confused deputy problem을 피하기 위해 극도의 주의가 필요하다.
credentials가 포함된 응답을 공유하려면,
`Access-Control-Allow-Origin
`와
`Access-Control-Allow-Credentials
` 헤더가 중요하다. 아래 표는
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과 비교하여 확인하도록 요구하는 데 사용할 수 있다. 대상은 request이다.
nosniff 결정(determine nosniff) 알고리즘은 header list list가 주어졌을 때 다음을 따른다:
-
values를 getting, decoding, and splitting(`
X-Content-Type-Options
`)을 list에 대해 실행한 결과로 둔다. -
values가 null이면 false를 반환한다.
-
values[0]이 "
nosniff
"와 ASCII 대소문자 구분 없이 일치하면 true를 반환한다. -
false를 반환한다.
웹 개발자 및 적합성 검사기는 `X-Content-Type-Options
`의 값에 대해 다음 ABNF를 사용해야 한다:
X-Content-Type-Options = "nosniff" ; case-insensitive
3.6.1. response를 request에 대해 nosniff로 차단해야 하는가?
다음 단계를 실행한다:
-
nosniff 결정을 response의 header list에 대해 실행한 결과가 false라면 allowed를 반환한다.
-
mimeType을 response의 header list에서 MIME 타입 추출 알고리즘을 실행한 결과로 둔다.
-
destination을 request의 destination으로 둔다.
-
destination이 script-like이고, mimeType이 failure이거나 JavaScript MIME 타입이 아니면 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
`
응답 헤더는 request의
current URL의 origin과
request의
origin을
request의 mode가
"no-cors
"일 때 비교하도록 강제할 수 있다.
Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" / %s"cross-origin" ; 대소문자 구분
교차 출처 리소스 정책 검사(cross-origin resource policy check) 알고리즘은 origin origin, environment settings object settingsObject, 문자열 destination, response response, 그리고 선택적 불린 값 forNavigation이 주어졌을 때 다음을 수행한다:
-
forNavigation이 주어지지 않았다면 false로 설정한다.
-
embedderPolicy를 settingsObject의 policy container의 embedder policy로 둔다.
-
교차 출처 리소스 정책 내부 검사를 origin, "
unsafe-none
", response, forNavigation에 대해 실행해 blocked를 반환하면 blocked를 반환한다.이 단계는 아래에서 Cross-Origin Embedder Policy에 관련 없는 위반을 보고하지 않기 위해 필요하다.
-
교차 출처 리소스 정책 내부 검사를 origin, embedderPolicy의 report only value, response, forNavigation에 대해 실행해 blocked를 반환하면 교차 출처 임베더 정책 CORP 위반 리포트 큐잉을 response, settingsObject, destination, true로 실행한다.
-
교차 출처 리소스 정책 내부 검사를 origin, embedderPolicy의 value, response, forNavigation에 대해 실행해 allowed를 반환하면 allowed를 반환한다.
-
교차 출처 임베더 정책 CORP 위반 리포트 큐잉을 response, settingsObject, destination, false로 실행한다.
-
blocked를 반환한다.
HTML의 navigate 알고리즘만 forNavigation이 true로 이 검사를 사용하며, 항상 중첩 내비게이션에만 해당된다. 그 외에는 response가 internal response (또는 opaque filtered response의 internal response)이거나, response가 곧 internal response가 될 것이다. [HTML]
교차 출처 리소스 정책 내부 검사(cross-origin resource policy internal check) 알고리즘은 origin origin, embedder policy value embedderPolicyValue, response response, 불린 forNavigation이 주어졌을 때 다음을 수행한다:
-
forNavigation이 true이고 embedderPolicyValue가 "
unsafe-none
"이면 allowed를 반환한다. -
policy를 getting(`
Cross-Origin-Resource-Policy
`)을 response의 header list에 대해 실행한 결과로 둔다.즉, `
Cross-Origin-Resource-Policy: same-site, same-origin
`은 아래에서 어떤 것도 일치하지 않으므로 항상 allowed가 된다. embedderPolicyValue가 "unsafe-none
"일 때는 두 개 이상의 `Cross-Origin-Resource-Policy
` 헤더도 동일하게 취급된다. -
policy가 `
same-origin
`, `same-site
`, `cross-origin
` 중 어느 것도 아니면 policy를 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
` -
다음 모두가 true이면
-
origin이 schemelessly same site라면 response의 URL의 origin
-
origin의 scheme이 "
https
"이거나, response의 URL의 scheme이 "https
"가 아닌 경우
그렇다면 allowed를 반환한다.
그 외에는 blocked를 반환한다.
`
Cross-Origin-Resource-Policy: same-site
`는 안전한 전송(https)으로 전달된 응답을 비안전한 요청(origin)과 일치시키지 않는다. 즉, secure로 전송된 응답은 secure로 시작한 initiator와만 일치한다. -
- null
교차 출처 임베더 정책 CORP 위반 리포트 큐잉(queue a cross-origin embedder policy CORP violation report) 알고리즘은 response response, environment settings object settingsObject, 문자열 destination, 불린 reportOnly가 주어졌을 때 다음을 수행한다:
-
endpoint를 reportOnly가 true이면 settingsObject의 policy container의 embedder policy의 report only reporting endpoint로, 그렇지 않으면 settingsObject의 policy container의 embedder policy의 reporting endpoint로 둔다.
-
serializedURL을 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. 가져오기
아래 알고리즘은 가져오기를 정의합니다. 대략적으로, 요청(request)과 작업 중 다양한 지점에서 실행할 하나 이상의 알고리즘을 받습니다. 마지막 두 알고리즘에는 응답이 전달됩니다. 처음 두 알고리즘은 업로드를 캡처하는 데 사용할 수 있습니다.
fetch를 실행하려면, request request, 선택적 알고리즘 processRequestBodyChunkLength, 선택적 알고리즘 processRequestEndOfBody, 선택적 알고리즘 processEarlyHintsResponse, 선택적 알고리즘 processResponse, 선택적 알고리즘 processResponseEndOfBody, 선택적 알고리즘 processResponseConsumeBody, 선택적 불리언 useParallelQueue (기본값 false)를 받아, 아래 단계를 수행합니다. processRequestBodyChunkLength가 주어질 경우, 전송된 바이트 수를 나타내는 정수를 받는 알고리즘이어야 합니다. processRequestEndOfBody가 주어질 경우, 인수를 받지 않는 알고리즘이어야 합니다. processEarlyHintsResponse가 주어질 경우, response를 받는 알고리즘이어야 합니다. processResponse가 주어질 경우, response를 받는 알고리즘이어야 합니다. processResponseEndOfBody가 주어질 경우, response를 받는 알고리즘이어야 합니다. processResponseConsumeBody가 주어질 경우, response와 null, 실패 또는 byte sequence를 받는 알고리즘이어야 합니다.
사용자 에이전트는 진행 중인 fetch를 일시 중단하도록 요청받을 수 있습니다. 사용자 에이전트는 일시 중단 요청을 수락하거나 무시할 수 있습니다. 일시 중단된 fetch는 재개될 수 있습니다. 진행 중인 fetch가 요청에 대해 HTTP 캐시의 응답을 업데이트 중인 경우, 사용자 에이전트는 일시 중단 요청을 무시해야 합니다.
사용자 에이전트는 request의 캐시 모드가 "no-store"이거나 응답에
`Cache-Control: no-store
` 헤더가 포함된 경우, HTTP 캐시의 항목을 업데이트하지 않습니다. [HTTP-CACHING]
-
Assert: request의 mode가 "
navigate
"이거나 processEarlyHintsResponse가 null이어야 한다. -
taskDestination을 null로 둔다.
-
crossOriginIsolatedCapability를 false로 둔다.
-
클라이언트로부터 요청 채우기를 request에 대해 실행한다.
-
request의 client가 null이 아니면:
-
taskDestination을 request의 client의 global object로 설정한다.
-
crossOriginIsolatedCapability를 request의 client의 cross-origin isolated capability로 설정한다.
-
-
useParallelQueue가 true라면, taskDestination을 새로운 병렬 큐 시작의 결과로 설정한다.
-
timingInfo를 fetch timing info의 새 인스턴스로 두고, start time과 post-redirect start time을 coarsened shared current time에 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의 body가 byte sequence라면, request의 body를 request의 body as a body로 설정한다.
-
다음 조건이 모두 true라면:
-
request의 URL의 scheme가 HTTP(S) scheme임
-
request의 mode가 "
same-origin
", "cors
", "no-cors
" 중 하나임 -
request의 client가 null이 아니고, request의 client의 global object가
Window
객체임 -
request의 method가 `
GET
`임 -
request의 unsafe-request flag가 설정되지 않았거나, request의 header list가 비어 있음
이 경우:
-
Assert: request의 origin이 request의 client의 same origin임
-
onPreloadedResponseAvailable을 다음 알고리즘으로 설정: response response를 받아, fetchParams의 preloaded response candidate에 response를 할당함
-
foundPreloadedResource를 preloaded resource 소비의 결과로 설정함: request의 client, request의 URL, request의 destination, request의 mode, request의 credentials mode, request의 integrity metadata, onPreloadedResponseAvailable
-
foundPreloadedResource가 true이고 fetchParams의 preloaded response candidate가 null이면, fetchParams의 preloaded response candidate를 "
pending
"으로 설정함
-
-
request의 header list에 `
Accept
`가 포함되어 있지 않으면:-
value를 `
*/*
`로 설정 -
request의 initiator가 "
prefetch
"이면, value를 document `Accept
` header value로 설정 -
그 외에는, 사용자 에이전트는 request의 destination에 따라 아래와 같이 value를 설정해야 함:
- "
document
"- "
frame
"- "
iframe
" - "
- document `
Accept
` header value - "
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의 header list에 추가한다.
-
-
request의 header list에 `
Accept-Language
`가 포함되어 있지 않으면, 사용자 에이전트는 append (`Accept-Language
, 적절한 header value)를 request의 header list에 추가한다. -
request의 internal priority가 null이면, request의 priority, initiator, destination, render-blocking을 사용하여 구현 정의 방식으로 request의 internal priority를 구현 정의 객체로 설정한다.
구현 정의 객체에는 HTTP/2의 스트림 가중치 및 의존성, HTTP용 확장 우선순위 스킴(Extensible Prioritization Scheme for HTTP)에서 사용하는 우선순위 정보(HTTP/3 등 해당 전송 포함), HTTP/1 fetch의 디스패치 및 처리 우선순위를 위한 동등한 정보가 포함될 수 있습니다. [RFC9218]
-
request가 하위 리소스 요청이면:
-
record를 새 fetch record로 두고, request는 request, controller는 fetchParams의 controller로 설정한다.
-
Append record를 request의 client의 fetch group의 fetch records에 추가함
-
-
main fetch를 fetchParams로 실행한다.
-
fetchParams의 controller를 반환함
클라이언트로부터 요청 채우기를 실행하려면, request request를 받아:
-
request의 traversable for user prompts가 "
client
"이면:-
request의 traversable for user prompts를 "
no-traversable
"로 설정함 -
request의 client가 null이 아니면:
-
global을 request의 client의 global object로 설정
-
global이
Window
객체이고 global의 navigable이 null이 아니면, request의 traversable for user prompts를 global의 navigable의 traversable navigable로 설정
-
-
-
request의 origin이 "
client
"이면: -
request의 policy container가 "
client
"이면:-
request의 client가 null이 아니면, request의 policy container를 request의 client의 policy container의 복제본으로 설정함 [HTML]
-
그 외에는, request의 policy container를 새 policy container로 설정함
-
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
"임 - request의 current URL의 scheme이 "
-
-
request의 response tainting을 "
basic
"으로 설정한다. -
scheme fetch를 fetchParams로 실행한 결과를 반환한다.
HTML은 URL의 scheme이 "
data
"인 경우, 생성된 문서 및 워커에 고유 불투명 origin을 할당한다. Service worker는 URL의 scheme이 HTTP(S) scheme인 경우에만 생성 가능하다. [HTML] [SW] -
- request의 mode가 "
same-origin
"임 -
네트워크 에러를 반환한다.
- request의 mode가 "
no-cors
"임 -
-
request의 redirect mode가 "
follow
"가 아니면, 네트워크 에러를 반환한다. -
request의 response tainting을 "
opaque
"로 설정한다. -
scheme fetch를 fetchParams로 실행한 결과를 반환한다.
-
- 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로 실행한 결과로 둔다.
-
corsWithPreflightResponse가 네트워크 에러면, 캐시 엔트리 삭제를 request로 실행한다.
-
corsWithPreflightResponse를 반환한다.
-
- 그 외의 경우
-
-
request의 response tainting을 "
cors
"로 설정한다. -
HTTP fetch를 fetchParams로 실행한 결과를 반환한다.
-
-
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가 206, internalResponse의 range-requested flag가 설정되어 있고, request의 header list에 `Range
`가 포함되어 있지 않으면, response와 internalResponse를 네트워크 에러로 설정한다.전통적으로, API는 range를 요청하지 않아도 range 응답을 허용했습니다. 이는 이전 range 요청의 부분 응답이 range 요청을 하지 않은 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
스킴 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는 빈 바이트 시퀀스 as a body로 설정하여 반환한다. - "
blob
" -
-
blobURLEntry를 request의 current URL의 blob URL entry로 둔다.
-
request의 method가 `
GET
`가 아니거나, blobURLEntry가 null이면, 네트워크 에러를 반환한다. [FILEAPI]`
GET
` method 제한은 상호 운용성 이외에 특별한 목적 없음. -
requestEnvironment를 determine the environment를 request로 실행한 결과로 둔다.
-
isTopLevelNavigation을 request의 destination이 "
document
"이면 true, 아니면 false로 둔다. -
isTopLevelNavigation이 false이고 requestEnvironment가 null이면, 네트워크 에러를 반환한다.
-
navigationOrEnvironment를 isTopLevelNavigation이 true면 "
navigation
", 아니면 requestEnvironment로 둔다. -
blob을 blob 객체 가져오기를 blobURLEntry와 navigationOrEnvironment로 실행한 결과로 둔다.
-
response를 새 response로 둔다.
-
fullLength를 blob의
size
로 둔다. -
serializedFullLength를 fullLength를 serialize하고 isomorphic encode한 결과로 둔다.
-
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를 get을 `
Range
`와 request의 header list로 실행한 결과로 둔다. -
rangeValue를 parsing a single range header value를 rangeHeader와 true로 실행한 결과로 둔다.
-
rangeValue가 실패면, 네트워크 에러를 반환한다.
-
(rangeStart, rangeEnd)를 rangeValue로 둔다.
-
rangeStart가 null이면:
-
rangeStart를 fullLength − rangeEnd로 설정한다.
-
rangeEnd를 rangeStart + rangeEnd − 1로 설정한다.
-
-
그 외의 경우:
-
rangeStart가 fullLength 이상이면, 네트워크 에러를 반환한다.
-
rangeEnd가 null이거나 rangeEnd가 fullLength 이상이면, rangeEnd를 fullLength − 1로 설정한다.
-
-
slicedBlob을 slice blob을 blob, rangeStart, rangeEnd + 1, type으로 실행한 결과로 둔다.
Range 헤더는 바이트 범위를 포함하지만, slice blob 알고리즘은 그렇지 않으므로 rangeEnd를 1 증가시켜야 한다.
-
slicedBodyWithType을 safely extracting을 slicedBlob으로 실행한 결과로 둔다.
-
serializedSlicedLength를 slicedBlob의
size
를 serialize하고 isomorphic encode한 결과로 둔다. -
contentRange를 build a content range를 rangeStart, rangeEnd, fullLength로 실행한 결과로 둔다.
-
response의 status를 206으로 설정한다.
-
response의 status message를 `
Partial Content
`로 설정한다. -
response의 header list를 « (`
Content-Length
`, serializedSlicedLength), (`Content-Type
`, type), (`Content-Range
`, contentRange) »로 설정한다.
-
-
response를 반환한다.
-
- "
data
" -
-
dataURLStruct를
data:
URL processor를 request의 current URL로 실행한 결과로 둔다. -
dataURLStruct가 실패면, 네트워크 에러를 반환한다.
-
새 response를 생성하여, status message는 `
OK
`, header list는 « (`Content-Type
`, mimeType) », body는 dataURLStruct의 body를 as a body로 설정하여 반환한다.
-
- "
file
" -
현재로서는 아쉽게도
file:
URL은 독자의 몫으로 남겨둔다.의심스러울 경우, 네트워크 에러를 반환한다.
- HTTP(S) scheme
-
HTTP fetch를 fetchParams로 실행한 결과를 반환한다.
- "
-
네트워크 에러를 반환한다.
환경 결정을 실행하려면, request request를 받아:
-
request의 reserved client가 null이 아니면, request의 reserved client를 반환한다.
-
null을 반환한다.
4.3. HTTP 가져오기
HTTP fetch를 실행하려면, fetch params fetchParams와 선택적 불리언 makeCORSPreflight(기본값 false)를 받아 다음 단계를 실행한다:
-
request를 fetchParams의 request로 둔다.
-
response와 internalResponse를 null로 둔다.
-
request의 service-workers mode가 "
all
"이면:-
requestForServiceWorker를 request의 복제본으로 둔다.
-
requestForServiceWorker의 body가 null이 아니면:
-
transformStream을 새로운
TransformStream
으로 둔다. -
transformAlgorithm을 chunk를 받아 다음 단계로 설정한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
chunk가
Uint8Array
객체가 아니면, 종료를 fetchParams의 controller에 대해 실행한다. -
그 외에는 enqueue chunk를 transformStream에 넣는다. 사용자 에이전트는 chunk를 구현 정의 실제 크기로 나누어 각각 enqueue 할 수 있다. 또한 여러 chunk를 구현 정의 실제 크기로 합쳐 enqueue할 수 있다.
-
-
transformStream 설정을 실행하여, transformAlgorithm을 transformAlgorithm으로 설정한다.
-
requestForServiceWorker의 body의 stream을 requestForServiceWorker의 body의 stream을 파이프한 결과로 둔다.
-
-
serviceWorkerStartTime을 coarsened shared current time으로, fetchParams의 cross-origin isolated capability를 인자로 설정한다.
-
response를 handle fetch를 requestForServiceWorker, fetchParams의 controller, fetchParams의 cross-origin isolated capability로 실행한 결과로 둔다.
-
response가 null이 아니면:
-
fetchParams의 timing info의 final service worker start time를 serviceWorkerStartTime으로 설정한다.
-
request의 body가 null이 아니면, cancel request의 body를 undefined로 실행한다.
-
internalResponse를 response가 filtered response가 아니면 response로, 아니면 response의 internal response로 설정한다.
-
다음 중 하나라도 true이면
-
response의 type이 "
error
"임 - request의 redirect mode가
"
manual
"가 아니고, response의 type이 "opaqueredirect
"임 - request의 redirect mode가
"
follow
"가 아니고, response의 URL list가 한 개를 초과함
이 경우 네트워크 에러를 반환한다.
-
-
-
-
response가 null이면:
-
makeCORSPreflight가 true이고 다음 중 하나라도 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에 item이 하나라도 있고, 해당 header-name cache entry match가 존재하지 않음
이 경우:
-
preflightResponse를 CORS-preflight fetch를 request로 실행한 결과로 둔다.
-
preflightResponse가 네트워크 에러이면 preflightResponse를 반환한다.
이 단계는 CORS-preflight cache를 확인하고 적절한 엔트리가 없으면 CORS-preflight fetch를 실행한다. 성공하면 캐시에 저장한다. CORS-preflight fetch의 목적은 가져온 리소스가 CORS 프로토콜을 인식하는지 확인하는 것이다. 캐시는 CORS-preflight fetch의 횟수를 최소화한다.
-
-
request의 redirect mode가 "
follow
"이면, request의 service-workers mode를 "none
"으로 설정한다.네트워크에서 발생한 리다이렉트(서비스 워커에서 발생한 것이 아닌)는 서비스 워커에 노출되지 않는다.
-
response와 internalResponse를 HTTP-network-or-cache fetch를 fetchParams로 실행한 결과로 설정한다.
-
request의 response tainting이 "
cors
"이고, request와 response에 대해 CORS check가 실패하면 네트워크 에러를 반환한다.CORS check는 response의 status가 304 또는 407인 경우, 또는 서비스 워커에서 온 경우에는 적용하지 않으며, 여기서 적용한다.
-
request와 response에 대해 TAO check가 실패하면 request의 timing allow failed flag를 설정한다.
-
-
request의 response tainting 또는 response의 type이 "
opaque
"이고, cross-origin resource policy check를 request의 origin, request의 client, request의 destination, internalResponse로 실행하여 blocked를 반환하면 네트워크 에러를 반환한다.cross-origin resource policy check는 네트워크에서 온 response와 서비스 워커에서 온 response 모두에 대해 실행된다. 이는 CORS check와 다르다. request의 client와 서비스 워커는 서로 다른 embedder 정책을 가질 수 있다.
-
internalResponse의 status가 redirect status이면:
-
internalResponse의 status가 303이 아니고, request의 body가 null이 아니며, connection이 HTTP/2를 사용하면, 사용자 에이전트는
RST_STREAM
프레임을 전송할 수 있으며, 권장된다.303은 특정 커뮤니티에서 특별한 의미를 가지므로 제외된다.
-
request의 redirect mode에 따라 아래 단계를 실행한다:
- "
error
" -
-
response를 네트워크 에러로 설정한다.
-
- "
manual
" -
-
request의 mode가 "
navigate
"이면, fetchParams의 controller의 next manual redirect steps를 HTTP-redirect fetch를 fetchParams와 response로 실행하는 단계로 설정한다. -
그 외에는 response를 opaque-redirect filtered response로 설정하며, internal response는 internalResponse로 둔다.
-
- "
follow
" -
-
response를 HTTP-redirect fetch를 fetchParams와 response로 실행한 결과로 설정한다.
-
- "
-
-
response를 반환한다. 일반적으로 internalResponse의 body의 stream이 반환 후에도 enqueue되고 있을 수 있다.
4.4. HTTP 리다이렉트 fetch
HTTP-redirect 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이 실패면 네트워크 에러를 반환한다.
-
locationURL의 scheme이 HTTP(S) scheme이 아니면 네트워크 에러를 반환한다.
-
request의 redirect count가 20이면, 네트워크 에러를 반환한다.
-
request의 redirect count를 1 증가시킨다.
-
request의 mode가 "
cors
"이고, locationURL이 credentials를 포함하며, request의 origin이 locationURL의 origin과 same origin이 아니면, 네트워크 에러를 반환한다. -
request의 response tainting이 "
cors
"이고, locationURL이 credentials를 포함하면, 네트워크 에러를 반환한다.이 규칙은 교차 출처 리소스가 동일 출처 URL로 리다이렉트할 때를 잡아낸다.
-
internalResponse의 status가 303이 아니고, request의 body가 null이 아니며, request의 body의 source가 null이면, 네트워크 에러를 반환한다.
-
다음 중 하나라도 true이면
-
internalResponse의 status가 301 또는 302이고, request의 method가 `
POST
`임 -
internalResponse의 status가 303이고, request의 method가 `
GET
` 또는 `HEAD
`가 아님
이 경우:
-
각 headerName에 대해 request-body-header name을 삭제한다. request의 header list에서 headerName을 삭제한다.
-
-
request의 current URL의 origin이 locationURL의 origin과 same origin이 아니면, 각 headerName에 대해 CORS non-wildcard request-header name을 삭제한다. request의 header list에서 headerName을 삭제한다.
즉, 최초 요청 이후에 다른 origin이 나타나면 `
Authorization
` 헤더가 제거된다. -
request의 body가 null이 아니면, request의 body를 body로, safely extracting을 request의 body의 source로 실행한 결과로 설정한다.
-
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으로 설정한다.
-
리다이렉트 시 request의 referrer policy 설정를 request와 internalResponse로 실행한다. [REFERRER]
-
recursive를 true로 둔다.
-
request의 redirect mode가 "
manual
"이면: -
main fetch를 fetchParams와 recursive로 실행한 결과를 반환한다.
이 단계는 main fetch를 호출하여 request의 response tainting 값을 올바르게 설정한다.
4.5. HTTP-네트워크-또는-캐시 가져오기
HTTP-네트워크-또는-캐시 가져오기를 실행하려면, fetch params fetchParams, 선택적 불리언 isAuthenticationFetch(기본값 false), 선택적 불리언 isNewConnectionFetch(기본값 false)를 받아 다음 단계를 수행한다:
일부 구현체는 HTTP 캐싱에 따라 부분 콘텐츠의 캐싱을 지원할 수 있습니다. 하지만 브라우저 캐시에서는 널리 지원되지 않습니다. [HTTP-CACHING]
-
request를 fetchParams의 request로 둔다.
-
httpFetchParams를 null로 둔다.
-
httpRequest를 null로 둔다.
-
response를 null로 둔다.
-
storedResponse를 null로 둔다.
-
httpCache를 null로 둔다.
-
revalidatingFlag를 unset으로 둔다.
-
아래 단계를 실행하지만 abort when fetchParams가 취소됨이면 중단한다:
-
request의 traversable for user prompts가 "
no-traversable
"이고 request의 redirect mode가 "error
"이면, httpFetchParams를 fetchParams로, httpRequest를 request로 설정한다. -
그 외의 경우:
-
httpRequest를 request의 복제본으로 설정한다.
구현체는 request의 body의 stream을 tee하는 것을 피하는 것이 권장된다. request의 body의 source가 null인 경우 단일 body만 필요하다. 예를 들어, body의 source가 null이면 리다이렉트와 인증이 fetch 실패로 끝난다.
-
httpFetchParams를 fetchParams의 복제본으로 설정한다.
-
httpFetchParams의 request를 httpRequest로 설정한다.
사용자 프롬프트 또는 리다이렉트가 가능한 경우, 사용자 에이전트는 프롬프트 응답 후 또는 리다이렉트 위치 결정 후 새 헤더 집합으로 요청을 재전송해야 할 수 있다. 이때 원래 요청 body가 이미 부분적으로 전송되었을 수 있으므로, 사전에 요청(body 포함)을 복제해 예비 복사본을 확보해야 한다.
-
-
includeCredentials를 아래 중 하나라도 true이면 true로, 아니면 false로 설정한다:
- request의 credentials mode가
"
include
"임 - request의 credentials mode가
"
same-origin
"이고 request의 response tainting이 "basic
"임
- request의 credentials mode가
"
-
Cross-Origin-Embedder-Policy에서 credentials 허용이 request로 false를 반환하면 includeCredentials를 false로 설정한다.
-
contentLength를 httpRequest의 body의 length로, body가 null이면 null로 설정한다.
-
contentLengthHeaderValue를 null로 둔다.
-
httpRequest의 body가 null이고 httpRequest의 method가 `
POST
` 또는 `PUT
`이면 contentLengthHeaderValue를 `0
`로 설정한다. -
contentLength가 null이 아니면 contentLengthHeaderValue를 contentLength로, serialize와 isomorphic encode를 적용한 결과로 설정한다.
-
contentLengthHeaderValue가 null이 아니면, append (`
Content-Length
`, contentLengthHeaderValue)를 httpRequest의 header list에 추가한다. -
contentLength가 null이 아니고 httpRequest의 keepalive가 true이면:
-
inflightKeepaliveBytes를 0으로 둔다.
-
group을 httpRequest의 client의 fetch group으로 둔다.
-
inflightRecords를 group 내 fetch record들 중 request의 keepalive가 true이고, done flag가 unset인 것의 집합으로 둔다.
-
각 fetchRecord에 대해:
-
contentLength와 inflightKeepaliveBytes의 합이 64키비바이트 넘으면 네트워크 에러를 반환한다.
위 제한은 body가 있는 요청이 환경 설정 객체보다 오래 살아남을 수 있는 경우, 크기가 제한되고 무한히 살아남지 않도록 보장한다.
-
-
-
referrerValue를 httpRequest의 referrer를 serialize하고 isomorphic encode한 값으로 둔다.
-
append (`
Referer
`, referrerValue)를 httpRequest의 header list에 추가한다.
-
-
요청 `
Origin
` 헤더 추가를 httpRequest로 실행한다. -
Fetch 메타데이터 헤더 추가를 httpRequest로 실행한다. [FETCH-METADATA]
-
httpRequest의 initiator가 "
prefetch
"이면 구조화 필드값 설정을 (`Sec-Purpose
`, 토큰prefetch
)로 httpRequest의 header list에 설정한다. -
httpRequest의 header list가 `
User-Agent
`를 포함하지 않으면, 사용자 에이전트는 append (`User-Agent
`, 기본 `User-Agent
` 값)을 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에 추가한다. -
httpRequest의 header list를 HTTP에 따라 수정한다. append는 httpRequest의 header list에 해당 header의 name이 이미 있으면 추가하지 않는다.
이 부분을 더 규범적으로 만들 수 있으면 좋겠다. 이 시점에서 `
Accept-Encoding
`, `Connection
`, `DNT
`, `Host
`는 필요하면 append된다.`
Accept
`, `Accept-Charset
`, `Accept-Language
`는 이 시점에 포함되지 않아야 한다.`
Accept
`, `Accept-Language
`는 이미 포함됨(fetch()에서는 기본적으로 포함되지 않음), `Accept-Charset
`는 불필요한 바이트다. 자세한 내용은 HTTP 헤더 계층 분리 참고. -
includeCredentials가 true이면:
-
요청 `
Cookie
` 헤더 추가를 httpRequest에 대해 실행한다. -
httpRequest의 header list가 `
Authorization
`를 포함하지 않으면:-
authorizationValue를 null로 둔다.
-
authentication entry가 httpRequest에 대해 존재하고, httpRequest의 use-URL-credentials flag가 unset이거나, 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 캐싱의 "Constructing Responses from Caches" 챕터 참고. [HTTP-CACHING]
HTTP 요구에 따라, `
Vary
` 헤더도 고려된다. -
storedResponse가 null이 아니면:
-
cache mode가 "
default
"이고, storedResponse가 stale-while-revalidate response이며, httpRequest의 client가 null이 아니면:-
response를 storedResponse로 설정한다.
-
response의 cache state를 "
local
"로 설정한다. -
revalidateRequest를 request의 복제본으로 설정한다.
-
revalidateRequest의 cache mode를 "
no-cache
"로 설정한다. -
revalidateRequest의 prevent no-cache cache-control header modification flag를 설정한다.
-
revalidateRequest의 service-workers mode를 "
none
"으로 설정한다. -
병렬로 main fetch를 새 fetch params로 실행한다. request는 revalidateRequest로 둔다.
이 fetch는 httpCache의 상태를 갱신하는 용도이며, 응답은 다음 캐시 접근 전까지 사용되지 않는다. stale 응답이 현재 요청의 응답으로 사용된다. 이 fetch는 client 컨텍스트에서 발행되므로 client가 사라지면 요청도 종료된다.
-
-
그 외의 경우:
-
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 캐싱의 "검증 요청 보내기" 챕터 참고. [HTTP-CACHING]
-
-
그 외에는 response를 storedResponse로 설정하고 response의 cache state를 "
local
"로 설정한다.
-
-
-
-
-
aborted라면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.
-
response가 null이면:
-
httpRequest의 cache mode가 "
only-if-cached
"이면 네트워크 에러를 반환한다. -
forwardResponse를 HTTP-network fetch를 httpFetchParams, includeCredentials, isNewConnectionFetch로 실행한 결과로 설정한다.
-
httpRequest의 method가 unsafe이고 forwardResponse의 status가 200~399 범위면, httpCache에서 적절한 저장된 response를 무효화한다. 자세한 내용은 HTTP 캐싱의 "저장된 응답 무효화" 챕터 참고. [HTTP-CACHING] storedResponse를 null로 설정한다.
-
revalidatingFlag가 설정되어 있고 forwardResponse의 status가 304이면:
-
storedResponse의 header list를 forwardResponse의 header list로 갱신한다. 자세한 내용은 HTTP 캐싱의 "검증 시 저장된 응답 신선화" 챕터 참고. [HTTP-CACHING]
이 단계는 캐시에 저장된 응답도 갱신한다.
-
response를 storedResponse로 설정한다.
-
response의 cache state를 "
validated
"로 설정한다.
-
-
response가 null이면:
-
response를 forwardResponse로 설정한다.
-
httpRequest와 forwardResponse를 httpCache에 저장한다. 자세한 내용은 HTTP 캐싱의 "캐시에 응답 저장" 챕터 참고. [HTTP-CACHING]
forwardResponse가 네트워크 에러이면, 이는 네거티브 캐싱(네트워크 에러 캐싱)이다.
관련 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가 null이 아니면:
-
request의 use-URL-credentials flag가 unset이거나 isAuthenticationFetch가 true이면:
-
fetchParams가 취소됨이면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.
-
username과 password를 최종 사용자에게 각각 요청하여 입력받고, request의 traversable for user prompts에서 입력한다.
-
username 설정을 request의 current URL과 username으로 실행한다.
-
password 설정을 request의 current URL과 password로 실행한다.
-
-
response를 HTTP-네트워크-또는-캐시 가져오기를 fetchParams와 true로 실행한 결과로 설정한다.
-
-
response의 status가 407이면:
-
request의 traversable for user prompts가 "
no-traversable
"이면 네트워크 에러를 반환한다. -
테스트 필요: 다중 `
Proxy-Authenticate
` 헤더, 누락, 파싱 이슈. -
fetchParams가 취소됨이면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.
-
최종 사용자에게 request의 traversable for user prompts에서 적절히 프롬프트하고, 결과를 proxy-authentication entry로 저장한다. [HTTP]
프록시 인증 관련 세부 사항은 HTTP에서 정의된다.
-
response를 HTTP-네트워크-또는-캐시 가져오기를 fetchParams로 실행한 결과로 설정한다.
-
-
아래 모두 true이면:
-
response의 status가 421임
-
isNewConnectionFetch가 false임
-
request의 body가 null이거나, request의 body가 null이 아니고, request의 body의 source가 null이 아님
이 경우:
-
fetchParams가 취소됨이면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.
-
response를 HTTP-네트워크-또는-캐시 가져오기를 fetchParams, isAuthenticationFetch, true로 실행한 결과로 설정한다.
-
-
isAuthenticationFetch가 true이면 authentication entry를 request와 주어진 realm에 대해 생성한다.
-
response를 반환한다. 일반적으로 response의 body의 stream은 반환 후에도 enqueue되고 있을 수 있다.
4.6. HTTP-네트워크 가져오기
HTTP-네트워크 가져오기를 실행하려면, fetch params fetchParams, 선택적 불리언 includeCredentials(기본값 false), 선택적 불리언 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로 실행한 결과로 둔다.
- 그 외의 경우
-
connection을 연결 얻기를 networkPartitionKey, request의 current URL, includeCredentials, newConnection으로 실행한 결과로 둔다.
- "
-
아래 단계를 실행하지만 abort when fetchParams가 취소됨이면 중단한다:
-
connection이 실패면 네트워크 에러를 반환한다.
-
timingInfo의 final connection timing info를 clamp and coarsen connection timing info를 connection의 timing info, timingInfo의 post-redirect start time, fetchParams의 cross-origin isolated capability로 실행한 결과로 설정한다.
-
connection이 HTTP/1.x 연결이고, request의 body가 null이 아니며, request의 body의 source가 null이면 네트워크 에러를 반환한다.
- timingInfo의 final network-request start time을 coarsened shared current time으로, fetchParams의 cross-origin isolated capability를 인자로 설정한다.
-
response를 connection을 통해 request를 사용해 HTTP 요청을 수행한 결과로 설정하며, 다음 사항에 유의한다:
-
HTTP의 관련 요구사항을 따른다. [HTTP] [HTTP-CACHING]
-
request의 body가 null이 아니고, request의 body의 source가 null이면, 사용자 에이전트는 최대 64키비바이트의 버퍼를 가질 수 있으며, request의 body 일부를 해당 버퍼에 저장할 수 있다. 만약 사용자 에이전트가 버퍼 크기를 초과해 body를 읽고, 요청을 재전송해야 한다면, 네트워크 에러를 반환한다.
연결이 타임아웃될 때 등 재전송이 필요하다.
body의 source가 null이 아니면, body를 재생성할 수 있으므로 버퍼가 필요없다.
source가 null이면, body는
ReadableStream
에서 생성됨을 의미하고, body를 재생성할 수 없으므로 버퍼가 필요하다. -
다음이 true인 동안:
-
timingInfo의 final network-response start time을 coarsened shared current time으로, fetchParams의 cross-origin isolated capability를 인자로, HTTP 파서가 응답 첫 바이트를 받은 직후에 설정한다.
-
모든 HTTP 응답 헤더가 전송될 때까지 대기한다.
-
status를 HTTP 응답의 상태 코드로 둔다.
-
status가 100~199 범위 내면:
-
timingInfo의 first interim network-response start time이 0이면, timingInfo의 first interim network-response start time을 timingInfo의 final network-response start time으로 설정한다.
-
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의 traversable for user prompts가 traversable navigable이면, 해당 대화 상자를 request의 traversable for user prompts에서 보여준다.
-
그 외에는 네트워크 에러를 반환한다.
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이 아니면, process request body chunk length를 bytes의 length로 실행한다.
-
-
processEndOfBody를 다음 단계로 설정한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
fetchParams의 process request end-of-body가 null이 아니면, process request end-of-body를 실행한다.
-
-
processBodyError를 e를 받아 다음 단계로 설정한다:
-
fetchParams가 취소됨이면 이 단계를 중단한다.
-
e가 "
AbortError
"DOMException
이면, abort fetchParams의 controller를 실행한다. -
그 외에는 terminate fetchParams의 controller를 실행한다.
-
-
body 점진적 읽기를 request의 body, processBodyChunk, processEndOfBody, processBodyError, fetchParams의 task destination으로 실행한다.
-
-
-
-
aborted이면:
-
connection이 HTTP/2를 사용하면
RST_STREAM
프레임을 전송한다. -
fetchParams에 대한 적절한 네트워크 에러를 반환한다.
-
-
buffer를 빈 바이트 시퀀스로 둔다.
이 버퍼는 사용자 에이전트의 네트워크 계층 내 내부 버퍼를 나타낸다.
-
stream을 new
ReadableStream
으로 둔다. -
pullAlgorithm을 다음 단계로 설정한다:
-
promise를 새 Promise로 둔다.
-
아래 단계를 병렬로 실행한다:
-
buffer가 비어있지 않을 때까지 대기한다.
-
fetch task 큐에 넣기를 실행하여 아래 단계를 fetchParams의 task destination과 함께 실행한다.
-
Pull from bytes를 buffer와 stream으로 실행한다.
-
stream이 errored면, terminate fetchParams의 controller를 실행한다.
-
resolve promise를 undefined로 실행한다.
-
-
promise를 반환한다.
-
-
cancelAlgorithm을 abort fetchParams의 controller를 reason으로 실행하는 알고리즘으로 설정한다.
-
byte reading 지원으로 stream 설정을 실행하여, pullAlgorithm을 pullAlgorithm으로, cancelAlgorithm을 cancelAlgorithm으로 설정한다.
-
includeCredentials가 true면, 사용자 에이전트는 응답 `
Set-Cookie
` 헤더 파싱 및 저장을 request와 response로 실행해야 한다. -
아래 단계를 병렬로 실행한다:
-
아래 단계를 abort when fetchParams가 취소됨이면 중단한다:
-
다음이 true인 동안:
-
response의 메시지 body에서 1바이트 이상 전송되면:
-
bytes를 전송된 바이트로 둔다.
-
codings를 extracting header list values를 `
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의 length만큼 증가시킨다.
-
bytes를 콘텐츠 코딩 처리를 codings과 bytes로 실행한 결과로 설정한다.
이 단계로 `
Content-Length
` 헤더의 신뢰도가 보장되지 않는다. -
response의 body info의 decoded size를 bytes의 length만큼 증가시킨다.
-
bytes가 실패면 terminate fetchParams의 controller를 실행한다.
-
bytes를 buffer에 append한다.
-
buffer 크기가 사용자 에이전트가 선택한 상한 초과면 fetch를 일시 중단하도록 요청한다.
-
-
그 외에 response의 메시지 body 바이트 전송이 정상적으로 끝났고, stream이 readable이면, close stream을 실행하고, 병렬 단계를 중단한다.
-
-
-
aborted이면:
-
fetchParams가 aborted이면:
-
response의 aborted flag를 설정한다.
-
stream이 readable이면, error stream을 deserialize a serialized abort reason로 fetchParams의 controller의 serialized abort reason과 구현 정의 realm을 인자로 실행한 결과로 error한다.
-
-
connection이 HTTP/2를 사용하면
RST_STREAM
프레임을 전송한다. -
그 외에는 사용자 에이전트는 성능에 악영향이 없다면 connection을 닫아야 한다.
예를 들어, 재사용 가능한 연결에서 남은 바이트가 적은 경우, 연결을 닫고 다음 fetch를 위해 핸드셰이크를 다시 하는 것보다 열어두는 것이 더 나을 수 있다.
-
이 단계들은 병렬로 실행되며, 이 시점에서 response의 body가 관련 있는지(예: 리다이렉트) 불분명하다.
-
-
response를 반환한다. 일반적으로 response의 body의 stream은 반환 후에도 enqueue되고 있을 수 있다.
4.7. CORS-프리플라이트 가져오기
이 단계는 CORS 프로토콜이 이해되는지 확인하는 사용자 에이전트 구현이다. 이른바 CORS-프리플라이트 요청이다. 성공하면 CORS-프리플라이트 캐시를 채워 fetch 횟수를 최소화한다.
CORS-프리플라이트 가져오기를 실행하려면, request request를 받아 다음 단계를 실행한다:
-
preflight을 새 request로 생성하고, method는 `
OPTIONS
`로, URL list는 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-네트워크-또는-캐시 가져오기를 사용하며, HTTP 가져오기를 사용하지 않는다.
-
append (`
Accept
`, `*/*
`)를 preflight의 header list에 추가한다. -
append (`
Access-Control-Request-Method
`, request의 method)를 preflight의 header list에 추가한다. -
headers를 CORS-비안전 요청 헤더 이름으로, request의 header list로 구한다.
-
headers가 비어있지 않으면:
-
value를 headers의 각 항목을 `
,
`로 연결한 문자열로 둔다. -
append (`
Access-Control-Request-Headers
`, value)를 preflight의 header list에 추가한다.
이 단계는 combine을 사용하지 않는다. 즉, 0x2C 뒤에 0x20을 추가하지 않는다. 이는 구현상의 이유 때문이다.
-
-
response를 HTTP-네트워크-또는-캐시 가져오기를 새 fetch params로 실행한 결과로 둔다. 이 때 request는 preflight이다.
-
CORS 검사를 request와 response에 대해 실행하여 성공하고, response의 status가 ok status이면:
CORS 검사는 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가 실패면 네트워크 에러를 반환한다.
-
methods가 null이고 request의 use-CORS-preflight flag가 설정되어 있으면, methods를 request의 method만 포함하는 새 리스트로 설정한다.
이는 request의 use-CORS-preflight flag 때문에 발생한 CORS-프리플라이트 가져오기가 캐시에 저장되도록 한다.
-
request의 method가 methods에 없고, request의 method가 CORS-safelisted method가 아니며, request의 credentials mode가 "
include
"이거나, methods에 `*
`가 없으면 네트워크 에러를 반환한다. -
request의 header list의 name 중 하나가 CORS non-wildcard request-header name이고, headerNames에 바이트 대소문자 구분 없이 일치하는 항목이 없으면 네트워크 에러를 반환한다.
-
각 unsafeName에 대해, CORS-비안전 요청 헤더 이름을 request의 header list와 함께 구하고, unsafeName이 headerNames에 바이트 대소문자 구분 없이 일치하지 않고, request의 credentials mode가 "
include
"이거나, headerNames에 `*
`가 없으면 네트워크 에러를 반환한다. -
max-age를 extracting header list values를 `
Access-Control-Max-Age
` 와 response의 header list로 실행한 결과로 둔다. -
max-age가 실패 또는 null이면 max-age를 5로 설정한다.
-
max-age가 max-age 제한을 초과하면, max-age를 제한값으로 설정한다.
-
사용자 에이전트가 캐시를 제공하지 않으면 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를 반환한다.
-
-
그 외의 경우 네트워크 에러를 반환한다.
4.8. CORS-프리플라이트 캐시
사용자 에이전트는 CORS-프리플라이트 캐시를 가진다. CORS-프리플라이트 캐시는 리스트이며, 캐시 엔트리로 구성된다.
캐시 엔트리는 다음으로 구성된다:
- 키 (네트워크 파티션 키)
- 바이트 직렬화된 오리진 (바이트 시퀀스)
- URL (URL)
- max-age (초 단위 숫자)
- 자격 증명 (불리언)
- 메서드 (null, `
*
` 또는 메서드) - 헤더 이름 (null, `
*
`, 또는 헤더 이름)
캐시 엔트리는 max-age 필드에 지정된 초가 저장 이후 경과하면 삭제되어야 한다. 캐시 엔트리는 그 이전에 삭제될 수도 있다.
새 캐시 엔트리 생성을 실행하려면 request, max-age, method, headerName을 받아 다음 단계를 실행한다:
-
entry를 캐시 엔트리로 생성하고, 다음으로 초기화한다:
- 키
-
네트워크 파티션 키 결정을 request로 실행한 결과
- 바이트 직렬화된 오리진
-
요청 오리진 바이트 직렬화를 request에 대해 실행한 결과
- URL
-
request의 current URL
- max-age
-
max-age
- 자격 증명
-
request의 credentials mode가 "
include
"이면 true, 아니면 false - 메서드
-
method
- 헤더 이름
-
headerName
-
Append entry를 사용자 에이전트의 CORS-프리플라이트 캐시에 추가한다.
캐시 엔트리 삭제를 실행하려면 request를 받아, remove 사용자 에이전트의 CORS-프리플라이트 캐시에서 다음 조건을 모두 만족하는 캐시 엔트리들을 삭제한다: 키가 네트워크 파티션 키 결정을 request로 실행한 결과와 같고, 바이트 직렬화된 오리진이 요청 오리진 바이트 직렬화를 request로 실행한 결과와 같으며, URL이 request의 current URL과 같다.
캐시 엔트리 일치란 캐시 엔트리 entry와 request에 대해 entry의 키가 네트워크 파티션 키 결정을 request로 실행한 결과와 같고, entry의 바이트 직렬화된 오리진이 요청 오리진 바이트 직렬화를 request로 실행한 결과와 같고, entry의 URL이 request의 current URL과 같으며, 아래 중 하나가 true일 때를 말한다:
- entry의 자격 증명이 true임
- entry의 자격 증명이 false이고 request의
credentials mode가 "
include
"가 아님
위 조건이 true이면 캐시 엔트리 일치이다.
메서드 캐시 엔트리
일치란
method와 request에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시에
캐시 엔트리가 있고,
캐시 엔트리 일치이며,
그 메서드가
method 또는 `*
`인 경우를 뜻한다.
헤더 이름 캐시 엔트리 일치란 headerName과 request에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시에 캐시 엔트리가 있고, 캐시 엔트리 일치이며, 아래 중 하나가 true일 때를 말한다:
- 그 헤더 이름이 바이트 대소문자 구분 없이 headerName과 일치함
- 그 헤더
이름이 `
*
`이고 headerName이 CORS non-wildcard request-header name이 아님
위 조건이 true이면 헤더 이름 캐시 엔트리 일치이다.
4.9. CORS 검사
CORS 검사를 실행하려면 request와 response를 받아 다음 단계를 실행한다:
-
origin을 get `
Access-Control-Allow-Origin
` 을 response의 header list로 실행한 결과로 둔다. -
origin이 null이면 실패를 반환한다.
null은 `
null
`과 다르다. -
request의 credentials mode가 "
include
"가 아니고, origin이 `*
`이면 성공을 반환한다. -
요청 오리진 바이트 직렬화를 request로 실행한 결과가 origin과 다르면 실패를 반환한다.
-
request의 credentials mode가 "
include
"가 아니면 성공을 반환한다. -
credentials를 get `
Access-Control-Allow-Credentials
` 을 response의 header list로 실행한 결과로 둔다. -
credentials가 `
true
`이면 성공을 반환한다. -
실패를 반환한다.
4.10. TAO 검사
TAO 검사를 실행하려면 request와 response를 받아 다음 단계를 실행한다:
-
request의 timing allow failed flag가 설정되어 있으면 실패를 반환한다.
-
values를 getting, decoding, and splitting을 `
Timing-Allow-Origin
`과 response의 header list로 실행한 결과로 둔다. -
values에 "
*
"가 있으면 성공을 반환한다. -
values에 요청 오리진 직렬화를 request로 실행한 결과가 있으면 성공을 반환한다.
-
request의 mode가 "
navigate
"이고, request의 current URL의 origin이 request의 origin과 same origin이 아니면 실패를 반환한다.이 단계는 중첩 네비게이션의 탐색에 필요하다. 여기서 request의 origin은 컨테이너 문서의 origin이 되고, TAO 검사는 실패를 반환한다. 네비게이션 타이밍은 TAO 검사 결과를 검증하지 않으므로, 중첩 문서는 전체 타이밍 정보를 볼 수 있지만 컨테이너 문서는 볼 수 없다.
-
request의 response tainting이 "
basic
"이면 성공을 반환한다. -
실패를 반환한다.
4.11. 지연 fetch
지연 fetch는 호출자가 fetch를 가능한 가장 늦은 시점에 실행하도록 요청할 수 있게 해주며, 즉 fetch 그룹이 종료될 때나, 또는 타임아웃 후에 실행된다.
지연 fetch 태스크
소스는
지연 fetch 결과를 갱신하는 데 사용되는 태스크
소스이다.
사용자 에이전트는 이 태스크
소스의 태스크를,
특히 DOM 조작 태스크 소스와 같이 스크립트 실행을 유발할 수 있는 태스크 소스보다 우선 실행해야 한다.
이는 fetchLater()
호출의 최신 상태를,
해당 결과에 의존할 수 있는 스크립트가 실행되기 전에 반영하기 위함이다.
지연 fetch 큐에
넣기를 실행하려면
request
request, null 또는
DOMHighResTimeStamp
activateAfter, 그리고 인자 없이 실행되는 알고리즘 onActivatedWithoutTermination을 받아:
-
클라이언트로부터 request 채우기를 request로 실행한다.
-
request의 service-workers mode를 "
none
"으로 설정한다. -
request의 keepalive를 true로 설정한다.
-
deferredRecord를 새로운 지연 fetch 레코드로 생성한다. request는 request, notify invoked는 onActivatedWithoutTermination로 둔다.
-
Append deferredRecord를 request의 client의 fetch group의 deferred fetch records에 추가한다.
-
activateAfter가 null이 아니면, 아래 단계를 병렬로 실행한다:
-
사용자 에이전트는 아래 조건 중 하나가 만족될 때까지 대기한다:
-
activateAfter 밀리초가 경과함
-
사용자 에이전트가 곧 스크립트 실행 기회를 잃을 것이라고 판단함(예: 브라우저가 백그라운드로 이동할 때, 또는 request의 client의 global object가
Window
객체이고, 연관된 문서가 "hidden
" visibility state를 오랜 시간 가졌을 때)
-
-
지연 fetch 처리를 deferredRecord로 실행한다.
-
-
deferredRecord를 반환한다.
총 요청 길이 계산을 실행하려면 request request를 받아:
-
totalRequestLength를 request의 URL를 serialize하고, exclude fragment를 true로 한 후 길이로 둔다.
-
totalRequestLength를 request의 referrer를 serialize한 길이만큼 증가시킨다.
-
각 (name, value)에 대해, request의 header list에서, totalRequestLength를 name의 길이 + value의 길이만큼 증가시킨다.
-
totalRequestLength를 반환한다.
지연 fetch들 처리을 실행하려면 fetch 그룹 fetchGroup을 받아:
-
각 deferred fetch record deferredRecord를 fetchGroup의 deferred fetch records에서 지연 fetch 처리를 deferredRecord로 실행한다.
지연 fetch 처리를 실행하려면 deferredRecord를 받아:
-
deferredRecord의 invoke state가 "
pending
"이 아니면 return한다. -
deferredRecord의 invoke state를 "
sent
"으로 설정한다. -
글로벌 태스크 큐에 넣기를 지연 fetch 태스크 소스에, deferredRecord의 request의 client의 global object와 함께, deferredRecord의 notify invoked를 실행한다.
4.11.1. 지연 fetch 할당량
이 절은 비규범적입니다.
지연 fetch 할당량은 최상위 traversable("탭")에 640키비바이트가 할당됩니다. 최상위 문서와 동일 출처의 직접 중첩 문서는 이 할당량을 사용해 지연 fetch를 큐에 넣을 수 있으며, 일부를 교차 출처 중첩 문서에 권한 정책을 통해 위임할 수도 있습니다.
기본적으로, 이 640키비바이트 중 128키비바이트가 교차 출처 중첩 문서에 할당하도록 예약되며, 각 중첩 문서는 8키비바이트를 예약합니다.
최상위 문서와 그 중첩 문서는 권한 정책을 통해 교차 출처 하위 문서에 얼마를 위임할지 제어할 수 있습니다. 기본적으로 "deferred-fetch-minimal
"
정책은 모든 오리진에 대해 활성화되어 있고, "deferred-fetch
"는
최상위 문서의 오리진에만 활성화되어 있습니다. 특정 오리진과 중첩 문서에 대해 "deferred-fetch
"
정책을 완화하면 해당 중첩 문서에 64키비바이트를 할당할 수 있습니다. 반대로 "deferred-fetch-minimal
"
정책을 특정 오리진이나 중첩 문서에 대해 제한하면, 문서가 기본적으로 받을 8키비바이트 할당을 막을 수 있습니다. 최상위 문서 자체에 대해 "deferred-fetch-minimal
"
정책을 비활성화하면, 전체 128키비바이트 위임 할당량이 640키비바이트의 메인 풀로 다시 합쳐집니다.
문서에 할당된 할당량 중, 동일 보고 오리진(즉, 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
객체는
헤더 리스트(헤더 리스트)를
가지며, 처음에는 비어 있습니다. 이 리스트는 다른 객체의 헤더 리스트를 가리키는 포인터일 수 있습니다. 예를 들어 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-urlencoded
serializer를 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()
메서드 단계는,
body
소비를 this와 다음 단계로 실행한 결과를 반환한다.
바이트 시퀀스 bytes를 받아 ArrayBuffer 생성을 bytes에,
this의 관련 realm에서 실행한다.
위 메서드는 RangeError
로
reject될 수 있습니다.
blob()
메서드 단계는,
body
소비를 this와 다음 단계로 실행한 결과를 반환한다.
바이트 시퀀스 bytes를 받아 Blob
객체를 생성하며,
내용은 bytes이고,
type
속성은 MIME 타입
얻기를 this에 실행한 결과로 설정한다.
bytes()
메서드 단계는,
body
소비를 this와 다음 단계로 실행한 결과를 반환한다.
바이트 시퀀스 bytes를 받아 Uint8Array 생성을 bytes에,
this의 관련 realm에서 실행한다.
위 메서드는 RangeError
로
reject될 수 있습니다.
formData()
메서드 단계는,
body
소비를 this와 아래 단계를 실행한 결과를 반환한다.
바이트 시퀀스 bytes를 받아:
-
mimeType을 MIME 타입 얻기를 this에 실행한 결과로 둔다.
-
mimeType이 null이 아니면, mimeType의 essence에 따라 다음을 실행한다:
- "
multipart/form-data
" -
-
bytes를 `
boundary
` 파라미터 값으로 파싱한다. 규칙은 Returning Values from Forms: multipart/form-data를 따른다. [RFC7578]`
Content-Disposition
` 헤더에 `filename
` 파라미터가 있으면, 해당 부분을 entry로 파싱하며, 값은File
객체이고, 내용은 해당 부분 내용이다.name
속성은 `filename
` 파라미터 값으로,type
속성은 해당 부분의 `Content-Type
` 헤더 값, 없으면 `text/plain
`로 한다([RFC7578] 4.4 절).`
Content-Disposition
` 헤더에 `filename
` 파라미터가 없으면, 해당 부분을 entry로 파싱하며, 값은 해당 부분 내용을 UTF-8로 BOM 없이 디코딩한 문자열이다. `Content-Type
` 헤더나 `charset
` 파라미터가 있든 없든 무관하게 처리한다.`
Content-Disposition
` 헤더에 `name
`이 `_charset_
`이면 다른 부분과 동일하게 파싱하며, 인코딩은 변경하지 않는다. -
실패하면 TypeError를 던진다.
-
새
FormData
객체를 반환하며, 파싱 결과의 entry들로 entry list를 채운다.
위 설명은 `
multipart/form-data
`에 대해 대략적이며, 더 상세한 파싱 명세가 필요합니다. 기여자 환영. -
- "
application/x-www-form-urlencoded
" -
-
entries를 파싱을 bytes에 실행한 결과로 둔다.
-
새
FormData
객체를 반환하며, entry list를 entries로 채운다.
-
- "
-
TypeError를 던진다.
json()
메서드 단계는,
body
소비를 this와 JSON 바이트를 파싱해 JS 값으로 변환으로 실행한 결과를 반환한다.
위 메서드는 SyntaxError
로
reject될 수 있습니다.
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
"는
RequestDestination
에서 생략되며, JavaScript에서 관찰할 수 없기 때문이다.
구현체는
여전히 destination으로 지원해야 한다. "websocket
"은 RequestMode
에서 생략되며, JavaScript에서 사용할 수도, 관찰할 수도 없다.
Request
객체는
request(request 객체)을 가진다.
Request
객체는 또한
headers(null 또는 Headers
객체, 초기값은
null)을 가진다.
Request
객체는 signal(null 또는 AbortSignal
객체, 초기값은 null)을 가진다.
Request
객체의
body는
request의
body이다.
request = new Request(input [, init])
-
새 request를 반환하며,
url
속성은 input이 문자열이면 input이고, input이Request
객체면 input의url
이다.init 인자는 아래와 같이 속성을 설정할 수 있는 객체이다:
method
- 문자열로 request의
method
를 설정한다. headers
Headers
객체, 객체 리터럴, 또는 2-항목 배열의 배열로 request의headers
를 설정한다.body
BodyInit
객체 또는 null로 request의 body를 설정한다.referrer
- 동일 출처 URL, "
about:client
", 또는 빈 문자열 값의 문자열로 request의 referrer를 설정한다. referrerPolicy
- referrer policy로 request의
referrerPolicy
를 설정한다. mode
- 문자열로 요청이 CORS를 사용할지, 동일 출처 URL로 제한될지를 나타낸다. request의
mode
를 설정한다. input이 문자열이면 기본값은 "cors
"이다. credentials
- 문자열로 인증 정보가 항상, 절대, 또는 동일 출처 URL일 때만 요청과 함께 전송될지를 나타낸다. 응답에서 인증 정보를 사용할지도 결정한다.
request의
credentials
를 설정한다. input이 문자열이면 기본값은 "same-origin
"이다. cache
- 문자열로 요청이 브라우저 캐시와 어떻게 상호작용할지 나타내며, request의
cache
를 설정한다. redirect
- 문자열로 request가 리다이렉트 시 어떻게 동작할지 나타내며, request의
redirect
를 설정한다. integrity
- request가 가져올 리소스의 암호학적 해시로, request의
integrity
를 설정한다. keepalive
- 불리언으로 request의
keepalive
를 설정한다. signal
AbortSignal
객체로 request의signal
을 설정한다.window
- null만 가능. request를 어떤
Window
와도 연결하지 않도록 한다. duplex
- "
half
"만 유효하며, 반이중 fetch(즉, 사용자 에이전트가 요청 전체를 전송한 후 응답을 처리함)를 시작한다. "full
"은 추후에 사용될 예약 값이며, 전이중 fetch(사용자 에이전트가 전체 요청을 보내기 전에 응답을 처리 가능)를 의미한다.body
가ReadableStream
객체일 때 필요하다. "full
" 정의는 issue #1254 참고. priority
- 문자열로 request의 priority를 설정한다.
request . method
- request의 HTTP 메서드를 반환하며, 기본값은 "
GET
"이다. request . url
- request의 URL을 문자열로 반환한다.
request . headers
- request와 연결된
Headers
객체를 반환한다. 네트워크 계층에서 사용자 에이전트가 추가한 헤더(예: "Host
")는 이 객체에 포함되지 않는다. request . destination
- request가 요청한 리소스 종류(예: "
document
" 또는 "script
")를 반환한다. request . referrer
- request의 referrer를 반환한다. init에서 명시적으로 설정하면 동일 출처 URL이 될 수 있고, 빈 문자열이면 referrer가
없음을 의미하며, 기본값은 "
about:client
"이다. fetch 시 `Referer
` 헤더 값을 결정할 때 사용된다. request . referrerPolicy
- request에 연결된 referrer policy를 반환한다. fetch 시 request의 referrer 값을 계산할 때 사용된다.
request . mode
- request와 연결된 mode를 반환한다. 요청이 CORS를 사용할지, 동일 출처 URL에만 제한될지를 문자열로 나타낸다.
request . credentials
- request와 연결된 credentials mode를 반환한다. 인증 정보가 항상, 절대, 또는 동일 출처 URL일 때만 요청과 함께 전송될지를 문자열로 나타낸다.
request . cache
- request와 연결된 cache mode를 반환한다. 요청이 fetch 시 브라우저 캐시와 어떻게 상호작용할지를 문자열로 나타낸다.
request . redirect
- request와 연결된 redirect mode를 반환한다. fetch 시 요청의 리다이렉트 처리 방식을 문자열로 나타내며, 기본적으로 request는 리다이렉트를 따름.
request . integrity
- request가 fetch하는 리소스의 서브 리소스 무결성(Subresource Integrity) 메타데이터를 반환한다. 값은 공백으로 구분된 여러 해시로 구성된다. [SRI]
request . keepalive
- request가 생성된 글로벌 객체보다 오래 살아남을 수 있는지 여부를 boolean으로 반환한다.
request . isReloadNavigation
- request가 reload 네비게이션인지 여부를 boolean으로 반환한다.
request . isHistoryNavigation
- request가 히스토리 네비게이션(뒤로/앞으로 네비게이션)인지 여부를 boolean으로 반환한다.
request . signal
- request와 연결된 signal을 반환한다.
AbortSignal
객체로, request가 abort됐는지, abort 이벤트 핸들러를 포함한다. request . duplex
- "
half
"를 반환하며, fetch가 반이중(사용자 에이전트가 전체 요청을 전송한 후 응답을 처리)임을 의미한다. 추후에 "full
"도 반환할 수 있으며, 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을 반환한다.
duplex
getter 단계는
"half
"를 반환한다.
clone()
메서드 단계:
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을 받아 다음을 수행한다:
response 초기화를
실행하려면, Response
객체 response,
ResponseInit
init, null 또는 body with type body를 받아 다음을 수행한다:
-
init["
status
"] 값이 200~599 범위에 없으면 RangeError를 던진다. -
init["
statusText
"] 값이 빈 문자열이 아니고 reason-phrase 토큰 생성식과 일치하지 않으면 TypeError를 던진다. -
response의 response의 status message를 init["
statusText
"]로 설정한다. -
init["
headers
"]가 있으면 fill을 response의 headers와 init["headers
"]로 실행한다. -
body가 null이 아니면:
new Response(body, init)
생성자 단계:
정적 error()
메서드 단계는,
새로운 network
error, "immutable
", 현재 realm을 받아 생성을 실행한 Response
객체를
반환한다.
정적 redirect(url, status)
메서드 단계:
-
parsedURL을 파싱을 url과 현재 settings 객체의 API 기본 URL로 실행한 결과로 둔다.
-
parsedURL이 실패면 TypeError를 던진다.
-
status가 redirect status가 아니면 RangeError를 던진다.
-
responseObject를 생성을 새로운 response, "
immutable
", 현재 realm으로 실행한 결과로 둔다. -
value를 parsedURL을 serialize하고 isomorphic encode한 결과로 둔다.
-
append(`
Location
`, value)를 responseObject의 response의 헤더 리스트에 추가한다. -
responseObject를 반환한다.
정적 json(data, init)
메서드 단계:
-
bytes를 JavaScript 값을 JSON 바이트로 직렬화를 data에 실행한 결과로 둔다.
-
body를 추출을 bytes로 실행한 결과로 둔다.
-
responseObject를 생성을 새로운 response, "
response
", 현재 realm으로 실행한 결과로 둔다. -
response 초기화를 responseObject, init, (body, "
application/json
")로 실행한다. -
responseObject를 반환한다.
type
getter 단계는 this의
response의 type을 반환한다.
url
getter 단계는, this의 response의 URL이 null이면 빈
문자열을,
아니면 this의
response의 URL을 serialize(exclude fragment true)하여 반환한다.
redirected
getter 단계는,
this의 response의 URL 리스트의 크기가 1보다
크면 true, 아니면 false를 반환한다.
리다이렉트 결과인 response를 필터링하려면 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 ]FetchLaterResult fetchLater (RequestInfo ,
input optional DeferredRequestInit = {}); };
init
fetch(input, init)
메서드 단계:
-
p를 새로운 promise로 둔다.
-
requestObject를
Request
생성자를 input, init 인자로 호출한 결과로 둔다. 예외가 발생하면 p를 reject하고 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로 둔다.
-
locallyAborted를 false로 둔다.
동일 스레드에서 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면, p를 reject하고
TypeError
로 중단. -
responseObject를 생성을
Response
객체, response, "immutable
", relevantRealm으로 실행한 결과로 둔다. -
p를 resolve한다(responseObject로).
-
-
p를 반환한다.
fetch() 호출 중단 단계는 promise, request, responseObject, error를 받아:
-
promise가 이미 fulfilled된 경우 아무 동작도 하지 않는다.
-
request의 body가 null이 아니고 readable이면, body를 cancel한다(error로).
-
responseObject가 null이면 반환.
-
response를 responseObject의 response로 둔다.
-
response의 body가 null이 아니고 readable이면, body를 error로 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를 그 값으로 설정한다. -
activateAfter가 0보다 작으면
RangeError
를 throw한다. -
this의 관련 글로벌 객체의 연결된 document가 완전히 활성이 아니면,
TypeError
를 throw한다. -
request의 URL의 scheme이 HTTP(S) scheme이 아니면
TypeError
를 throw한다. -
request의 URL이 신뢰할 수 있는 URL이 아니면
TypeError
를 throw한다. -
request의 body가 null이 아니고, request의 body의 length가 null이면
TypeError
를 throw한다.body가
ReadableStream
객체인 요청은 지연할 수 없다. -
사용 가능한 deferred-fetch quota가 request의 client, request의 URL의 origin에 대해 request의 total request length보다 작으면, "
QuotaExceededError
"DOMException
을 throw한다. -
activated를 false로 둔다.
-
deferredRecord를 queue a deferred fetch를 request, activateAfter, 아래 단계(activated를 true로 설정함)로 실행한 결과로 둔다.
-
다음 abort 단계 추가를 requestObject의 signal에 대해 수행한다: deferredRecord의 invoke state를 "
aborted
"로 설정한다. -
새
FetchLaterResult
객체를 반환하며, activated getter 단계는 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 타입)과
본문(body) (바이트 시퀀스)로 이루어져
있습니다.
data:
URL 프로세서는 URL dataURL을 받아 다음 단계들을 실행합니다:
-
단언(Assert): dataURL의 scheme이 "
data
"임을 확인합니다. -
input을 URL serializer를 dataURL에 실행하고, exclude fragment를 true로 설정하여 얻은 결과로 합니다.
-
input에서 앞의 "
data:
"를 제거합니다. -
position을 input의 시작 위치로 설정합니다.
-
mimeType을 시퀀스 수집을 통해 U+002C(,)가 아닌 코드 포인트 시퀀스로 합니다.
-
앞뒤 ASCII 공백 제거를 mimeType에 적용합니다.
이 작업은 U+0020 SPACE 코드 포인트만 제거합니다.
-
position이 input의 끝을 지난 경우 실패를 반환합니다.
-
position을 1만큼 이동합니다.
-
encodedBody를 input의 나머지로 설정합니다.
-
body를 percent-decoding을 encodedBody에 적용한 값으로 합니다.
-
mimeType이 U+003B(;)로 끝나고, 0개 이상의 U+0020 SPACE 뒤에 ASCII 대소문자 구분 없이 "base64"가 있다면 다음을 수행합니다:
-
stringBody를 isomorphic decode를 body에 적용한 값으로 합니다.
-
body를 forgiving-base64 decode를 stringBody에 적용한 값으로 합니다.
-
body가 실패라면 실패를 반환합니다.
-
mimeType에서 마지막 6개의 코드 포인트를 제거합니다.
-
mimeType에서 마지막의 U+0020 SPACE 코드 포인트를 제거합니다.
-
mimeType에서 마지막 U+003B(;)를 제거합니다.
-
-
mimeType이 "
;
"로 시작하면 "text/plain
"을 mimeType 앞에 붙입니다. -
mimeTypeRecord를 MIME 타입 파싱을 mimeType에 적용한 값으로 합니다.
-
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 리다이렉트 처리
리다이렉트(응답의 상태 또는 내부 응답(있다면)의 상태가 리다이렉트 상태인 경우)는 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를
시작합니다(`mode`가 "websocket
"인 request를 사용). 이로 인해 많은 fetch 정책 결정(예: HTTP Strict Transport
Security (HSTS))을 공유하게 됩니다. 궁극적으로 fetch는 WebSockets에 전용 연결을 얻기 위해 호출됩니다. [WEBSOCKETS]
[HSTS]
Fetch는 이전에 WebSocket 연결 얻기 및 WebSocket 연결 설정을 직접 정의했으나, 현재는 모두 WebSockets에서 정의됩니다. [WEBSOCKETS]
다른 표준에서 fetch 사용하기
본질적으로 fetching은 request와 response의 교환입니다. 실제로 표준에서 올바르게 채택하고 사용하기에는 꽤 복잡한 메커니즘입니다. 이 섹션은 몇 가지 조언을 제공합니다.
반드시 도메인 전문가에게 검토를 받으세요.
작업 진행 중입니다.
요청 설정하기
fetching의 첫 번째 단계는 request를 생성하고, items를 채우는 것입니다.
HTTP에서 정의한 대로 request의 URL과 method를 먼저
설정하세요. 만약 `POST
` 또는 `PUT
` request에 body가 필요한 경우,
request의 body를 byte sequence로 설정하거나, 직접 생성한 ReadableStream
을
body의 stream으로 설정할 수 있습니다. [HTTP]
request의 destination을 destination
table 안내에 따라 선택하세요. Destinations는
Content Security Policy에 영향을 주고,
`Sec-Fetch-Dest
`
헤더 등 다양한 의미를 갖습니다. 새로운 기능에 destination이 필요하지만 destination table에 없다면,
이슈를
등록해 논의해주세요. [CSP]
request의 client를
작업 중인 environment settings object로 설정하세요. 웹에 노출된 API는 일반적으로 Web
IDL로 정의되며,
각 interface를 구현하는 객체마다
relevant settings object가 있습니다. 예를 들어,
request가 element와 연관된 경우, request의 client를 해당 element의 node
document의 relevant settings object로 설정합니다. JavaScript, HTML, CSS 또는 기타
Document
하위 리소스에 직접적으로 웹에 노출되는 모든 기능은 client가 있어야 합니다.
fetching이 직접적으로 웹에 노출되지 않는 경우,
예를 들어 현재 Window
나
Worker
에
의존하지 않고 백그라운드에서 전송되는 경우, request의 client를 null로 두고, request의 origin, policy
container, service-workers mode, referrer를 적절하게 설정하세요. 예를 들어
미리 environment settings object에서 복사하여 사용할 수 있습니다. 이런 고급
케이스에서는 Content Security Policy와 referrer policy 처리를 반드시 명확히 해야 합니다. 또한 콜백이 fetch 호출 및 응답 처리에서 parallel queue에 게시되므로, 동시성도 처리해야 합니다. [REFERRER] [CSP]
크로스 오리진 리소스 처리 방식을 잘 고민하세요. 어떤 기능은 same
origin에서만 동작해야 할 수 있으므로, request의 mode를 "same-origin
"으로 설정하세요. 그 외의 경우, 대부분의 새로운 웹 노출
기능은 mode를
"cors
"로 설정해야 합니다. 만약 기능이 웹에 노출되지 않거나, CORS 없이 크로스 오리진 리소스를 fetch해야 할 다른 이유가 있다면, 이슈를 등록해
논의하세요.
크로스 오리진 요청의 경우, credentials 포함 여부도
결정하세요. 포함해야 한다면 request의
credentials mode를 "include
"로 설정하세요.
fetch가 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에 대해 캐싱을 비활성화하고 싶다면,
cache
mode를 "default
" 외의 값으로 설정하세요.
요청이 리다이렉트를 지원할지 여부도 결정하세요. 지원하지 않을 경우 redirect mode를 "error
"로 설정하세요.
request의 나머지 파라미터들도 필요하다면 참고하세요. 이 파라미터들은 특수 목적에 더 자주 사용되며, 현행 표준의 § 2.2.5 Requests에서 자세히 설명되어 있습니다.
fetch 호출 및 응답 처리
request 외에도 fetch 연산은 몇 가지 선택적 인자를 받습니다. 알고리즘을 받는 인자에 대해서는: 해당 알고리즘은 태스크(또는 parallel queue에서 useParallelQueue가 true일 때)에서 호출됩니다.
request가 준비되면, fetch에 어떤 알고리즘을 전달할지 결정하려면, response를 어떻게 처리할지, 특히 어떤 단계에서 콜백을 받을지 결정하세요:
- 완료 시점에 처리
-
대부분의 호출자가 response를 이렇게 처리합니다. 예를 들어 스크립트와 스타일 리소스가 해당됩니다. response의 body를 전체 byte sequence로 읽은 뒤 호출자가 처리합니다.
response를 완료 시점에 처리하려면, fetch의 processResponseConsumeBody 인자에 알고리즘을 전달하세요. 전달된 알고리즘은 response와 body를 모두 읽은 결과(내부 response의 internal response)를 받게 됩니다. 두 번째 인자의 값 의미는 다음과 같습니다:
- null
- response의 body가 null인 경우로, network error가 발생했거나 null body status일 때입니다.
- failure
- response의 body 내용을 완전히 읽으려다 실패한 경우입니다. 예: I/O 오류 등.
- byte sequence
-
response의 internal response의 body를 완전히 읽은 경우입니다.
전체 내용을 담은 byte sequence는 request의 mode가 "
no-cors
"일 때도 전달됩니다. 이런 콘텐츠는 요청한 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를 파싱하고, 필요한 작업을 수행합니다.
-
- 헤더 먼저, 그 다음 청크 단위
-
예를 들어 비디오 재생이나 이미지 점진적 로딩 등 일부 경우에는, 호출자가 응답을 스트리밍 처리하며 청크 단위로 처리하고 싶을 수 있습니다. response는 헤더가 처리된 뒤 fetch 호출자에게 전달되며, 그 뒤로 호출자가 직접 처리합니다.
response를 청크 단위로 처리하려면, fetch의 processResponse 인자에 알고리즘을 전달하세요. 전달된 알고리즘은 응답 헤더가 수신되면 response를 인자로 받고, response의 body의 stream을 직접 읽어 남은 응답을 다운로드해야 합니다. 편의를 위해 processResponseEndOfBody 인자에도 알고리즘을 전달할 수 있는데, 이는 응답 및 body를 모두 읽은 뒤 호출됩니다. 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면 사용자에게 오류를 알립니다.
-
그 외에는 reader를 response의 body의 stream에 대해 얻고, extracting a MIME type으로 확인한 MIME 타입에 따라 적절히 처리합니다.
-
-
- 응답 무시
-
어떤 경우에는 response 자체가 필요 없는 경우도 있습니다. 예:
navigator.sendBeacon()
등. fetch에 콜백을 전달하는 것은 선택 사항이므로, 콜백을 생략하면 응답을 기대하지 않고 fetch가 동작합니다. 이런 경우 response의 body의 stream은 폐기되며, 호출자는 불필요하게 내용을 다운로드하는 것을 신경 쓸 필요가 없습니다.Fetch request를 호출합니다. URL은
https://fire-and-forget.example.com/
, method는 `POST
`, client는 this의 relevant settings object입니다.
응답 처리를 위한 콜백 외에도, fetch는 고급 케이스용 추가 콜백을 받습니다. processEarlyHintsResponse는 response의 status가 103일 때를 위한 것으로, 현재는 네비게이션만 처리됩니다. processRequestBodyChunkLength와 processRequestEndOfBody는 요청 body 업로드 진행 상황을 호출자에게 알려줍니다.
fetch 연산은 호출된 동일 스레드에서 시작한 뒤 내부 작업을 병렬로 실행합니다. 위 콜백들은 기본적으로 이벤트 루프(기본값은 client의 global object)에 게시됩니다. 응답을 병렬로 처리하고 메인 스레드와의 상호작용을 직접 처리하려면, fetch 호출 시 useParallelQueue를 true로 설정하세요.
진행 중인 fetch 조작하기
이미 시작된 fetch 연산을 조작하려면, fetch를 호출해 반환된 fetch controller를 사용하세요. 예를 들어, 사용자 또는 페이지 로직에 따라 fetch controller를 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, 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, 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로 제공됩니다.
이 문서는 현행 표준입니다. 특허 검토 버전에 관심 있으신 분들은 현행 표준 검토 초안을 참조하세요.