패치

현행 표준 — 마지막 갱신

참여:
GitHub whatwg/fetch (새 이슈, 열린 이슈)
Matrix에서 채팅
커밋:
GitHub whatwg/fetch/commits
이 커밋 기준 스냅샷
@fetchstandard
테스트:
web-platform-tests fetch/ (진행 중 작업)
번역 (비규범적):
日本語
简体中文
한국어

요약

패치 표준은 요청, 응답, 그리고 이를 연결하는 과정인 패칭을 정의합니다.

목표

이 표준의 목표는 웹 플랫폼 전반에 걸쳐 패칭을 통합하고, 이에 관련된 모든 것에 대해 일관된 처리를 제공하는 것입니다. 여기에는 다음이 포함됩니다:

이를 위해 HTTP `Origin` 헤더 의미를 원래 The Web Origin Concept에서 정의했던 것보다 대체합니다. [ORIGIN]

1. 서문

상위 관점에서 리소스를 패칭하는 것은 꽤 단순한 작업입니다. 요청이 들어가고, 응답이 나옵니다. 하지만 그 작업의 세부사항은 매우 복잡하며, 예전에는 명확하게 문서화되지 않았고 API마다 다르게 동작했습니다.

수많은 API가 리소스를 패치하는 기능을 제공합니다. 예를 들면 HTML의 imgscript 요소, CSS의 cursorlist-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 paramsstruct로, fetch 알고리즘에서 부기 용도로 사용됩니다. 다음과 같은 항목을 가집니다:

request
request.
요청 본문 청크 길이 처리 (기본값 null)
process request end-of-body (기본값 null)
process early hints response (기본값 null)
process response (기본값 null)
process response end-of-body (기본값 null)
process response consume body (기본값 null)
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 controllerstruct로, 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을 받아 다음을 실행합니다:

  1. Assert: controllerreport timing steps가 null이 아님을 확인합니다.

  2. controllerreport timing stepsglobal과 함께 호출합니다.

특정 fetch controller controller에 대해 다음 수동 리디렉트 처리를 하려면:

  1. Assert: controllernext manual redirect steps가 null이 아님을 확인합니다.

  2. controllernext manual redirect steps를 호출합니다.

fetch controller controller에 대해 전체 타이밍 정보 추출을 하려면:

  1. Assert: controllerfull timing info가 null이 아님을 확인합니다.

  2. controllerfull timing info를 반환합니다.

특정 fetch controller controller에 대해 선택적 error와 함께 abort 하려면:

  1. controllerstate를 "aborted"로 설정합니다.

  2. fallbackError를 "AbortError" DOMException으로 둡니다.

  3. error가 주어지지 않았다면 fallbackError로 설정합니다.

  4. serializedErrorStructuredSerialize(error)로 둡니다. 예외가 발생하면 serializedErrorStructuredSerialize(fallbackError)로 둡니다.

  5. controllerserialized abort reasonserializedError로 설정합니다.

null 또는 Record abortReasonrealm realm이 주어졌을 때 serialize된 abort reason 역직렬화는 다음과 같습니다:

  1. fallbackError를 "AbortError" DOMException으로 둡니다.

  2. deserializedErrorfallbackError로 둡니다.

  3. abortReason이 null이 아니면, deserializedErrorStructuredDeserialize(abortReason, realm)로 둡니다. 예외가 발생하거나 undefined를 반환하면 deserializedErrorfallbackError로 둡니다.

  4. deserializedError를 반환합니다.

fetch controller controller종료(terminate)하려면, controllerstate를 "terminated"로 설정합니다.

fetch params fetchParams는, 그 controllerstate가 "aborted"일 때 중단(aborted) 상태입니다.

fetch params fetchParams는, 그 controllerstate가 "aborted" 또는 "terminated"일 때 취소(canceled) 상태입니다.

fetch timing infostruct로, Resource TimingNavigation 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)
DOMHighResTimeStamp.
final connection timing info (기본값 null)
Null 또는 connection timing info.
server-timing headers (기본값 « »)
문자열의 list.
render-blocking (기본값 false)
불리언 값.

response body infostruct로, Resource TimingNavigation Timing에 필요한 정보를 유지합니다. 다음의 항목을 가집니다: [RESOURCE-TIMING] [NAVIGATION-TIMING]

encoded size (기본값 0)
decoded size (기본값 0)
숫자.
content type (기본값 빈 문자열)
ASCII 문자열.
content encoding (기본값 빈 문자열)
ASCII 문자열.

fetch timing info timingInfo가 주어졌을 때 불투명 타이밍 정보 생성은, timingInfostart timepost-redirect start timetimingInfostart time인 새로운 fetch timing info를 반환합니다.

알고리즘 algorithm, global object 또는 parallel queue taskDestination이 주어졌을 때 fetch 태스크 큐잉(queue a fetch task)은 다음과 같이 실행합니다:

  1. taskDestinationparallel queue라면, enqueue algorithmtaskDestination에 추가합니다.

  2. 그렇지 않으면, 글로벌 태스크(global task)networking task sourcetaskDestinationalgorithm으로 큐잉합니다.


정수 직렬화(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)가 주어졌을 때 다음을 수행합니다:

  1. positionStartposition으로 둡니다.

  2. value를 빈 문자열로 둡니다.

  3. Assert: inputposition에 있는 코드 포인트가 U+0022 (")임을 확인합니다.

  4. position을 1만큼 증가시킵니다.

  5. 다음이 참인 동안:

    1. U+0022 (") 또는 U+005C (\)가 아닌 코드 포인트 시퀀스 수집 결과를 input, position으로부터 value에 추가합니다.

    2. positioninput의 끝을 지난 경우, break합니다.

    3. quoteOrBackslashinputposition에 있는 코드 포인트로 둡니다.

    4. position을 1만큼 증가시킵니다.

    5. quoteOrBackslash가 U+005C (\)이면:

      1. positioninput의 끝을 지난 경우 U+005C (\)를 value에 추가하고 break합니다.

      2. inputposition에 있는 코드 포인트value에 추가합니다.

      3. position을 1만큼 증가시킵니다.

    6. 그 외의 경우:

      1. Assert: quoteOrBackslash가 U+0022 (")임을 확인합니다.

      2. Break.

  6. extract-value가 true라면 value를 반환합니다.

  7. inputpositionStart부터 position까지(포함)의 코드 포인트들을 반환합니다.

입력 출력 extract-value가 true일 때의 출력 최종 위치 변수
""\" ""\" "\" 2
""Hello" World" ""Hello"" "Hello" 7
""Hello \\ World\""" ""Hello \\ World\""" "Hello \ World"" 18

이 예시에서 위치 변수는 항상 0에서 시작합니다.

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)입니다.

  1. Assert: type은 "dictionary", "list", 또는 "item" 중 하나입니다.

  2. value헤더 목록에서 name을 가져온 결과로 둡니다.

  3. value가 null이면 null을 반환합니다.

  4. result구조화 필드 파싱(parsing structured fields)의 결과로 둡니다. input_stringvalue, header_typetype입니다.

  5. 파싱에 실패했다면 null을 반환합니다.

  6. result를 반환합니다.

구조화 필드 값 가져오기해당 헤더가 존재하지 않는 것과 이 구조화 필드 값으로 파싱에 실패한 것을 의도적으로 구분하지 않습니다. 이는 웹 플랫폼 전반에서 일관된 처리를 보장합니다.

구조화 필드 값 설정(set a structured field value) 을 하려면 튜플(tuple) (헤더 이름 name, 구조화 필드 값 structuredValue)과 헤더 목록 list가 주어집니다:

  1. serializedValue구조화 필드 직렬화(serializing structured fields) 알고리즘을 structuredValue에 적용한 결과로 둡니다.

  2. Set (name, serializedValue) 를 list에 적용합니다.

구조화 필드 값은 HTTP가(결국) 흥미롭고 효율적으로 직렬화할 수 있는 객체로 정의되어 있습니다. 현재 Fetch는 헤더 값바이트 시퀀스로 지원하므로, 이 객체들은 직렬화를 통해서만 헤더 목록에 설정할 수 있고, 파싱을 통해서만 헤더 목록에서 얻을 수 있습니다. 앞으로는 객체 상태가 끝까지 유지될 수도 있습니다. [RFC9651]


헤더 목록 list헤더를 포함(contains)하는지 여부는 헤더 이름 namelist포함헤더name바이트 대소문자 구분 없이 name과 일치하는 것이 있는지로 판단합니다.

가져오기(get)헤더 이름 name헤더 목록 list가 주어졌을 때 다음 단계를 실행합니다. 결과는 null 또는 헤더 값입니다.

  1. listname을 포함하지 않으면 null을 반환합니다.

  2. list에서 헤더name바이트 대소문자 구분 없이 name과 일치하는 모든 을 0x2C 0x20(쉼표+공백)으로 구분하여 순서대로 반환합니다.

가져오기, 디코드 및 분할(get, decode, and split)헤더 이름 name헤더 목록 list가 주어졌을 때 다음 단계를 실행합니다. 결과는 null 또는 리스트 ( 문자열(string) )입니다.

  1. valuename을 가져온 결과로 둡니다.

  2. value가 null이면 null을 반환합니다.

  3. get, decode, and splitvalue에 적용한 결과를 반환합니다.

다음은 get, decode, and split이 실제로 어떻게 동작하는지, name 인자가 `A`일 때의 예시입니다:

헤더(네트워크 상) 출력
A: nosniff,
« "nosniff", "" »
A: nosniff
B: sniff
A:
A:
B: sniff
« "" »
B: sniff
null
A: text/html;", x/x
« "text/html;", x/x" »
A: text/html;"
A: x/x
A: x/x;test="hi",y/y
« "x/x;test="hi"", "y/y" »
A: x/x;test="hi"
C: **bingo**
A: y/y
A: x / x,,,1
« "x / x", "", "", "1" »
A: x / x
A: ,
A: 1
A: "1,2", 3
« ""1,2"", "3" »
A: "1,2"
D: 4
A: 3

get, decode, and split헤더 값(header value) value에 대해 실행하려면 다음 단계를 따릅니다. 반환 값은 문자열 리스트(list of strings)입니다.

  1. inputisomorphic decoding value 결과로 둡니다.

  2. position위치 변수(position variable)로, input의 시작 위치로 지정합니다.

  3. values문자열 리스트(list of strings)로, 처음에는 « »로 둡니다.

  4. temporaryValue를 빈 문자열로 둡니다.

  5. 다음이 참인 동안 반복합니다:

    1. U+0022 (") 또는 U+002C (,)가 아닌 코드 포인트 시퀀스 수집 결과를 input, position으로부터 temporaryValue에 추가합니다.

      이 결과는 빈 문자열일 수도 있습니다.

    2. positioninput의 끝을 지나지 않았고, position 위치의 코드 포인트가 U+0022 (")이면:

      1. temporaryValueHTTP 따옴표 문자열 수집 결과를 input, position으로부터 추가합니다.

      2. position이 끝을 지나지 않았다면 continue합니다.
    3. temporaryValue의 시작과 끝에서 HTTP 탭 또는 공백을 모두 제거합니다.

    4. Append temporaryValuevalues에 추가합니다.

    5. temporaryValue를 빈 문자열로 설정합니다.

    6. positioninput의 끝을 지났다면 values를 반환합니다.

    7. Assert: inputposition 위치의 코드 포인트가 U+002C (,)임을 확인합니다.

    8. position을 1만큼 증가시킵니다.

특정 허용된 호출지(blessed call sites)를 제외하고, 위 알고리즘을 직접 호출하지 않아야 합니다. 대신 get, decode, and split을 사용하세요.

append헤더(header) (name, value)를 헤더 목록(header list) list에 추가하는 알고리즘입니다:

  1. listname을 포함하면, name을 첫 번째 해당 헤더name으로 설정합니다.

    이렇게 하면 list에 이미 존재하는 헤더name의 대소문자가 재사용됩니다. 여러 개가 일치하면 헤더name은 모두 동일합니다.

  2. Append (name, value)를 list에 추가합니다.

delete헤더 이름(header name) name헤더 목록(header list) list에서 제거하는 알고리즘입니다. 이때 헤더name바이트 대소문자 구분 없이 name과 일치하는 모든 헤더를 list에서 제거합니다.

set헤더(header) (name, value)를 헤더 목록(header list) list에 설정하는 방법입니다:

  1. listname을 포함하면, 첫 번째 해당 헤더(header)값(value)value로 설정하고, 나머지 해당 헤더들은 제거한다.

  2. 그렇지 않으면, append (name, value)를 list에 추가합니다.

combine헤더(header) (name, value)를 헤더 목록(header list) list에 결합하는 방법입니다:

  1. listname을 포함하면, 첫 번째 해당 헤더value 뒤에 0x2C 0x20(쉼표+공백), value를 순서대로 이어붙입니다.

  2. 그렇지 않으면, append (name, value)를 list에 추가합니다.

combineXMLHttpRequestWebSocket 프로토콜 핸드셰이크에서 사용됩니다.

헤더 이름을 정렬된 소문자 집합으로 변환(convert header names to a sorted-lowercase set)하려면, 리스트(list) headerNames가 주어졌을 때 다음 단계를 따릅니다. 반환값은 순서 있는 집합(ordered set)헤더 이름(header name)입니다.

  1. headerNamesSet을 새로운 순서 있는 집합으로 둡니다.

  2. name에 대해, 바이트 소문자화(byte-lowercasing) nameheaderNamesSetappend합니다.

  3. 오름차순 정렬headerNamesSet바이트 비교(byte less than)로 적용한 결과를 반환합니다.

sort and combine헤더 목록(header list) list를 입력받아, 다음 단계를 실행합니다. 반환값은 헤더 목록(header list)입니다.

  1. headers헤더 목록(header list)으로 둡니다.

  2. names헤더 이름을 정렬된 소문자 집합으로 변환한 결과로 둡니다. 이때 list헤더들의 이름을 사용합니다.

  3. name에 대해:

    1. name이 `set-cookie`라면:

      1. valueslist에서 헤더name바이트 대소문자 구분 없이 name과 일치하는 모든 의 리스트로 둡니다.

      2. value에 대해 Append (name, value)를 headers에 추가합니다.

    2. 그 외의 경우:

      1. valuelist에서 name을 가져온 결과로 둡니다.

      2. Assert: value가 null이 아님을 확인합니다.

      3. Append (name, value)를 headers에 추가합니다.

  4. headers를 반환합니다.


헤더(header)튜플(tuple)로, 이름(name) (헤더 이름)과 값(value) (헤더 값)으로 구성됩니다.

헤더 이름(header name)바이트 시퀀스로, field-name 토큰 생성식을 만족합니다.

헤더 값(header value)바이트 시퀀스로, 다음 조건을 모두 만족해야 합니다:

헤더 값의 정의는 field-value 토큰 생성식을 따르지 않는 것이, 배포된 콘텐츠와 호환되지 않기 때문입니다.

헤더 값 정규화(normalize)바이트 시퀀스 potentialValue에서 선행 및 후행 HTTP 공백 바이트를 제거하는 것입니다.


헤더 (name, value) 가 CORS-안전 목록 요청 헤더(CORS-safelisted request-header)인지 판단하려면 다음 단계를 실행합니다:

  1. value길이가 128을 초과하면 false를 반환합니다.

  2. 바이트 소문자화(Byte-lowercase)name에 따라 분기합니다:

    `accept`

    valueCORS-비안전 요청 헤더 바이트가 있으면 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`
    1. valueCORS-비안전 요청 헤더 바이트가 있으면 false를 반환합니다.

    2. mimeType파싱(parsing)등가 디코딩(isomorphic decoding) value 결과로 둡니다.

    3. mimeType이 실패(failure)라면 false를 반환합니다.

    4. mimeTypeessence가 "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`
    1. rangeValue단일 range 헤더 값 파싱(parsing a single range header value)value와 false를 넘긴 결과로 둡니다.

    2. rangeValue가 실패(failure)면 false를 반환합니다.

    3. rangeValue[0]이 null이면 false를 반환합니다.

      웹 브라우저는 `bytes=-500`와 같은 range를 내보내지 않으므로 이 알고리즘은 그런 경우를 safelist하지 않습니다.

    기타

    false를 반환합니다.

  3. true를 반환합니다.

`Content-Type` 헤더 safelist에는 제한적 예외가 있습니다. 자세한 내용은 CORS 프로토콜 예외를 참고하세요.

CORS-비안전 요청 헤더 바이트(CORS-unsafe request-header byte)는 바이트 byte가 다음 중 하나에 해당할 때입니다:

CORS-비안전 요청 헤더 이름(CORS-unsafe request-header names)헤더 목록 headers에 대해 다음과 같이 결정합니다:

  1. unsafeNames를 새 리스트로 둡니다.

  2. potentiallyUnsafeNames를 새 리스트로 둡니다.

  3. safelistValueSize를 0으로 둡니다.

  4. headersheader에 대해:

    1. headerCORS-안전 목록 요청 헤더가 아니면, append headernameunsafeNames에 추가합니다.

    2. 그 밖의 경우, headernamepotentiallyUnsafeNames에 추가하고, safelistValueSizeheadervalue길이만큼 더합니다.

  5. safelistValueSize가 1024를 초과하면 potentiallyUnsafeNamesnameappendunsafeNames에 추가합니다.

  6. 헤더 이름을 정렬된 소문자 집합으로 변환unsafeNames를 반환합니다.

CORS non-wildcard 요청 헤더 이름(CORS non-wildcard request-header name)헤더 이름바이트 대소문자 구분 없이 `Authorization`와 일치하는 것입니다.

특권 no-CORS 요청 헤더 이름(privileged no-CORS request-header name)헤더 이름바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:

이들은 특권 API에서 설정할 수 있으며, 관련 요청 객체가 복사될 때는 보존되지만, 권한이 없는 API가 요청을 수정하는 경우 제거됩니다.

`Range` 헤더는 주로 다운로드미디어 패치에서 사용됩니다.

특정 요청에 range 헤더 추가를 위한 헬퍼가 제공됩니다.

CORS-안전 목록 응답 헤더 이름(CORS-safelisted response-header name)리스트헤더 이름 list에 대해, 다음 중 하나와 바이트 대소문자 구분 없이 일치하는 것입니다:

no-CORS-안전 목록 요청 헤더 이름(no-CORS-safelisted request-header name)헤더 이름바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:

헤더 (name, value)가 no-CORS-안전 목록 요청 헤더(no-CORS-safelisted request-header)인지 판단하려면 다음 단계를 실행합니다:

  1. nameno-CORS-안전 목록 요청 헤더 이름이 아니면 false를 반환합니다.

  2. (name, value)가 CORS-안전 목록 요청 헤더인지 여부를 반환합니다.

헤더 (name, value)가 금지된 요청 헤더(forbidden request-header)인지 판단하려면 다음 단계가 true를 반환하면 됩니다:

  1. name이 다음 중 하나와 바이트 대소문자 구분 없이 일치하면:

    true를 반환합니다.

  2. name바이트 소문자화하여, proxy- 또는 sec-으로 시작하면 true를 반환합니다.

  3. name이 다음 중 하나와 바이트 대소문자 구분 없이 일치하면:

    • `X-HTTP-Method`
    • `X-HTTP-Method-Override`
    • `X-Method-Override`

    다음 절차를 실행합니다:

    1. parsedValuesget, decode, and split value의 결과로 둡니다.

    2. parsedValuesmethod에 대해, isomorphic encodingmethod금지된 메서드(forbidden method)라면 true를 반환합니다.

  4. false를 반환합니다.

이 헤더들은 사용자 에이전트가 완전히 제어할 수 있도록 금지됩니다.

헤더 이름이 `Sec-`로 시작하는 경우, 헤더fetch 등 개발자가 헤더를 제어할 수 있는 API에 의해 사용될 때, 새 헤더가 안전하게 도입될 수 있도록 예약되어 있습니다. 예: XMLHttpRequest. [XHR]

`Set-Cookie` 헤더는 의미상 응답 헤더이므로 요청에서는 쓸모가 없습니다. `Set-Cookie` 헤더는 결합(combine)될 수 없으므로, Headers 객체에서 더 복잡하게 처리해야 합니다. 여기서 금지하는 이유는 이 복잡성이 요청으로 새어 나가는 것을 막기 위함입니다.

금지된 응답 헤더 이름(forbidden response-header name)헤더 이름바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:

요청 본문 헤더 이름(request-body-header name)헤더 이름바이트 대소문자 구분 없이 다음 중 하나와 일치하는 것입니다:


헤더 값 추출(extract header values)헤더(header) header가 주어졌을 때 다음 단계를 실행합니다:

  1. headervalueABNF 기준으로 headername에 대해 파싱에 실패하면 failure를 반환합니다.

  2. headervalueABNF 기준으로 파싱하여 나온 하나 이상의 을 반환합니다.

헤더 목록 값 추출(extract header list values)헤더 이름 name헤더 목록(header list) list가 주어졌을 때 다음 단계를 실행합니다:

  1. listname을 포함하지 않으면 null을 반환합니다.

  2. name에 대한 ABNF가 단일 헤더(header)만 허용하고, listname을 중복 포함하면 failure를 반환합니다.

    다른 오류 처리가 필요하다면, 먼저 원하는 헤더를 추출하세요.

  3. values를 빈 리스트로 둡니다.

  4. listname을 포함하는 모든 헤더(header) header에 대해:

    1. extract헤더 값 추출header에 실행한 결과로 둡니다.

    2. extract가 failure면 failure를 반환합니다.

    3. extract각 값을 순서대로 values에 추가합니다.

  5. values를 반환합니다.

콘텐츠 범위 생성(build a content range)은 정수 rangeStart, 정수 rangeEnd, 정수 fullLength가 주어졌을 때 다음 단계를 실행합니다:

  1. contentRange를 `bytes `로 둡니다.

  2. rangeStart직렬화등가 인코딩(isomorphic encoded) 하여 contentRange에 추가합니다.

  3. 0x2D (-)를 contentRange에 추가합니다.

  4. rangeEnd직렬화등가 인코딩 하여 contentRange에 추가합니다.

  5. 0x2F (/)를 contentRange에 추가합니다.

  6. fullLength직렬화등가 인코딩 하여 contentRange에 추가합니다.

  7. contentRange를 반환합니다.

단일 range 헤더 값 파싱(parse a single range header value)바이트 시퀀스 value와 불리언 allowWhitespace가 주어졌을 때 다음을 실행합니다:

  1. data등가 디코딩(isomorphic decoding) value 결과로 둡니다.

  2. data가 "bytes"로 시작하지 않으면 failure를 반환합니다.

  3. position위치 변수(position variable)로, data의 5번째 코드 포인트 위치로 둡니다.

  4. allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.

  5. dataposition 위치 코드 포인트가 U+003D (=)가 아니면 failure를 반환합니다.

  6. position을 1만큼 증가시킵니다.

  7. allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.

  8. rangeStartASCII 숫자(ASCII digits) 시퀀스를 data, position에서 수집한 결과로 둡니다.

  9. rangeStartValuerangeStart가 빈 문자열이 아니면 10진수로 해석한 값, 아니면 null로 둡니다.

  10. allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.

  11. dataposition 위치 코드 포인트가 U+002D (-)가 아니면 failure를 반환합니다.

  12. position을 1만큼 증가시킵니다.

  13. allowWhitespace가 true라면, HTTP 탭 또는 공백 시퀀스를 data, position에서 수집합니다.

  14. rangeEndASCII 숫자(ASCII digits) 시퀀스를 data, position에서 수집한 결과로 둡니다.

  15. rangeEndValuerangeEnd가 빈 문자열이 아니면 10진수로 해석한 값, 아니면 null로 둡니다.

  16. positiondata의 끝을 지나지 않았다면 failure를 반환합니다.

  17. rangeEndValuerangeStartValue가 모두 null이면 failure를 반환합니다.

  18. rangeStartValuerangeEndValue가 모두 숫자이고, rangeStartValuerangeEndValue보다 크면 failure를 반환합니다.

  19. (rangeStartValue, rangeEndValue)를 반환합니다.

    range 끝이나 시작이 생략될 수 있습니다. 예: `bytes=0-` 또는 `bytes=-500`도 유효한 range입니다.

단일 range 헤더 값 파싱은 허용된 range 헤더 값의 일부만 성공하지만, 미디어 요청이나 다운로드 재개 등에서 사용자 에이전트가 가장 자주 사용하는 형식입니다. 이 range 헤더 값 형식은 range 헤더 추가를 통해 설정할 수 있습니다.


기본 `User-Agent` 값(default `User-Agent` value)구현 정의(implementation-defined) 헤더 값입니다 (`User-Agent` 헤더용).

웹 호환성 문제로 인해, 웹 브라우저는 이 값이 `Mozilla/5.0 (`로 시작하도록 하고, 일반적으로 다른 웹 브라우저를 따라하도록 강하게 권장됩니다.

문서 `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)은 다음으로 구성됩니다:

복제(clone)본문 body에 대해 실행하려면 다음을 따릅니다:

  1. « out1, out2 »를 teeing body스트림의 결과로 둡니다.

  2. body스트림out1으로 설정합니다.

  3. 나머지 멤버는 body에서 복사하고, 본문스트림out2로 하여 반환합니다.

바이트 시퀀스 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는 예외를 인자로 받는 알고리즘이어야 합니다.

  1. taskDestination이 null이면 새 parallel queue 시작 결과를 taskDestination로 둡니다.

  2. reader리더(getting a reader)body스트림에 대해 구합니다.

    이 동작은 예외를 발생시키지 않습니다.

  3. 점진적 읽기 루프(incrementally-read loop)reader, taskDestination, processBodyChunk, processEndOfBody, processBodyError로 실행합니다.

점진적 읽기 루프(incrementally-read loop)를 실행하려면, ReadableStreamDefaultReader 객체 reader, parallel queue 또는 global object taskDestination, 알고리즘 processBodyChunk, 알고리즘 processEndOfBody, 알고리즘 processBodyError가 주어집니다:

  1. readRequest를 다음 read request로 둡니다:

    chunk steps (chunk)
    1. continueAlgorithm을 null로 둡니다.

    2. chunkUint8Array 객체가 아니라면, continueAlgorithm을 다음 단계로 설정합니다: processBodyErrorTypeError와 함께 실행.

    3. 그 외의 경우:

      1. bytes복사(copy)chunk로 둡니다.

        구현은 이 복사를 피하는 전략을 사용할 것을 강력히 권장합니다.

      2. continueAlgorithm을 다음 단계로 설정합니다:

        1. processBodyChunkbytes로 실행.

        2. 점진적 읽기 루프reader, taskDestination, processBodyChunk, processEndOfBody, processBodyError로 재귀 호출.

    4. fetch 태스크 큐잉continueAlgorithm, taskDestination에 실행합니다.

    close steps
    1. fetch 태스크 큐잉processEndOfBody, taskDestination에 실행합니다.

    error steps (e)
    1. fetch 태스크 큐잉processBodyErroretaskDestination로 실행합니다.

  2. 청크 읽기(Read a chunk)readerreadRequest로 실행합니다.

완전히 읽기(fully read)본문(body) body, 알고리즘 processBody, 알고리즘 processBodyError, 옵션으로 null, parallel queue 또는 global object taskDestination (기본값 null)이 주어졌을 때 다음을 실행합니다. processBody바이트 시퀀스를 인자로 받는 알고리즘이어야 하며, processBodyError는 예외(옵션)를 인자로 받을 수 있는 알고리즘이어야 합니다.

  1. taskDestination이 null이면 새 parallel queue 시작 결과를 taskDestination로 둡니다.

  2. successStepsfetch 태스크 큐잉processBodybytes, taskDestination로 실행하는 알고리즘으로 둡니다.

  3. errorStepsfetch 태스크 큐잉processBodyErrorexception, taskDestination로 실행하는 알고리즘으로 둡니다.

  4. reader리더(getting a reader)body스트림에 대해 구합니다. 예외가 발생하면 errorSteps를 그 예외와 함께 실행하고 종료합니다.

  5. 모든 바이트 읽기(Read all bytes)reader, successSteps, errorSteps로 실행합니다.


타입이 있는 본문(body with type)튜플로, 본문(body) (body)과 타입(type) (헤더 값 또는 null)으로 구성됩니다.


콘텐츠 코딩 처리(handle content codings)codingsbytes가 주어졌을 때 다음 단계를 수행합니다:

  1. codings가 지원되지 않으면 bytes를 반환합니다.

  2. HTTP에서 설명한 대로 codingsbytes를 디코딩한 결과를 반환합니다. 디코딩 중 오류가 발생하면 failure를 반환합니다. [HTTP]

2.2.5. 요청

이 절은 요청이 어떻게 동작하는지 자세히 문서화합니다. 시작하려면 요청 설정을 참고하세요.

fetch의 입력값은 요청(request)입니다.

요청은 연관된 메서드(method)를 가집니다. (method) 별도의 언급이 없으면 `GET`입니다.

리다이렉트 중 HTTP fetch에서 설명된 대로 `GET`으로 변경될 수 있습니다.

요청은 연관된 URL (URL)을 가집니다.

구현은 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 documentenvironment 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 지시어에 대해 요청clientglobal 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 containerfetch 중에 변경됩니다. 이를 통해 표준에서 요청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 modefetchcredentials의 흐름을 제어한다. 요청mode가 "navigate"이면 credentials mode는 "include"로 간주되며, fetch는 현재 다른 값을 고려하지 않는다. HTML이 이 부분을 변경하면 이 표준도 그에 맞게 변경되어야 한다.

요청은 연관된 use-URL-credentials 플래그 를 가진다. 별도 언급이 없으면 설정되지 않은 상태다.

이 플래그가 설정된 경우, 요청URLusernamepassword가 있고, 해당 인증 항목(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`, fetchcache 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 flagfetch 알고리즘에서 부가적인 부기용으로 사용된다.


서브리소스 요청(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-taintrequest request에 대해 계산하려면 다음 단계를 따른다. 반환값은 "same-origin", "same-site", "cross-site" 중 하나이다.

  1. Assert: requestorigin이 "client"가 아님을 확인한다.

  2. lastURL을 null로 둔다.

  3. taint를 "same-origin"으로 둔다.

  4. requestURL 목록url에 대해:

    1. lastURL이 null이면 lastURLurl로 설정하고 continue한다.

    2. urloriginlastURLoriginsame site가 아니고, requestoriginlastURLoriginsame site가 아니면, "cross-site"를 반환한다.

    3. urloriginlastURLoriginsame origin이 아니고, requestoriginlastURLoriginsame origin이 아니면, taint를 "same-site"로 설정한다.

    4. lastURLurl로 설정한다.

  5. taint를 반환한다.

요청 origin 직렬화(Serializing a request origin)request request가 주어졌을 때 다음을 실행한다:

  1. Assert: requestorigin이 "client"가 아님을 확인한다.

  2. requestredirect-taint가 "same-origin"이 아니면, "null"을 반환한다.

  3. requestoriginascii 직렬화하여 반환한다.

요청 origin 바이트 직렬화(Byte-serializing a request origin)request request가 주어졌을 때, 요청 origin 직렬화의 결과를 등가 인코딩(isomorphic encoded)하여 반환한다.


복제(clone)request request에 대해 실행하려면 다음을 따른다:

  1. newRequestrequest의 복사본(단, body는 제외)으로 둔다.

  2. requestbody가 null이 아니면, newRequestbodyclone requestbody 결과로 설정한다.

  3. newRequest를 반환한다.


range 헤더 추가(add a range header)request request에, 정수 first와 옵션 정수 last와 함께 하려면 다음을 따른다:

  1. Assert: last가 주어졌다면, firstlast 이하임을 확인한다.

  2. rangeValue를 `bytes=`로 둔다.

  3. 직렬화등가 인코딩firstrangeValue에 추가한다.

  4. 0x2D (-)를 rangeValue에 추가한다.

  5. last가 주어졌다면, 직렬화등가 인코딩하여 rangeValue에 추가한다.

  6. 헤더 append(`Range`, rangeValue)를 requestheader list에 추가한다.

range 헤더는 양끝 포함 바이트 범위를 나타낸다. 즉, first가 0이고 last가 500이면 501 바이트 범위다.

여러 응답을 하나의 논리 리소스로 결합하는 기능은 역사적으로 보안 버그의 원인이었다. 부분 응답을 다루는 기능을 설계할 때는 반드시 보안 리뷰를 받을 것.


보고용 응답 URL 직렬화(serialize a response URL for reporting)response response에 대해 다음을 실행한다:

  1. Assert: responseURL list비어있지 않음을 확인한다.

  2. urlresponseURL list[0]의 복사본으로 둔다.

    이는 responseURL이 아니다. 리다이렉트 대상 정보 노출을 피하기 위함(이와 유사한 CSP 보고에 대한 고려도 참고). [CSP]

  3. username 설정url과 빈 문자열로 실행한다.

  4. password 설정url과 빈 문자열로 실행한다.

  5. 직렬화(serialization)url에 대해(단, fragment 제외 옵션 포함) 반환한다.

Cross-Origin-Embedder-Policy가 credentials를 허용하는지 확인하려면, request request가 주어졌을 때 다음을 실행한다:

  1. Assert: requestorigin이 "client"가 아님을 확인한다.

  2. requestmode가 "no-cors"가 아니면 true를 반환한다.

  3. requestclient가 null이면 true를 반환한다.

  4. requestclientpolicy containerembedder policyvalue가 "credentialless"가 아니면 true를 반환한다.

  5. requestoriginrequestcurrent URLorigin동일 출처이고, requestredirect-taint가 "same-origin"이 아니면 true를 반환한다.

  6. 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이다.

네트워크 응답의 sourcelength 개념은 항상 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에 대해 생성하려면:

  1. Assert: fetchParams취소(canceled) 상태임을 확인한다.

  2. 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 responseopaque-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 responseopaque-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에 대해 실행하려면:

  1. responsefiltered response라면, 동일한 filtered response를 새로 만들되, 내부 응답response내부 응답복제한 것으로 한다.

  2. newResponseresponse의 복사본(단, body는 제외)으로 둔다.

  3. responsebody가 null이 아니면, newResponsebody복제 responsebody로 설정한다.

  4. newResponse를 반환한다.


신선한 응답(fresh response)이란, 응답(response)현재 age(current age)신선도 수명(freshness lifetime) 이내에 있는 경우를 말합니다.

stale-while-revalidate 응답(stale-while-revalidate response)이란, 응답(response)신선한 응답(fresh response)이 아니고, 현재 agestale-while-revalidate 수명 이내인 경우를 말합니다. [HTTP-CACHING] [STALE-WHILE-REVALIDATE]

오래된 응답(stale response)이란 응답(response)신선한 응답이나 stale-while-revalidate 응답이 아닌 경우입니다.


location URL응답(response) response와 null 또는 ASCII 문자열 requestFragment가 주어졌을 때 아래 단계를 따라 값을 반환합니다. 반환 값은 null, failure, 또는 URL입니다.

  1. responsestatus리다이렉트 상태(redirect status)가 아니면 null을 반환합니다.

  2. locationextracting header list values에 `Location`과 responseheader list를 넘겨 호출한 결과로 둡니다.

  3. locationheader value라면, location파싱(parsing)한 결과로, base는 responseURL로 설정합니다.

    responseResponse 생성자로 만들어진 경우 responseURL은 null이므로, location절대 URL+fragment 문자열이어야만 파싱이 성공합니다.

  4. locationURL이고 fragment가 null이면, locationfragmentrequestFragment로 설정합니다.

    이렇게 하면 모든(합성 포함) 응답이 HTTP에서 정의된 리다이렉트 처리 모델을 따르게 됩니다. [HTTP]

  5. location을 반환합니다.

location URL 알고리즘은 오직 이 표준 및 HTML의 수동 리다이렉트 처리 navigate 알고리즘에서만 사용됩니다. [HTML]

2.2.7. 기타

잠재적 destination(potential destination)은 "fetch"이거나 빈 문자열이 아닌 destination이다.

변환(translate)잠재적 destination potentialDestination에 대해 실행하려면 다음을 따른다:

  1. potentialDestination이 "fetch"라면 빈 문자열을 반환한다.

  2. Assert: potentialDestinationdestination임을 확인한다.

  3. 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 recordstruct이며, 다음 항목(items)을 가진다:

request
request.
controller
fetch controller 또는 null.

deferred fetch recordstruct이며, 나중에 fetch를 실행하는 데 필요한 상태를 저장하는데 사용된다(예: 문서가 언로드되거나 fully active가 아니게 될 때 등). 다음 항목(items)을 가진다:

request
request.
notify invoked
인자를 받지 않는 알고리즘.
invoke state (기본값 "pending")
"pending", "sent", "aborted" 중 하나.

fetch group fetchGroup종료된 경우:

  1. fetch record recordfetchGroupfetch records에 있다면, recordcontroller가 null이 아니고, recordrequestdone flag가 unset이고, keepalive가 false라면, terminate recordcontroller를 실행한다.

  2. Process deferred fetchesfetchGroup에 대해 실행한다.

2.5. 도메인 해석

(This is a tracking vector.) origin 해석(resolve an origin)을 하려면, 네트워크 파티션 키(network partition key) keyorigin origin이 주어진다:

  1. originhostIP 주소라면, « originhost »를 반환한다.

  2. originhostpublic suffix가 "localhost" 또는 "localhost."라면, « ::1, 127.0.0.1 »를 반환한다.

  3. origin을 하나 이상의 IP 주소집합(set)으로 변환하는 구현 정의(implementation-defined) 작업을 수행한다.

    또한 단순히 IP 주소만 얻는 것 외에, 다른 연결 정보도 얻는 작업이 구현 정의로 수행될 수 있다. 예를 들어, originschemeHTTP(S) scheme라면, 구현체는 HTTPS RR에 대한 DNS 질의를 할 수도 있다. [SVCB]

    이 작업이 성공하면, IP 주소의 집합(set)과 추가 구현 정의 정보를 반환한다.

  4. 실패(failure)를 반환한다.

origin 해석 결과는 캐시될 수 있다. 캐시할 경우, key를 캐시 키의 일부로 사용해야 한다.

이 작업은 일반적으로 DNS를 포함하므로, DNS 서버에서 key를 고려하지 않고 캐시가 발생할 수 있다. 구현체에 따라 로컬에서 key를 고려할 수 없는 경우도 있다. [RFC1035]

IP 주소의 반환 순서는 origin 해석 알고리즘 호출마다 다를 수 있다.

(캐시 키를 제외한) 세부 사항은 현행 표준이 정의하는 시스템과 직접적으로 관련이 없으므로 구체적으로 명시하지 않는다. 다른 문서에서 이 프리미티브에 의존하고자 한다면, 반드시 현행 표준 커뮤니티와 충분한 논의가 선행되어야 한다.

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)
DOMHighResTimeStamp.
ALPN 협상 프로토콜(ALPN negotiated protocol) (기본값: 빈 바이트 시퀀스)
바이트 시퀀스.

connection timing info clamp/coarsen 알고리즘은 connection timing info timingInfo, DOMHighResTimeStamp defaultStartTime, 불리언 crossOriginIsolatedCapability가 주어졌을 때 다음을 실행한다:

  1. timingInfoconnection start timedefaultStartTime보다 작으면, 모든 시각 값을 defaultStartTime으로 하고 ALPN negotiated protocoltimingInfo의 값을 사용한 새로운 connection timing info를 반환한다.

  2. 아니라면 각 시각 값을 coarsen time 알고리즘으로 crossOriginIsolatedCapability를 넘겨 처리한 값을 사용하고, ALPN negotiated protocoltimingInfo의 값을 사용한 새로운 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)로 호출한다:

  1. new가 "no"면:

    1. connections를 연결 풀에서 keykey, originurlorigin, credentialscredentialsconnection 집합으로 한다.

    2. connections가 비어 있지 않고 requireUnreliable이 false면 그 중 하나를 반환한다.

    3. connections 중에서 불안정 전송(unreliable transport, 예: HTTP/3)을 지원하는 connection이 있으면 그것을 반환한다.

  2. proxiesurl에 대한 프록시를 구현 정의 방식으로 찾은 결과로 한다. 프록시가 없으면 proxies는 « "DIRECT" »가 된다.

    이 단계에서는 Web Proxy Auto-Discovery Protocol(WPAD)이나 proxy auto-config(PAC) 등 비표준 기술도 사용된다. "DIRECT" 값은 해당 url에 프록시를 사용하지 않음을 의미한다.

  3. timingInfo를 새로운 connection timing info로 둔다.

  4. proxiesproxy에 대해:

    1. timingInfodomain lookup start timeunsafe shared current time으로 설정한다.

    2. hosts를 « urloriginhost »로 한다.

    3. proxy가 "DIRECT"면, hostsresolve an origin 알고리즘에 keyurlorigin을 넘겨 얻은 결과로 설정한다.

    4. hosts가 failure면 continue한다.

    5. timingInfodomain lookup end timeunsafe shared current time으로 설정한다.

    6. connection을 아래 단계로 얻는다: create a connection 알고리즘에 key, urlorigin, credentials, proxy, 구현 정의 host (from hosts), timingInfo, requireUnreliable를 넘겨서, 여러 번 병렬로 실행하고 하나 이상이 성공할 때까지 기다린다. 구현 정의 방식으로 반환값 하나를 선택해 반환한다. 나머지 connection들은 닫을 수 있다.

      즉, 구현체는 IP 주소 여러 개를 pick & race 하거나, IPv6를 우선하거나, 타임아웃 시 재시도하는 등 다양한 전략을 쓸 수 있다.

    7. connection이 failure면 continue한다.

    8. new가 "yes-and-dedicated"가 아니면 appendconnection을 연결 풀에 추가한다.

    9. connection을 반환한다.

  5. 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이 주어졌을 때 다음을 실행한다:

  1. timingInfoconnection start timeunsafe shared current time으로 설정한다.

  2. connection을 새 connection으로 만들고, keykey, originorigin, credentialscredentials, timing infotimingInfo로 한다. record connection timing infoconnection에 대해 실행하고, 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를 반환한다.

  3. timingInfoALPN negotiated protocolconnection의 ALPN Protocol ID로 설정한다. 단, 아래 주의사항에 유의: [RFC7301]

    • 프록시를 사용할 경우, 터널 연결이 성립하면 해당 터널링 프로토콜의 ALPN Protocol ID로, 아니면 프록시까지의 첫 홉의 ALPN Protocol ID로 설정한다.

    • 실험적·비공식 프로토콜을 쓰면, 실제 사용된 ALPN Protocol ID를 사용해야 한다. ALPN이 협상에 사용되지 않았다면 다른 설명 문자열을 써도 된다.

      timingInfoALPN negotiated protocol은 네트워크 프로토콜을 식별하기 위한 정보이며, ALPN이 협상에 쓰이지 않아도 실제 사용 프로토콜의 ALPN ID를 써야 한다.

    ALPN Protocol ID 목록은 IANA에서 관리한다. ALPN Protocol IDs 참고.

  4. connection을 반환한다.


connection timing info 기록(record connection timing info) 알고리즘은 connection connection에 대해 timingInfoconnectiontiming info로 두고, 다음 사항을 관찰한다:

connection timing info clamp/coarsen 알고리즘은 재사용된 연결의 상세 정보 노출 방지 및 시간값 coarsen을 보장한다.

2.7. 네트워크 파티션 키(Network partition keys)

네트워크 파티션 키(network partition key)site와 null 또는 구현 정의 값을 요소로 하는 튜플이다.

네트워크 파티션 키 결정(determine the network partition key) 알고리즘은 environment environment가 주어졌을 때 다음을 따른다:

  1. topLevelOriginenvironmenttop-level origin으로 둔다.

  2. topLevelOrigin이 null이면, topLevelOriginenvironmenttop-level creation URLorigin으로 둔다.

  3. Assert: topLevelOriginorigin이다.

  4. topLevelSiteobtain a site 알고리즘을 topLevelOrigin에 대해 실행한 결과로 둔다.

  5. secondKey를 null 또는 구현 정의 값 중 하나로 둔다.

    secondKey는 의도적으로 다소 모호하게 정의되어 있다. 세부 내용은 아직 발전 중임. issue #1035 참고.

  6. (topLevelSite, secondKey)를 반환한다.

네트워크 파티션 키 결정(determine the network partition key) 알고리즘은 request request가 주어졌을 때 다음을 따른다:

  1. requestreserved client가 null이 아니면, 네트워크 파티션 키 결정 알고리즘을 requestreserved client에 대해 실행한 결과를 반환한다.

  2. requestclient가 null이 아니면, 네트워크 파티션 키 결정 알고리즘을 requestclient에 대해 실행한 결과를 반환한다.

  3. null을 반환한다.

2.8. HTTP 캐시 파티션(HTTP cache partitions)

HTTP 캐시 파티션 결정(determine the HTTP cache partition) 알고리즘은 request request가 주어졌을 때 다음을 따른다:

  1. key네트워크 파티션 키 결정 알고리즘을 request에 대해 실행한 결과로 둔다.

  2. key가 null이면 null을 반환한다.

  3. key와 연관된 고유한 HTTP 캐시를 반환한다. [HTTP-CACHING]

2.9. 포트 차단(Port blocking)

새로운 프로토콜은 ALPN을 사용해 TLS를 통해 프로토콜을 협상함으로써 포트 차단의 필요성을 피할 수 있다. 이 경우 HTTP 요청을 통해 프로토콜이 위조될 수 없다. [RFC7301]

request request에 대해 나쁜 포트(bad port)로 인해 차단되어야 하는지 여부를 결정하려면:

  1. urlrequestcurrent URL로 둔다.

  2. urlschemeHTTP(S) scheme이고, urlport나쁜 포트(bad port)라면 blocked를 반환한다.

  3. 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. responserequest에 대해 MIME 타입으로 차단해야 하는가?

다음 단계를 실행한다:

  1. mimeTyperesponseheader list에서 MIME 타입 추출의 결과로 둔다.

  2. mimeType이 failure라면 allowed를 반환한다.

  3. destinationrequestdestination으로 둔다.

  4. destinationscript-like이고, 아래 중 하나라도 해당되면 blocked를 반환한다:

    • mimeTypeessence가 "audio/", "image/", "video/"로 시작하는 경우
    • mimeTypeessence가 "text/csv"인 경우
  5. allowed를 반환한다.

3. HTTP 확장

3.1. 쿠키(Cookies)

`Cookie` 요청 헤더와 `Set-Cookie` 응답 헤더는 대부분 자체 명세에서 정의된다. 여기서는 이를 편리하게 사용하기 위한 추가 인프라를 정의한다. [COOKIES].

요청 `Cookie` 헤더 추가(append a request `Cookie` header) 알고리즘은 request request가 주어졌을 때 다음을 따른다:

  1. 사용자 에이전트가 request에 대해 쿠키를 비활성화하도록 설정되어 있다면, 리턴한다.

  2. sameSitesame-site 모드 결정 알고리즘을 request에 대해 실행한 결과로 둔다.

  3. isSecurerequestcurrent URLscheme이 "https"이면 true, 아니면 false로 둔다.

  4. httpOnlyAllowed를 true로 둔다.

    이는 fetch에서 호출되었기 때문에 true다. (예: document.cookie getter에서는 다를 수 있음)

  5. cookiesretrieve cookies 알고리즘에 isSecure, requestcurrent URLhost, requestcurrent URLpath, httpOnlyAllowed, sameSite를 넘겨 호출한 결과로 둔다.

    쿠키 저장소는 정렬된 쿠키 목록을 반환한다

  6. cookies비어있으면 리턴한다.

  7. valueserialize cookies 알고리즘에 cookies를 넘겨 실행한 결과로 둔다.

  8. Append (`Cookie`, value)를 requestheader list에 추가한다.

응답 `Set-Cookie` 헤더 파싱 및 저장(parse and store response `Set-Cookie` headers) 알고리즘은 request requestresponse response가 주어졌을 때 다음을 따른다:

  1. 사용자 에이전트가 request에 대해 쿠키를 비활성화하도록 설정되어 있다면 리턴한다.

  2. allowNonHostOnlyCookieForPublicSuffix를 false로 둔다.

  3. isSecurerequestcurrent URLscheme이 "https"이면 true, 아니면 false로 둔다.

  4. httpOnlyAllowed를 true로 둔다.

    이는 fetch에서 호출되어 true임(document.cookie getter 등에서는 다름).

  5. sameSiteStrictOrLaxAllowedsame-site 모드 결정 알고리즘이 request에 대해 "strict-or-less"를 반환하면 true, 아니면 false로 둔다.

  6. responseheader listheader에 대해:

    1. headername이 `Set-Cookie`와 바이트 대소문자 무시(byte-case-insensitive)로 일치하지 않으면 continue한다.

    2. Parse and store a cookie 알고리즘에 headervalue, isSecure, requestcurrent URLhost, requestcurrent URLpath, httpOnlyAllowed, allowNonHostOnlyCookieForPublicSuffix, sameSiteStrictOrLaxAllowed를 넘겨 실행한다.

    3. Garbage collect cookies 알고리즘에 requestcurrent URLhost를 넘겨 실행한다.

    `Set-Cookie` 헤더는 병합될 수 없으므로 각각 독립적으로 처리된다. 이는 다른 어떤 헤더에도 허용되지 않는다.

same-site 모드 결정(determine the same-site mode) 알고리즘은 request request에 대해 다음을 따른다:

  1. Assert: requestmethod가 "GET" 또는 "POST"임을 확인한다.

  2. requesttop-level navigation initiator origin이 null이 아니고, requestURLoriginsame site가 아니면, "unset-or-less"를 반환한다.

  3. requestmethod가 "GET"이고, requestdestination이 "document"이면, "lax-or-less"를 반환한다.

  4. requestclienthas cross-site ancestor가 true라면, "unset-or-less"를 반환한다.

  5. requestredirect-taint가 "cross-site"라면, "unset-or-less"를 반환한다.

  6. "strict-or-less"를 반환한다.

직렬화된 쿠키 기본 경로URL url로부터 얻으려면:

  1. cloneURLurl의 복제본으로 한다.

  2. cloneURLpath쿠키 기본 경로로 설정한다. 이때 cloneURLpath를 사용한다.

  3. cloneURLURL 경로 직렬화를 반환한다.

3.2. `Origin` 헤더

`Origin` 요청 헤더fetch가 어디에서 시작되었는지를 나타낸다.

`Origin` 헤더는 경로(path)를 노출하지 않는 `Referer` [sic] 헤더의 변형이다. 이는 HTTP fetchrequestresponse tainting이 "cors"이거나, requestmethod가 `GET` 또는 `HEAD`가 아닌 경우에 사용된다. 호환성 문제로 인해 모든 fetch에 포함되지는 않는다.

가능한 요청 origin의 바이트 직렬화(byte-serializing a request origin) 알고리즘이 request에 대해 반환하는 모든 값이다.

이 정의는 The Web Origin Concept의 정의를 대체한다. [ORIGIN]


요청 `Origin` 헤더 추가(append a request `Origin` header) 알고리즘은 request request가 주어졌을 때 다음을 실행한다:

  1. Assert: requestorigin이 "client"가 아님을 확인한다.

  2. serializedOrigin요청 origin의 바이트 직렬화 알고리즘을 request에 대해 실행한 결과로 둔다.

  3. requestresponse tainting이 "cors"이거나, requestmode가 "websocket"이면, append (`Origin`, serializedOrigin)을 requestheader list에 추가한다.

  4. 그렇지 않고 requestmethod가 `GET` 또는 `HEAD`가 아니라면:

    1. requestmode가 "cors"가 아니면, requestreferrer policy에 따라 분기한다:

      "no-referrer"

      serializedOrigin을 `null`로 설정한다.

      "no-referrer-when-downgrade"
      "strict-origin"
      "strict-origin-when-cross-origin"

      requestorigintuple origin이고, 그 scheme이 "https"이며, requestcurrent URLscheme이 "https"가 아니면, serializedOrigin을 `null`로 설정한다.

      "same-origin"

      requestoriginrequestcurrent URLorigin동일 출처(same origin)가 아니면, serializedOrigin을 `null`로 설정한다.

      그 외
      아무것도 하지 않는다.
    2. append (`Origin`, serializedOrigin)을 requestheader list에 추가한다.

requestreferrer policy는 fetcher가 서버와 origin을 명시적으로 공유하도록 설정하지 않은 모든 fetch에 대해 고려된다(예: CORS 프로토콜 사용 등).

3.3. CORS 프로토콜

교차 출처 응답 공유를 허용하고 HTML의 form 요소로 가능한 것보다 더 다양한 fetch를 허용하기 위해 CORS 프로토콜이 존재한다. 이는 HTTP 위에 계층화되어 있으며, 응답이 다른 origin과 공유될 수 있음을 선언하는 것을 허용한다.

방화벽(인트라넷) 뒤의 응답에서 데이터가 유출되는 것을 막기 위해 opt-in 메커니즘이어야 한다. 또한 requestcredentials가 포함되어 있을 때는 민감한 데이터 유출을 방지하기 위해서도 opt-in이어야 한다.

이 절에서는 서버 개발자를 위한 CORS 프로토콜을 설명한다. 사용자 에이전트에 대한 요구 사항은 fetch 알고리즘에 포함되어 있으며, 새로운 HTTP 헤더 문법을 제외한다.

3.3.1. 일반

CORS 프로토콜은 응답이 교차 출처로 공유 가능한지 나타내는 일련의 헤더로 구성된다.

HTML의 form 요소로 가능한 것보다 더 복잡한 request의 경우, CORS-사전 요청(CORS-preflight request)을 수행하여, requestcurrent URLCORS 프로토콜을 지원하는지 확인한다.

3.3.2. HTTP 요청

CORS 요청이란 `Origin` 헤더를 포함하는 HTTP 요청을 말한다. 이 헤더는 CORS 프로토콜에 참여하는지 신뢰성 있게 판별할 수 있는 기준이 되지 않는다. 왜냐하면 `Origin` 헤더는 requestmethod가 `GET` 또는 `HEAD`가 아닌 모든 경우에도 포함되기 때문이다.

CORS-사전 요청(CORS-preflight request)이란 CORS 요청으로, CORS 프로토콜이 적용 가능한지 확인하는 역할을 한다. 이 때 method는 `OPTIONS`이고 다음 헤더가 포함된다:

`Access-Control-Request-Method`

이후에 동일 리소스에 대해 할 CORS 요청이 어떤 method를 사용할 수 있는지 나타낸다.

CORS-사전 요청에는 다음 헤더도 포함될 수 있다:

`Access-Control-Request-Headers`

이후에 동일 리소스에 대해 할 CORS 요청이 어떤 헤더를 사용할 수 있는지 나타낸다.

3.3.3. HTTP 응답

CORS 요청에 대한 HTTP 응답에는 다음 헤더를 포함할 수 있다:

`Access-Control-Allow-Origin`

응답이 공유될 수 있는지 나타내며, 요청의 `Origin` 헤더의 리터럴 (또는 `null`)이나 `*`를 응답에서 반환한다.

`Access-Control-Allow-Credentials`

requestcredentials mode가 "include"일 때 응답이 공유될 수 있는지 나타낸다.

CORS-사전 요청의 경우 requestcredentials mode는 항상 "same-origin"(즉, credentials 미포함)이지만, 이후의 CORS 요청에서는 그렇지 않을 수 있다. 따라서 CORS-사전 요청의 HTTP 응답에도 지원 여부를 표시해야 한다.

CORS-사전 요청에 대한 HTTP 응답에는 다음 헤더를 포함할 수 있다:

`Access-Control-Allow-Methods`

응답의 responseURLCORS 프로토콜 목적으로 지원하는 method를 나타낸다.

`Allow` 헤더는 CORS 프로토콜 목적과는 무관하다.

`Access-Control-Allow-Headers`

응답의 responseURLCORS 프로토콜 목적으로 지원하는 헤더를 나타낸다.

`Access-Control-Max-Age`

`Access-Control-Allow-Methods`와 `Access-Control-Allow-Headers` 헤더의 정보를 몇 초(기본값 5초) 동안 캐시할 수 있는지 나타낸다.

CORS 요청이면서 CORS-사전 요청이 아닌 경우, 다음 헤더도 포함할 수 있다:

`Access-Control-Expose-Headers`

응답의 일부로 노출될 수 있는 헤더를 그 이름들을 나열하여 표시한다.


서버 개발자가 공유 의도가 있는 CORS 요청에 대한 성공적인 HTTP 응답은, 위에 명시된 헤더를 요청에 맞는 으로 포함하기만 하면 어떤 status도 사용할 수 있다.

CORS-사전 요청에 대한 성공적인 HTTP 응답도 유사하나, ok status (예: 200 또는 204)로 제한된다.

그 외의 HTTP 응답은 성공적이지 않으며, 공유가 불가능하거나 CORS-사전 요청에 실패한다. 서버에서 수행한 작업이 타이밍 등 부채널로 누출될 수 있음에 유의해야 한다. 서버 개발자가 이를 명시적으로 나타내고 싶다면, 403 status와 관련 헤더의 생략을 함께 사용할 수 있다.

원한다면 "실패"도 공유할 수 있지만, 이는 성공적인 HTTP 응답으로 간주된다. 따라서 CORS-사전 요청이 아닌 CORS 요청에 대한 성공적인 HTTP 응답의 status는 403을 포함해 아무 값이나 될 수 있다.

결국 서버 개발자는 HTTP 응답 처리 방식에서 많은 자유를 가지며, 이러한 전략은 CORS-사전 요청과 그 이후 CORS 요청의 응답 처리 방식이 다를 수 있다:

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

requestcredentials mode가 "include"일 때는 fetchcredentials를 포함하는 것 외에도 CORS 프로토콜 동작에 영향을 미친다.

예전에는 XMLHttpRequest 를 이용해 requestcredentials mode를 "include"로 설정할 수 있었다:

var client = new XMLHttpRequest()
client.open("GET", "./")
client.withCredentials = true
/* … */

현재는 fetch("./", { credentials:"include" }).then(/* … */)만으로 충분하다.

requestcredentials 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` 응답 헤더도 requestcredentials 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` 응답 헤더를 제공한다. hstscsp 값은 `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) 없이 요청을 트리거할 수 있음을 예상해야 한다:

명세에서는 새 예외 도입을 피해야 하며, 반드시 신중히 보안 영향을 고려하여야 한다. 새로운 예외는 이슈 등록을 통해 제안할 수 있다.

3.4. `Content-Length` 헤더

`Content-Length` 헤더는 주로 HTTP에서 정의되어 있다. HTTP에서 정의된 처리 모델이 웹 콘텐츠와 호환되지 않으므로 여기서 처리 모델을 정의한다. [HTTP]

길이 추출(extract a length) 알고리즘은 header list headers에서 다음 단계를 실행한다:

  1. valuesgetting, decoding, and splitting `Content-Length` from headers의 결과로 둔다.

  2. values가 null이면 null을 반환한다.

  3. candidateValue를 null로 둔다.

  4. valuesvalue에 대해:

    1. candidateValue가 null이면 candidateValuevalue를 할당한다.

    2. 아니라면 valuecandidateValue와 다르면 failure를 반환한다.

  5. candidateValue가 빈 문자열이거나, code pointASCII digit이 아닌 것이 있으면 null을 반환한다.

  6. candidateValue를 10진수 숫자로 해석하여 반환한다.

3.5. `Content-Type` 헤더

`Content-Type` 헤더는 주로 HTTP에서 정의되어 있다. HTTP에서 정의된 처리 모델이 웹 콘텐츠와 호환되지 않으므로 여기서 처리 모델을 정의한다. [HTTP]

MIME 타입 추출(extract a MIME type) 알고리즘은 header list headers에서 다음 단계를 실행한다. 반환 값은 failure 또는 MIME 타입이다.

  1. charset을 null로 둔다.

  2. essence를 null로 둔다.

  3. mimeType을 null로 둔다.

  4. valuesgetting, decoding, and splitting `Content-Type` from headers의 결과로 둔다.

  5. values가 null이면 failure를 반환한다.

  6. valuesvalue에 대해:

    1. temporaryMimeTypeMIME 타입 파싱(parsing) value 결과로 둔다.

    2. temporaryMimeType이 failure이거나, 그 essence가 "*/*"면 continue한다.

    3. mimeTypetemporaryMimeType으로 둔다.

    4. mimeTypeessenceessence와 다르면:

      1. charset을 null로 둔다.

      2. mimeTypeparameters["charset"]가 존재하면 charset을 그 값으로 둔다.

      3. essencemimeTypeessence로 둔다.

    5. 아니라면, mimeTypeparameters["charset"]가 존재하지 않고, charset이 null이 아니면 mimeTypeparameters["charset"]를 charset으로 둔다.

  7. mimeType이 null이면 failure를 반환한다.

  8. mimeType을 반환한다.

MIME 타입 추출이 failure를 반환하거나, MIME 타입essence가 해당 포맷에 대해 부적절할 경우, 이는 치명적 오류로 간주한다. 기존 웹 플랫폼 기능들은 항상 이 패턴을 따르지 않아 다수의 보안 취약점 원인이 되어 왔다. 이에 반해 MIME 타입parameters는 일반적으로 무시해도 안전하다.

MIME 타입 추출 알고리즘의 실제 동작 예시:

헤더(네트워크 상) 출력(직렬화(serialized))
Content-Type: text/plain;charset=gbk, text/html
text/html
Content-Type: text/html;charset=gbk;a=b, text/html;x=y
text/html;x=y;charset=gbk
Content-Type: text/html;charset=gbk;a=b
Content-Type: text/html;x=y
Content-Type: text/html;charset=gbk
Content-Type: x/x
Content-Type: text/html;x=y
text/html;x=y
Content-Type: text/html
Content-Type: cannot-parse
text/html
Content-Type: text/html
Content-Type: */*
Content-Type: text/html
Content-Type:

레거시 인코딩 추출(legacy extract an encoding) 알고리즘은 failure 또는 MIME 타입 mimeTypeencoding fallbackEncoding이 주어졌을 때 다음을 따른다:

  1. mimeType이 failure면 fallbackEncoding을 반환한다.

  2. mimeType["charset"]이 존재하지 않으면 fallbackEncoding을 반환한다.

  3. tentativeEncodingget an encoding 알고리즘에 mimeType["charset"]을 넘겨 실행한 결과로 둔다.

  4. tentativeEncoding이 failure면 fallbackEncoding을 반환한다.

  5. 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가 주어졌을 때 다음을 따른다:

  1. valuesgetting, decoding, and splitting(`X-Content-Type-Options`)을 list에 대해 실행한 결과로 둔다.

  2. values가 null이면 false를 반환한다.

  3. values[0]이 "nosniff"와 ASCII 대소문자 구분 없이 일치하면 true를 반환한다.

  4. false를 반환한다.

웹 개발자 및 적합성 검사기는 `X-Content-Type-Options`의 에 대해 다음 ABNF를 사용해야 한다:

X-Content-Type-Options           = "nosniff" ; case-insensitive

3.6.1. responserequest에 대해 nosniff로 차단해야 하는가?

다음 단계를 실행한다:

  1. nosniff 결정responseheader list에 대해 실행한 결과가 false라면 allowed를 반환한다.

  2. mimeTyperesponseheader list에서 MIME 타입 추출 알고리즘을 실행한 결과로 둔다.

  3. destinationrequestdestination으로 둔다.

  4. destinationscript-like이고, mimeType이 failure이거나 JavaScript MIME 타입이 아니면 blocked를 반환한다.

  5. destination이 "style"이고 mimeType이 failure이거나 essence가 "text/css"가 아니면 blocked를 반환한다.

  6. allowed를 반환한다.

requestdestinationscript-like 또는 "style"만 고려한다. 이는 공격이 이 대상을 통해 발생하기 때문이다. "image"는 배포된 콘텐츠와 호환되지 않아 제외되었다.

3.7. `Cross-Origin-Resource-Policy` 헤더

`Cross-Origin-Resource-Policy` 응답 헤더requestcurrent URLoriginrequestoriginrequestmode가 "no-cors"일 때 비교하도록 강제할 수 있다.

ABNF:

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이 주어졌을 때 다음을 수행한다:

  1. forNavigation이 주어지지 않았다면 false로 설정한다.

  2. embedderPolicysettingsObjectpolicy containerembedder policy로 둔다.

  3. 교차 출처 리소스 정책 내부 검사origin, "unsafe-none", response, forNavigation에 대해 실행해 blocked를 반환하면 blocked를 반환한다.

    이 단계는 아래에서 Cross-Origin Embedder Policy에 관련 없는 위반을 보고하지 않기 위해 필요하다.

  4. 교차 출처 리소스 정책 내부 검사origin, embedderPolicyreport only value, response, forNavigation에 대해 실행해 blocked를 반환하면 교차 출처 임베더 정책 CORP 위반 리포트 큐잉response, settingsObject, destination, true로 실행한다.

  5. 교차 출처 리소스 정책 내부 검사origin, embedderPolicyvalue, response, forNavigation에 대해 실행해 allowed를 반환하면 allowed를 반환한다.

  6. 교차 출처 임베더 정책 CORP 위반 리포트 큐잉response, settingsObject, destination, false로 실행한다.

  7. blocked를 반환한다.

HTML의 navigate 알고리즘만 forNavigation이 true로 이 검사를 사용하며, 항상 중첩 내비게이션에만 해당된다. 그 외에는 responseinternal 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이 주어졌을 때 다음을 수행한다:

  1. forNavigation이 true이고 embedderPolicyValue가 "unsafe-none"이면 allowed를 반환한다.

  2. policygetting(`Cross-Origin-Resource-Policy`)을 responseheader list에 대해 실행한 결과로 둔다.

    즉, `Cross-Origin-Resource-Policy: same-site, same-origin`은 아래에서 어떤 것도 일치하지 않으므로 항상 allowed가 된다. embedderPolicyValue가 "unsafe-none"일 때는 두 개 이상의 `Cross-Origin-Resource-Policy` 헤더도 동일하게 취급된다.

  3. policy가 `same-origin`, `same-site`, `cross-origin` 중 어느 것도 아니면 policy를 null로 둔다.

  4. policy가 null이면 embedderPolicyValue에 따라 분기한다:

    "unsafe-none"

    아무 것도 하지 않는다.

    "credentialless"

    다음 중 하나라도 true이면 policy를 `same-origin`으로 설정한다:

    "require-corp"

    policy를 `same-origin`으로 설정한다.

  5. policy에 따라 분기한다:

    null
    `cross-origin`

    allowed를 반환한다.

    `same-origin`

    origin동일 출처(same origin)라면 responseURLorigin과, allowed를 반환한다.

    그 외에는 blocked를 반환한다.

    `same-site`

    다음 모두가 true이면

    그렇다면 allowed를 반환한다.

    그 외에는 blocked를 반환한다.

    `Cross-Origin-Resource-Policy: same-site`는 안전한 전송(https)으로 전달된 응답을 비안전한 요청(origin)과 일치시키지 않는다. 즉, secure로 전송된 응답은 secure로 시작한 initiator와만 일치한다.

교차 출처 임베더 정책 CORP 위반 리포트 큐잉(queue a cross-origin embedder policy CORP violation report) 알고리즘은 response response, environment settings object settingsObject, 문자열 destination, 불린 reportOnly가 주어졌을 때 다음을 수행한다:

  1. endpointreportOnly가 true이면 settingsObjectpolicy containerembedder policyreport only reporting endpoint로, 그렇지 않으면 settingsObjectpolicy containerembedder policyreporting endpoint로 둔다.

  2. serializedURLserialize a response URL for reportingresponse에 대해 실행한 결과로 둔다.

  3. dispositionreportOnly가 true이면 "reporting", 아니면 "enforce"로 둔다.

  4. body를 다음 속성을 포함하는 새 객체로 둔다:

    key value
    "type" "corp"
    "blockedURL" serializedURL
    "destination" destination
    "disposition" disposition
  5. generate and queue a reportsettingsObjectglobal 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]

  1. Assert: requestmode가 "navigate"이거나 processEarlyHintsResponse가 null이어야 한다.

    초기 힌트(status가 103인 응답) 처리는 내비게이션에 대해서만 검증됩니다.

  2. taskDestination을 null로 둔다.

  3. crossOriginIsolatedCapability를 false로 둔다.

  4. 클라이언트로부터 요청 채우기request에 대해 실행한다.

  5. requestclient가 null이 아니면:

    1. taskDestinationrequestclientglobal object로 설정한다.

    2. crossOriginIsolatedCapabilityrequestclientcross-origin isolated capability로 설정한다.

  6. useParallelQueue가 true라면, taskDestination새로운 병렬 큐 시작의 결과로 설정한다.

  7. timingInfofetch timing info의 새 인스턴스로 두고, start timepost-redirect start timecoarsened shared current timecrossOriginIsolatedCapability를 적용한 값으로 설정하고, render-blockingrequestrender-blocking 값으로 설정한다.

  8. fetchParams를 새 fetch params의 인스턴스로 두고, requestrequest, timing infotimingInfo, process request body chunk lengthprocessRequestBodyChunkLength, process request end-of-bodyprocessRequestEndOfBody, process early hints responseprocessEarlyHintsResponse, process responseprocessResponse, process response consume bodyprocessResponseConsumeBody, process response end-of-bodyprocessResponseEndOfBody, task destinationtaskDestination, cross-origin isolated capabilitycrossOriginIsolatedCapability로 설정한다.

  9. requestbodybyte sequence라면, requestbodyrequestbody as a body로 설정한다.

  10. 다음 조건이 모두 true라면:

    이 경우:

    1. Assert: requestoriginrequestclientsame origin

    2. onPreloadedResponseAvailable을 다음 알고리즘으로 설정: response response를 받아, fetchParamspreloaded response candidateresponse를 할당함

    3. foundPreloadedResourcepreloaded resource 소비의 결과로 설정함: requestclient, requestURL, requestdestination, requestmode, requestcredentials mode, requestintegrity metadata, onPreloadedResponseAvailable

    4. foundPreloadedResource가 true이고 fetchParamspreloaded response candidate가 null이면, fetchParamspreloaded response candidate를 "pending"으로 설정함

  11. requestheader list에 `Accept`가 포함되어 있지 않으면:

    1. value를 `*/*`로 설정

    2. requestinitiator가 "prefetch"이면, valuedocument `Accept` header value로 설정

    3. 그 외에는, 사용자 에이전트는 requestdestination에 따라 아래와 같이 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`
    4. Append (`Accept`, value)를 requestheader list에 추가한다.

  12. requestheader list에 `Accept-Language`가 포함되어 있지 않으면, 사용자 에이전트는 append (`Accept-Language, 적절한 header value)를 requestheader list에 추가한다.

  13. requestinternal priority가 null이면, requestpriority, initiator, destination, render-blocking을 사용하여 구현 정의 방식으로 requestinternal priority구현 정의 객체로 설정한다.

    구현 정의 객체에는 HTTP/2의 스트림 가중치 및 의존성, HTTP용 확장 우선순위 스킴(Extensible Prioritization Scheme for HTTP)에서 사용하는 우선순위 정보(HTTP/3 등 해당 전송 포함), HTTP/1 fetch의 디스패치 및 처리 우선순위를 위한 동등한 정보가 포함될 수 있습니다. [RFC9218]

  14. request하위 리소스 요청이면:

    1. record를 새 fetch record로 두고, requestrequest, controllerfetchParamscontroller로 설정한다.

    2. Append recordrequestclientfetch groupfetch records에 추가함

  15. main fetchfetchParams로 실행한다.

  16. fetchParamscontroller를 반환함

클라이언트로부터 요청 채우기를 실행하려면, request request를 받아:

  1. requesttraversable for user prompts가 "client"이면:

    1. requesttraversable for user prompts를 "no-traversable"로 설정함

    2. requestclient가 null이 아니면:

      1. globalrequestclientglobal object로 설정

      2. globalWindow 객체이고 globalnavigable이 null이 아니면, requesttraversable for user promptsglobalnavigabletraversable navigable로 설정

  2. requestorigin이 "client"이면:

    1. Assert: requestclient가 null이 아님

    2. requestoriginrequestclientorigin으로 설정함

  3. requestpolicy container가 "client"이면:

    1. requestclient가 null이 아니면, requestpolicy containerrequestclientpolicy container복제본으로 설정함 [HTML]

    2. 그 외에는, requestpolicy container를 새 policy container로 설정함

4.1. 메인 fetch

main fetch를 실행하려면, fetch params fetchParams와 선택적 불리언 recursive (기본값 false)를 받아 다음 단계를 실행한다:

  1. requestfetchParamsrequest로 둔다.

  2. response를 null로 둔다.

  3. requestlocal-URLs-only flag가 설정되어 있고, requestcurrent URLlocal이 아니면, response네트워크 에러로 설정한다.

  4. Content Security Policy 위반 사항을 request에 대해 보고한다.

  5. request를 필요하다면 잠재적으로 신뢰할 수 있는 URL로 업그레이드한다.

  6. 혼합 콘텐츠 request를 필요하다면 잠재적으로 신뢰할 수 있는 URL로 업그레이드한다.

  7. request가 잘못된 포트로 인해 차단되어야 하는지, request fetch가 혼합 콘텐츠로 인해 차단되어야 하는지, Content Security Policy에 의해 request가 차단되어야 하는지, 무결성 정책에 의해 request가 차단되어야 하는지 중 하나라도 blocked를 반환하면, response네트워크 에러로 설정한다.

  8. requestreferrer policy가 빈 문자열이면, requestreferrer policyrequestpolicy containerreferrer policy로 설정한다.

  9. requestreferrer가 "no-referrer"가 아니면, requestreferrerrequest의 referrer 결정의 결과로 설정한다. [REFERRER]

    Referrer Policy에서 명시한 대로, 사용자 에이전트는 최종 사용자에게 requestreferrer를 "no-referrer"로 오버라이드하거나 덜 민감한 정보만 노출하도록 선택권을 제공할 수 있습니다.

  10. requestcurrent URLscheme을 아래 조건이 모두 true이면 "https"로 설정한다:

    모든 DNS 동작은 일반적으로 구현 정의이므로, DNS 조회에 HTTPS RR이 포함되어 있는지 판단하는 방법 역시 구현 정의입니다. DNS 동작은 전통적으로 연결 얻기 시점까지 수행되지 않으므로, 사용자 에이전트는 더 일찍 DNS 동작을 수행하거나, 로컬 DNS 캐시를 참조하거나, fetch 알고리즘 내에서 더 늦게까지 기다렸다가 scheme 변경이 필요함을 발견해서 로직을 되돌릴 수도 있습니다.

  11. recursive가 false이면, 남은 단계를 병렬로 실행한다.

  12. response가 null이면, 다음에서 처음으로 일치하는 구문에 해당하는 단계를 실행한 결과를 response로 설정한다:

    fetchParamspreloaded response candidate가 null이 아님
    1. fetchParamspreloaded response candidate가 "pending"이 아닐 때까지 대기한다.

    2. Assert: fetchParamspreloaded response candidateresponse

    3. fetchParamspreloaded response candidate를 반환한다.

    requestcurrent URLoriginrequestoriginsame origin이고, requestresponse tainting이 "basic"임
    requestcurrent URLscheme이 "data"임
    requestmode가 "navigate" 또는 "websocket"임
    1. requestresponse tainting을 "basic"으로 설정한다.

    2. "scheme-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.

    HTML은 URLscheme이 "data"인 경우, 생성된 문서 및 워커에 고유 불투명 origin을 할당한다. Service worker는 URLschemeHTTP(S) scheme인 경우에만 생성 가능하다. [HTML] [SW]

    requestmode가 "same-origin"임

    네트워크 에러를 반환한다.

    requestmode가 "no-cors"임
    1. requestredirect mode가 "follow"가 아니면, 네트워크 에러를 반환한다.

    2. requestresponse tainting을 "opaque"로 설정한다.

    3. "scheme-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.

    requestcurrent URLschemeHTTP(S) scheme이 아니면

    네트워크 에러를 반환한다.

    requestuse-CORS-preflight flag가 설정됨
    requestunsafe-request flag가 설정되어 있고, requestmethodCORS-safelisted method가 아니거나, CORS-unsafe request-header namesrequestheader list비어있지 않음
    1. requestresponse tainting을 "cors"로 설정한다.

    2. corsWithPreflightResponse를 "http-fetch", fetchParams, 그리고 true를 주어 override fetch를 실행한 결과로 설정한다.

    3. corsWithPreflightResponse네트워크 에러면, 캐시 엔트리 삭제request로 실행한다.

    4. corsWithPreflightResponse를 반환한다.

    그 외의 경우
    1. requestresponse tainting을 "cors"로 설정한다.

    2. "http-fetch"와 fetchParams가 주어졌을 때 override fetch를 실행한 결과를 반환한다.

  13. recursive가 true면 response를 반환한다.

  14. response네트워크 에러가 아니고 responsefiltered response가 아니면:

    1. requestresponse tainting이 "cors"이면:

      1. headerNamesextracting header list values를 `Access-Control-Expose-Headers`와 responseheader list로 실행한 결과로 둔다.

      2. requestcredentials mode가 "include"가 아니고, headerNames가 `*`를 포함하면, responseCORS-exposed header-name listresponseheader list 내의 모든 고유 header name로 설정한다.

      3. 그 외에 headerNames가 null 또는 실패가 아니면, responseCORS-exposed header-name listheaderNames로 설정한다.

        headerNames 중 하나가 여전히 `*`일 수 있지만, 이는 headername이 `*`인 경우에만 일치한다.

    2. responsefiltered response로 설정한다. response를 내부 응답으로 두고, requestresponse tainting에 따라 아래와 같이 한다:

      "basic"
      basic filtered response
      "cors"
      CORS filtered response
      "opaque"
      opaque filtered response
  15. internalResponseresponse네트워크 에러일 경우 response로, 아니면 responseinternal response로 둔다.

  16. internalResponseURL list비어 있으면, requestURL list복제본으로 설정한다.

    responseURL list는 비어 있을 수 있음 (예: about: URL fetch 시).

  17. internalResponseredirect taintrequestredirect-taint로 설정한다.

  18. requesttiming allow failed flag가 설정되어 있지 않으면, internalResponsetiming allow passed flag를 설정한다.

  19. response네트워크 에러가 아니고, 아래 중 하나라도 blocked를 반환하면

    이 경우 responseinternalResponse네트워크 에러로 설정한다.

  20. responsetype이 "opaque"이고, internalResponsestatus가 206, internalResponserange-requested flag가 설정되어 있고, requestheader list에 `Range`가 포함되어 있지 않으면, responseinternalResponse네트워크 에러로 설정한다.

    전통적으로, API는 range를 요청하지 않아도 range 응답을 허용했습니다. 이는 이전 range 요청의 부분 응답이 range 요청을 하지 않은 API에 제공되는 것을 막습니다.

    자세히 보기

    위 단계는 다음 공격을 방지합니다:

    미디어 요소가 교차 출처 HTML 리소스의 범위를 요청함. 비록 이 미디어가 유효하지 않지만, 서비스 워커에서 응답의 복제본을 참조로 유지 가능. 이후 스크립트 요소의 fetch 응답으로 활용 가능. 부분 응답이 유효한 JavaScript라면(전체 리소스는 유효하지 않아도), 실행 시 민감한 데이터가 유출될 수 있음.

  21. response네트워크 에러가 아니고, requestmethod가 `HEAD` 또는 `CONNECT`이거나, internalResponsestatusnull body status이면, internalResponsebody를 null로 설정하고, 그에 대한 enqueuing은 무시한다.

    이것은 HTTP를 위반하는 서버에 대한 에러 처리를 표준화합니다.

  22. requestintegrity metadata가 빈 문자열이 아니면:

    1. processBodyError를 다음 단계로 설정: fetch response handoverfetchParams네트워크 에러로 실행한다.

    2. responsebody가 null이면, processBodyError를 실행하고, 이 단계를 중단한다.

    3. processBodybytes를 인자로 받아 다음 단계로 설정:

      1. bytesrequest의 integrity metadata와 일치하지 않으면, processBodyError를 실행하고, 이 단계를 중단한다. [SRI]

      2. responsebodybytes as a body로 설정한다.

      3. fetch response handoverfetchParamsresponse로 실행한다.

    4. body 완전 읽기responsebody, processBodyprocessBodyError로 실행한다.

  23. 그 외의 경우, fetch response handoverfetchParamsresponse로 실행한다.


fetch response handoverfetch params fetchParamsresponse response를 받아 다음 단계를 실행한다:

  1. timingInfofetchParamstiming info로 둔다.

  2. response네트워크 에러가 아니고, fetchParamsrequestclientsecure context이면, timingInfoserver-timing headersresponseinternal responseheader list에서 `Server-Timing`을 get/decode/split한 결과로 설정한다.

    internal response를 사용하는 것은 `Server-Timing` 헤더 데이터 노출이 `Timing-Allow-Origin` 헤더로 보호되기 때문에 안전하다.

    사용자 에이전트는 `Server-Timing` 헤더를 non-secure context 요청에도 노출할 수 있다.

  3. 만약 fetchParamsrequestdestination이 "document"라면, fetchParamscontrollerfull timing infofetchParamstiming info로 설정한다.

  4. processResponseEndOfBody를 다음 단계로 둔다:

    1. unsafeEndTimeunsafe shared current time으로 둔다.

    2. fetchParamscontrollerreport timing stepsglobal object global을 받아 다음 단계로 둔다:

      1. fetchParamsrequestURLschemeHTTP(S) scheme이 아니면 return.

      2. timingInfoend timerelative high resolution time으로, unsafeEndTimeglobal을 인자로 설정한다.

      3. cacheStateresponsecache state로 둔다.

      4. bodyInforesponsebody info로 둔다.

      5. responsetiming allow passed flag가 설정되어 있지 않으면, timingInfoopaque timing info 생성의 결과로 설정하고, cacheState를 빈 문자열로 설정한다.

        response네트워크 에러인 경우도 포함한다.

      6. responseStatus를 0으로 둔다.

      7. fetchParamsrequestmode가 "navigate"가 아니거나 responseredirect taint가 "same-origin"이면:

        1. responseStatusresponsestatus로 설정한다.

        2. mimeTyperesponseheader list에서 extracting a MIME type의 결과로 둔다.

        3. mimeType이 실패가 아니면, bodyInfocontent typeminimizing a supported MIME type의 결과로 mimeType을 넘겨 설정한다.

      8. fetchParamsrequestinitiator type이 null이 아니면, mark resource timingtimingInfo, fetchParamsrequestURL, fetchParamsrequestinitiator type, global, cacheState, bodyInfo, responseStatus로 실행한다.

    3. processResponseEndOfBodyTask를 다음 단계로 설정한다:

      1. fetchParamsrequestdone flag를 설정한다.

      2. fetchParamsprocess response end-of-body가 null이 아니면, fetchParamsprocess response end-of-bodyresponse로 실행한다.

      3. fetchParamsrequestinitiator type이 null이 아니고, fetchParamsrequestclientglobal objectfetchParamstask destination이면, fetchParamscontrollerreport timing stepsfetchParamsrequestclientglobal object로 실행한다.

    4. fetch task 큐에 넣기를 실행하여 processResponseEndOfBodyTaskfetchParamstask destination과 함께 실행한다.

  5. fetchParamsprocess response가 null이 아니면, fetch task 큐에 넣기를 실행하여 fetchParamsprocess responseresponse로, fetchParamstask destination과 함께 실행한다.

  6. internalResponseresponse네트워크 에러일 경우 response로, 아니면 responseinternal response로 둔다.

  7. internalResponsebody가 null이면, processResponseEndOfBody를 실행한다.

  8. 그 외의 경우:

    1. transformStream을 새로운 TransformStream으로 둔다.

    2. identityTransformAlgorithm을 알고리즘으로 두고, chunk를 받아 transformStream에 enqueue한다.

    3. transformStream 설정을 실행하여, transformAlgorithmidentityTransformAlgorithm으로, flushAlgorithmprocessResponseEndOfBody로 설정한다.

    4. internalResponsebodystreaminternalResponsebodystreamtransformStream에 파이프한 결과로 설정한다.

    TransformStream은 스트림이 끝에 도달할 때 알림을 받기 위해 필요하며, 그 외에는 identity transform stream이다.

  9. fetchParamsprocess response consume body가 null이 아니면:

    1. processBodynullOrBytes를 인자로 받아, fetchParamsprocess response consume bodyresponsenullOrBytes로 실행하는 단계로 설정한다.

    2. processBodyErrorfetchParamsprocess response consume bodyresponse와 failure로 실행하는 단계로 설정한다.

    3. internalResponsebody가 null이면, fetch task 큐에 넣기를 실행하여 processBody를 null로 실행하고, fetchParamstask destination과 함께 실행한다.

    4. 그 외에는, body 완전 읽기internalResponsebody, processBody, processBodyError, fetchParamstask destination로 실행한다.

4.2. 오버라이드 fetch

override fetch는 "scheme-fetch" 또는 "http-fetch" type, fetch params fetchParams, 그리고 선택적 boolean makeCORSPreflight (기본값 false)를 입력으로 받는다:

  1. requestfetchParamsrequest로 설정한다.

  2. responserequest에 대해 potentially override response for a request를 실행한 결과로 설정한다.

  3. response가 null이 아니면 response를 반환한다.

  4. type에 따라 다음 단계 중 하나를 실행한다:

    "scheme fetch"

    responsefetchParams를 입력으로 scheme fetch를 실행한 결과로 설정한다.

    "HTTP fetch"

    responsefetchParamsmakeCORSPreflight를 입력으로 HTTP fetch를 실행한 결과로 설정한다.

  5. response를 반환한다.

potentially override response for a request 알고리즘은 request request를 입력받아, response 또는 null을 반환한다. 동작은 구현 정의이며, 사용자 에이전트가 request에 직접 응답을 반환하거나 null을 반환하여 요청을 계속 진행하도록 허용할 수 있다.

기본적으로 이 알고리즘은 다음과 같이 단순하게 구현된다:

  1. null을 반환한다.

사용자 에이전트는 일반적으로 이 기본 구현을 보다 복잡한 동작으로 오버라이드한다. 예를 들어, 사용자 에이전트는 사용자의 안전을 위해 일반적으로 `https://unsafe.example/`로의 요청을 차단하지만, `https://unsafe.example/widget.js`와 같은 널리 사용되는 리소스에 대해서는 호환을 위해 shim을 생성할 수 있다. 그 구현 예시는 아래와 같다:

  1. requestcurrent urlhost등록 가능한 도메인이 "unsafe.example"이면:

    1. requestcurrent urlpath가 « "widget.js" »이면:

      1. body를 [여기에 shim 콘텐츠를 바이트 시퀀스로 삽입]로 설정한다.

      2. 아래 속성을 가진 새로운 response를 반환한다:

        type
        "cors"
        status
        200
        ...
        ...
        body
        bodybody로 변환한 결과.
    2. network error를 반환한다.

  2. null을 반환한다.

4.3. 스킴 fetch

스킴 fetchfetch params fetchParams를 입력으로 받는다:

  1. fetchParams취소됨이면, fetchParams에 대해 적절한 네트워크 오류를 반환한다.

  2. requestfetchParamsrequest로 설정한다.

  3. requestcurrent URLscheme에 따라 다음 단계를 실행한다:

    "about"

    requestcurrent URLpath가 "blank" 문자열이면, response를 새로 만들어 반환한다. status message는 `OK`, header list는 « (`Content-Type`, `text/html;charset=utf-8`) », body는 빈 바이트 시퀀스를 body로 변환한 값이다.

    URL "about:config" 등은 네비게이션 처리 시 다루며, fetch 맥락에서는 네트워크 오류가 발생한다.

    "blob"
    1. blobURLEntryrequestcurrent URLblob URL entry로 설정한다.

    2. requestmethod가 `GET`이 아니거나 blobURLEntry가 null이면 네트워크 오류를 반환한다. [FILEAPI]

      `GET` method 제한은 상호운용성 이외에는 의미가 없다.

    3. requestEnvironment환경 결정하기request에 대해 실행한 결과로 설정한다.

    4. isTopLevelNavigationrequestdestination이 "document"이면 true, 아니면 false로 설정한다.

    5. isTopLevelNavigation이 false이고 requestEnvironment가 null이면, 네트워크 오류를 반환한다.

    6. navigationOrEnvironmentisTopLevelNavigation이 true면 "navigation", 아니면 requestEnvironment로 설정한다.

    7. blobblob 객체 얻기blobURLEntrynavigationOrEnvironment에 대해 실행한 결과로 설정한다.

    8. blobBlob 객체가 아니면 네트워크 오류를 반환한다.

    9. response를 새로운 response로 설정한다.

    10. fullLengthblobsize로 설정한다.

    11. serializedFullLengthfullLength직렬화하고, isomorphic 인코딩한 결과로 설정한다.

    12. typeblobtype으로 설정한다.

    13. requestheader list에 `Range`가 포함되어 있지 않으면:

      1. bodyWithTypebody 안전 추출blob에 대해 실행한 결과로 설정한다.

      2. responsestatus message를 `OK`로 설정한다.

      3. responsebodybodyWithTypebody로 설정한다.

      4. responseheader list를 « (`Content-Length`, serializedFullLength), (`Content-Type`, type) »로 설정한다.

    14. 그 외의 경우:

      1. responserange-requested flag를 설정한다.

      2. rangeHeader가져오기를 사용해 requestheader list에서 `Range`를 가져온다.

      3. rangeValue단일 range 헤더 값 파싱rangeHeader 및 true로 실행한 결과로 설정한다.

      4. rangeValue가 실패이면 네트워크 오류를 반환한다.

      5. (rangeStart, rangeEnd)를 rangeValue로 설정한다.

      6. rangeStart가 null이면:

        1. rangeStartfullLengthrangeEnd로 설정한다.

        2. rangeEndrangeStart + rangeEnd − 1로 설정한다.

      7. 그 외의 경우:

        1. rangeStartfullLength보다 크거나 같으면, 네트워크 오류를 반환한다.

        2. rangeEnd가 null이거나 rangeEndfullLength보다 크거나 같으면 rangeEndfullLength − 1로 설정한다.

      8. slicedBlobslice blobblob, rangeStart, rangeEnd + 1, type에 대해 실행한 결과로 설정한다.

        range 헤더는 바이트 범위가 포함(inclusive)임을 나타내지만, slice blob 알고리즘은 입력 범위가 포함되지 않는다. slice blob을 사용하려면 rangeEnd를 증가시켜야 한다.

      9. slicedBodyWithTypebody 안전 추출slicedBlob에 대해 실행한 결과로 설정한다.

      10. responsebodyslicedBodyWithTypebody로 설정한다.

      11. serializedSlicedLengthslicedBlobsize직렬화하고 isomorphic 인코딩한 결과로 설정한다.

      12. contentRangeContent-Range 빌드rangeStart, rangeEnd, fullLength에 대해 실행한 결과로 설정한다.

      13. responsestatus를 206으로 설정한다.

      14. responsestatus message를 `Partial Content`로 설정한다.

      15. responseheader list를 « (`Content-Length`, serializedSlicedLength), (`Content-Type`, type), (`Content-Range`, contentRange) »로 설정한다.

    15. response를 반환한다.

    "data"
    1. dataURLStructdata: URL 처리기requestcurrent URL에 대해 실행한 결과로 설정한다.

    2. dataURLStruct가 실패이면 네트워크 오류를 반환한다.

    3. mimeTypedataURLStructMIME 타입직렬화한 값으로 설정한다.

    4. 새로운 response를 반환한다. status message는 `OK`, header list는 « (`Content-Type`, mimeType) », bodydataURLStructbodybody로 변환한 값이다.

    "file"

    현재로서는 아쉽게도 file: URL 처리는 독자에게 남겨진 과제이다.

    의심스러울 때는 네트워크 오류를 반환한다.

    HTTP(S) scheme

    HTTP fetchfetchParams에 대해 실행한 결과를 반환한다.

  4. 네트워크 오류를 반환한다.

환경 결정하기request request를 입력으로 받는다:

  1. requestreserved client가 null이 아니면, requestreserved client를 반환한다.

  2. requestclient가 null이 아니면, requestclient를 반환한다.

  3. null을 반환한다.

4.4. HTTP fetch

HTTP fetchfetch params fetchParams와 선택적 boolean makeCORSPreflight (기본값 false)를 입력으로 받아, 다음 단계들을 실행한다:

  1. requestfetchParamsrequest로 설정한다.

  2. responseinternalResponse를 null로 설정한다.

  3. requestservice-workers mode가 "all"이면:

    1. requestForServiceWorkerrequestclone으로 설정한다.

    2. requestForServiceWorkerbody가 null이 아니면:

      1. transformStream을 새로운 TransformStream 객체로 설정한다.

      2. transformAlgorithmchunk을 입력으로 아래 단계로 정의한다:

        1. fetchParams취소됨이면, 이 단계를 중지한다.

        2. chunkUint8Array 객체가 아니면 terminatefetchParamscontroller에 적용한다.

        3. 그 외의 경우, enqueue를 사용해 chunktransformStream에 넣는다. 사용자 에이전트는 chunk를 구현 정의의 적절한 크기로 분할하여 각각 enqueue하거나, chunk들을 구현 정의의 적절한 크기로 결합하여 enqueue할 수 있다.

      3. Set up을 사용해 transformStreamtransformAlgorithmtransformAlgorithm이 되도록 설정한다.

      4. requestForServiceWorkerbodystreamrequestForServiceWorkerbodystreampipeThroughtransformStream에 연결한 결과로 설정한다.

    3. serviceWorkerStartTimecoarsened shared current timefetchParamscross-origin isolated capability로 실행한 결과로 설정한다.

    4. responsehandle fetchrequestForServiceWorkerfetchParamscontroller, cross-origin isolated capability로 실행한 결과로 설정한다. [HTML] [SW]

    5. response가 null이 아니면:

      1. fetchParamstiming infofinal service worker start timeserviceWorkerStartTime으로 설정한다.

      2. requestbody가 null이 아니면 cancelrequestbody에 undefined와 함께 실행한다.

      3. internalResponseresponsefiltered response가 아니면 response, 그렇지 않으면 responseinternal response로 설정한다.

      4. 다음 중 하나가 참이면

        • responsetype이 "error"이다

        • requestmode가 "same-origin"이고 responsetype이 "cors"이다

        • requestmode가 "no-cors"가 아니고 responsetype이 "opaque"이다

        • requestredirect mode가 "manual"가 아니고 responsetype이 "opaqueredirect"이다
        • requestredirect mode가 "follow"가 아니고 responseURL list에 항목이 두 개 이상 있다

        이면 network error를 반환한다.

  4. response가 null이면:

    1. makeCORSPreflight이 true이고 다음 조건 중 하나라도 참이면:

      그렇다면:

      1. preflightResponseCORS-프리플라이트 fetchrequest에 대해 실행한 결과로 설정한다.

      2. preflightResponsenetwork error이면 preflightResponse를 반환한다.

      이 단계는 CORS-프리플라이트 캐시를 확인하고 적절한 엔트리가 없으면 CORS-프리플라이트 fetch를 수행하며, 성공 시 캐시를 채운다. CORS-프리플라이트 fetch의 목적은 fetch 리소스가 CORS 프로토콜을 인지하고 있음을 보장하는 데 있다. 캐시는 CORS-프리플라이트 fetch 횟수를 최소화하기 위해 존재한다.

    2. requestredirect mode가 "follow"이면, requestservice-workers mode를 "none"으로 설정한다.

      네트워크에서 발생한 리다이렉트는(서비스 워커로부터 발생한 것이 아닌 경우) 서비스 워커에 노출되어서는 안 된다.

    3. responseinternalResponseHTTP-네트워크-또는-캐시 fetchfetchParams에 대해 실행한 결과로 설정한다.

    4. requestresponse tainting가 "cors"이고 CORS 체크requestresponse에 대해 실행한 결과가 실패이면, network error를 반환한다.

      CORS 체크responsestatus가 304 또는 407일 때나, 서비스 워커에서 온 response에는 적용되지 않는다. 이 단계에서 적용된다.

    5. TAO 체크requestresponse에 대해 실행한 결과가 실패이면, requesttiming allow failed flag를 설정한다.

  5. requestresponse tainting 또는 responsetype이 "opaque"이고, cross-origin resource policy checkrequestorigin, requestclient, requestdestination, internalResponse로 실행한 결과가 blocked이면, network error를 반환한다.

    cross-origin resource policy check는 네트워크에서 온 response와 서비스 워커에서 온 response 모두에 대해 실행된다. 이는 CORS 체크와 다르며, requestclient와 서비스 워커는 서로 다른 embedder 정책을 가질 수 있다.

  6. internalResponsestatusredirect status이면:

    1. internalResponsestatus가 303이 아니고 requestbody가 null이 아니며 connection이 HTTP/2를 사용하는 경우, 사용자 에이전트는 RST_STREAM 프레임을 전송해도 된다(권장됨).

      303은 일부 커뮤니티에서 특별한 의미를 가지므로 제외된다.

    2. requestredirect mode에 따라 다음 단계 실행:

      "error"
      1. responsenetwork error로 설정한다.

      "manual"
      1. requestmode가 "navigate"이면, fetchParamscontrollernext manual redirect stepsHTTP-리다이렉트 fetchfetchParamsresponse로 실행하는 것으로 설정한다.

      2. 그 외의 경우, responseopaque-redirect filtered response로 설정하고 internal responseinternalResponse로 한다.

      "follow"
      1. responseHTTP-리다이렉트 fetchfetchParamsresponse로 실행한 결과로 설정한다.

  7. response를 반환한다. 일반적으로 internalResponsebodystream은 반환 후에도 계속 enqueue된다.

4.5. HTTP-리다이렉트 fetch

HTTP-리다이렉트 fetchfetch params fetchParamsresponse response를 받아, 다음 단계를 실행한다:

  1. requestfetchParamsrequest로 설정한다.

  2. internalResponseresponsefiltered response가 아니면 response, 그렇지 않으면 responseinternal response로 설정한다.

  3. locationURLinternalResponselocation URL로 설정하되, requestcurrent URLfragment를 사용한다.

  4. locationURL이 null이면 response를 반환한다.

  5. locationURL이 실패이면 network error를 반환한다.

  6. locationURLschemeHTTP(S) scheme이 아니면, network error를 반환한다.

  7. requestredirect count가 20이면, network error를 반환한다.

  8. requestredirect count를 1 증가시킨다.

  9. requestmode가 "cors"이고, locationURLcredentials를 포함하며, requestoriginlocationURLorigin동일 출처가 아니면, network error를 반환한다.

  10. requestresponse tainting이 "cors"이고 locationURLcredentials를 포함하면, network error를 반환한다.

    이는 교차 출처 리소스가 동일 출처 URL로 리다이렉트하는 경우를 포착한다.

  11. internalResponsestatus가 303이 아니고, requestbody가 null이 아니며, requestbodysource가 null이면, network error를 반환한다.

  12. 다음 중 하나가 참이면

    • internalResponsestatus가 301 또는 302이고 requestmethod가 `POST`이다

    • internalResponsestatus가 303이고 requestmethod가 `GET` 또는 `HEAD`가 아니다

    그렇다면:

    1. requestmethod를 `GET`으로, requestbody를 null로 설정한다.

    2. For each headerName of request-body-header name, delete headerNamerequestheader list에서 제거한다.

  13. requestcurrent URLoriginlocationURLorigin동일 출처가 아니면, for each headerName of CORS non-wildcard request-header name에 대해, delete headerNamerequestheader list에서 제거한다.

    즉, 최초 요청 이후 다른 origin이 나타나는 순간 `Authorization` 헤더가 제거된다.

  14. requestbody가 null이 아니면, requestbodybody로 설정하되, safely extractingrequestbodysource에 대해 실행한 결과의 body로 한다.

    requestbodysource가 null인지 여부는 이미 확인되었다.

  15. timingInfofetchParamstiming info로 설정한다.

  16. timingInforedirect end timepost-redirect start timecoarsened shared current time으로 설정하되, fetchParamscross-origin isolated capability를 사용한다.

  17. timingInforedirect start time이 0이면, timingInforedirect start timetimingInfostart time으로 설정한다.

  18. Append locationURLrequestURL list에 추가한다.

  19. request의 referrer policy를 redirect 시에 설정requestinternalResponse에 대해 호출한다. [REFERRER]

  20. recursive를 true로 설정한다.

  21. requestredirect mode가 "manual"이면:

    1. Assert: requestmode는 "navigate"이다.

    2. recursive를 false로 설정한다.

  22. main fetchfetchParamsrecursive로 실행한 결과를 반환한다.

    이는 main fetch를 호출하여 requestresponse tainting을 올바르게 결정하기 위함이다.

4.6. HTTP-네트워크-또는-캐시 fetch

HTTP-네트워크-또는-캐시 fetchfetch params fetchParams, 선택적 boolean isAuthenticationFetch (기본값 false), 선택적 boolean isNewConnectionFetch (기본값 false)를 받아 다음 단계를 실행한다:

일부 구현은 HTTP Caching에 따라 부분 콘텐츠의 캐싱을 지원할 수 있다. 그러나 이는 브라우저 캐시에서 널리 지원되지 않는다. [HTTP-CACHING]

  1. requestfetchParamsrequest로 설정한다.

  2. httpFetchParams를 null로 설정한다.

  3. httpRequest를 null로 설정한다.

  4. response를 null로 설정한다.

  5. storedResponse를 null로 설정한다.

  6. httpCache를 null로 설정한다.

  7. revalidatingFlag는 해제된 상태로 둔다.

  8. 다음 단계를 실행하되, abort when fetchParams취소됨이면 중단한다:

    1. requesttraversable for user prompts가 "no-traversable"이고 requestredirect mode가 "error"이면, httpFetchParamsfetchParams로, httpRequestrequest로 설정한다.

    2. 그 외의 경우:

      1. httpRequestrequestclone으로 설정한다.

        구현에서는 requestbodystream을 tee하지 않는 것이 권장된다. 특히 requestbodysource가 null인 경우에는 단일 body만 필요하기 때문이다. 예를 들어, requestbodysource가 null이면, 리다이렉트와 인증은 결국 fetch를 실패시킨다.

      2. httpFetchParamsfetchParams의 복사본으로 설정한다.

      3. httpFetchParamsrequesthttpRequest로 설정한다.

      사용자 프롬프트나 리다이렉트가 가능한 경우, 사용자 응답 또는 리다이렉트 위치 결정 후에 사용자 에이전트는 새로운 헤더 집합으로 요청을 다시 전송해야 할 수 있다. 그 시점에는 원래 요청 본문이 이미 부분적으로 전송되었을 수 있으므로, 사전에 요청(본문 포함)을 복제하여 예비 복사본을 확보해야 한다.

    3. includeCredentials를 다음 중 하나가 참이면 true로 설정한다:

      그 외의 경우 false로 설정한다.

    4. Cross-Origin-Embedder-Policy allows credentialsrequest에 대해 실행한 결과가 false이면, includeCredentials를 false로 설정한다.

    5. contentLengthhttpRequestbodylength로 설정하되, httpRequestbody가 null이 아닌 경우에만 해당하고, 그렇지 않으면 null로 설정한다.

    6. contentLengthHeaderValue를 null로 설정한다.

    7. httpRequestbody가 null이고 httpRequestmethod가 `POST` 또는 `PUT`이면, contentLengthHeaderValue를 `0`으로 설정한다.

    8. contentLength가 null이 아니면 contentLengthHeaderValuecontentLengthserialized하고 isomorphic encoded한 값으로 설정한다.

    9. contentLengthHeaderValue가 null이 아니면 append (`Content-Length`, contentLengthHeaderValue)를 httpRequestheader list에 추가한다.

    10. contentLength가 null이 아니고 httpRequestkeepalive가 true이면:

      1. inflightKeepaliveBytes를 0으로 설정한다.

      2. grouphttpRequestclientfetch group으로 설정한다.

      3. inflightRecordsgroupfetch recordsrequestkeepalive가 true이고 done flag가 해제된 것들의 집합으로 설정한다.

      4. For each fetchRecord of inflightRecords에 대해:

        1. inflightRequestfetchRecordrequest로 설정한다.

        2. inflightKeepaliveBytesinflightRequestbodylength를 더한다.

      5. contentLengthinflightKeepaliveBytes의 합이 64 키비바이트를 초과하면 network error를 반환한다.

      위 제한은 본문을 포함하고 environment settings object보다 오래 살아남을 수 있는 요청이 유한한 크기를 가지도록 하고 무기한 유지되지 않도록 보장한다.

    11. httpRequestreferrerURL이면:

      1. referrerValuehttpRequestreferrerserialized하고 isomorphic encoded한 값으로 설정한다.

      2. Append (`Referer`, referrerValue)를 httpRequestheader list에 추가한다.

    12. Append a request `Origin` headerhttpRequest에 대해 실행한다.

    13. Append the Fetch metadata headers for httpRequest. [FETCH-METADATA]

    14. httpRequestinitiator가 "prefetch"이면, set a structured field value를 (`Sec-Purpose`, token prefetch)로 httpRequestheader list에 설정한다.

    15. httpRequestheader listdoes not contain `User-Agent`이면, 사용자 에이전트는 append (`User-Agent`, default `User-Agent` value)를 httpRequestheader list에 수행해야 한다.

    16. httpRequestcache mode가 "default"이고 httpRequestheader listcontains `If-Modified-Since`, `If-None-Match`, `If-Unmodified-Since`, `If-Match`, 또는 `If-Range`이면, httpRequestcache mode를 "no-store"로 설정한다.

    17. httpRequestcache mode가 "no-cache"이고, httpRequestprevent no-cache cache-control header modification flag가 해제되어 있으며, httpRequestheader listdoes not contain `Cache-Control`이면, append (`Cache-Control`, `max-age=0`)를 httpRequestheader list에 수행한다.

    18. httpRequestcache mode가 "no-store" 또는 "reload"이면:

      1. httpRequestheader listdoes not contain `Pragma`이면, append (`Pragma`, `no-cache`)를 httpRequestheader list에 수행한다.

      2. httpRequestheader listdoes not contain `Cache-Control`이면, append (`Cache-Control`, `no-cache`)를 httpRequestheader list에 수행한다.

    19. httpRequestheader listcontains `Range`이면, append (`Accept-Encoding`, `identity`)를 httpRequestheader list에 수행한다.

      이는 인코딩된 response의 일부에 대해 handling content codings 시 실패를 방지한다.

      또한 많은 서버가 비-identity 인코딩이 허용되면 `Range` 헤더를 잘못 무시한다.

    20. HTTP에 따라 httpRequestheader list를 수정한다. 특정 headernamehttpRequestheader listcontains되어 있으면 해당 headerappend하지 않는다.

      이를 더 규범적으로 만들 수 있다면 좋겠지만, 현 시점에서는 `Accept-Encoding`, `Connection`, `DNT`, `Host` 등의 headers가 필요 시 appended되어야 한다.

      `Accept`, `Accept-Charset`, `Accept-Language`는 이 시점에 포함되어서는 안 된다.

      `Accept`와 `Accept-Language`는 이미 포함되어 있으며 (단, 기본적으로 후자를 포함하지 않는 fetch()를 사용하는 경우 제외), `Accept-Charset`는 바이트 낭비이다. 자세한 내용은 HTTP header layer division을 참조하라.

    21. includeCredentials가 true이면:

      1. Append a request `Cookie` headerhttpRequest에 대해 실행한다.

      2. httpRequestheader listdoes not contain `Authorization`이면:

        1. authorizationValue를 null로 설정한다.

        2. httpRequest에 대한 authentication entry가 존재하고, httpRequestuse-URL-credentials flag가 해제되어 있거나 httpRequestcurrent URLcredentials를 포함하지 않으면, authorizationValueauthentication entry로 설정한다.

        3. 그 외의 경우, httpRequestcurrent URLcredentials를 포함하고 isAuthenticationFetch가 true이면, authorizationValuehttpRequestcurrent URL`Authorization` 값으로 변환한 것으로 설정한다.

        4. authorizationValue가 null이 아니면 append (`Authorization`, authorizationValue)를 httpRequestheader list에 수행한다.

    22. proxy-authentication entry가 있으면, 적절히 사용한다.

      이는 의도적으로 httpRequestcredentials mode에 의존하지 않는다.

    23. httpCachedetermining the HTTP cache partitionhttpRequest에 대해 실행한 결과로 설정한다.

    24. httpCache가 null이면 httpRequestcache mode를 "no-store"로 설정한다.

    25. httpRequestcache mode가 "no-store"도 "reload"도 아니면:

      1. storedResponsehttpCache에서 응답을 선택한 결과(검증이 필요할 수 있음)로 설정하되, HTTP Caching의 "Constructing Responses from Caches" 장을 따른다(있다면). [HTTP-CACHING]

        HTTP의 요구에 따라 `Vary` header도 고려된다.

      2. storedResponse가 null이 아니면:

        1. cache mode가 "default"이고, storedResponsestale-while-revalidate response이며, httpRequestclient가 null이 아니면:

          1. responsestoredResponse로 설정한다.

          2. responsecache state를 "local"로 설정한다.

          3. revalidateRequestrequestclone으로 설정한다.

          4. revalidateRequestcache mode를 "no-cache"로 설정한다.

          5. revalidateRequestprevent no-cache cache-control header modification flag를 설정한다.

          6. revalidateRequestservice-workers mode를 "none"으로 설정한다.

          7. In parallel, main fetch를 실행하되, fetch params를 새로 만들고 그 requestrevalidateRequest로 설정한다.

            이 fetch는 httpCache의 상태를 갱신하기 위한 것이며, 다른 캐시 접근 전까지는 응답이 사용되지 않는다. 현재 요청에 대해서는 오래된 응답이 사용된다. 이 fetch는 client의 문맥에서 발행되므로 client가 사라지면 요청은 종료된다.

        2. 그 외의 경우:

          1. storedResponsestale response이면, revalidatingFlag를 설정한다.

          2. revalidatingFlag가 설정되어 있고 httpRequestcache mode가 "force-cache"도 "only-if-cached"도 아니면:

            1. storedResponseheader listcontains `ETag`이면, append (`If-None-Match`, `ETag`의 value)를 httpRequestheader list에 수행한다.

            2. storedResponseheader listcontains `Last-Modified`이면, append (`If-Modified-Since`, `Last-Modified`의 value)를 httpRequestheader list에 수행한다.

            또한 HTTP Caching의 "Sending a Validation Request" 장을 참조하라. [HTTP-CACHING]

          3. 그렇지 않으면 responsestoredResponse로 설정하고, responsecache state를 "local"로 설정한다.

  9. If aborted이면, fetchParams에 대한 appropriate network error를 반환한다.

  10. response가 null이면:

    1. httpRequestcache mode가 "only-if-cached"이면 network error를 반환한다.

    2. forwardResponseHTTP-네트워크 fetchhttpFetchParams, includeCredentials, isNewConnectionFetch로 실행한 결과로 설정한다.

    3. httpRequestmethodunsafe이고 forwardResponsestatus가 200 이상 399 이하이면, HTTP Caching의 "Invalidating Stored Responses" 장에 따라 httpCache에서 적절한 저장된 응답을 무효화하고, storedResponse를 null로 설정한다. [HTTP-CACHING]

    4. revalidatingFlag가 설정되어 있고 forwardResponsestatus가 304이면:

      1. storedResponseheader listforwardResponseheader list를 사용하여 갱신하되, HTTP Caching의 "Freshening Stored Responses upon Validation" 장을 따른다. [HTTP-CACHING]

        이는 캐시에 저장된 응답도 함께 업데이트한다.

      2. responsestoredResponse로 설정한다.

      3. responsecache state를 "validated"로 설정한다.

    5. response가 null이면:

      1. responseforwardResponse로 설정한다.

      2. httpRequestforwardResponsehttpCache에 저장하되, HTTP Caching의 "Storing Responses in Caches" 장을 따른다. [HTTP-CACHING]

        forwardResponsenetwork error이면, 이는 사실상 네트워크 오류를 캐시하는 것으로, 때때로 "negative caching"으로 알려져 있다.

        연관된 body info도 응답과 함께 캐시에 저장된다.

  11. responseURL listhttpRequestURL listclone으로 설정한다.

  12. httpRequestheader listcontains `Range`이면, responserange-requested flag를 설정한다.

  13. responserequest-includes-credentialsincludeCredentials로 설정한다.

  14. responsestatus가 401이고, httpRequestresponse tainting이 "cors"가 아니며, includeCredentials가 true이고, requesttraversable for user promptstraversable navigable이면:

    1. 테스트 필요: 다중 `WWW-Authenticate` 헤더, 누락, 파싱 이슈.

    2. requestbody가 null이 아니면:

      1. requestbodysource가 null이면, network error를 반환한다.

      2. requestbodybody로 설정하되, safely extractingrequestbodysource에 대해 실행한 결과의 body로 한다.

    3. requestuse-URL-credentials flag가 해제되어 있거나 isAuthenticationFetch가 true이면:

      1. fetchParams취소됨이면, fetchParams에 대한 appropriate network error를 반환한다.

      2. usernamepassword를 각각 사용자에게 requesttraversable for user prompts에서 프롬프트하여 얻는다.

      3. Set the usernamerequestcurrent URLusername으로 실행한다.

      4. Set the passwordrequestcurrent URLpassword로 실행한다.

    4. responseHTTP-네트워크-또는-캐시 fetchfetchParams와 true로 실행한 결과로 설정한다.

  15. responsestatus가 407이면:

    1. requesttraversable for user prompts가 "no-traversable"이면 network error를 반환한다.

    2. 테스트 필요: 다중 `Proxy-Authenticate` 헤더, 누락, 파싱 이슈.

    3. fetchParams취소됨이면, fetchParams에 대한 appropriate network error를 반환한다.

    4. 필요에 따라 최종 사용자를 requesttraversable for user prompts에서 프롬프트하고, 그 결과를 proxy-authentication entry로 저장한다. [HTTP]

      프록시 인증과 관련된 나머지 세부사항은 HTTP에서 정의된다.

    5. responseHTTP-네트워크-또는-캐시 fetchfetchParams에 대해 실행한 결과로 설정한다.

  16. 다음이 모두 참이면

    • responsestatus가 421이다

    • isNewConnectionFetch가 false이다

    • requestbody가 null이거나, requestbody가 null이 아니고 requestbodysource가 null이 아니다

    그렇다면:

    1. fetchParams취소됨이면, fetchParams에 대한 appropriate network error를 반환한다.

    2. responseHTTP-네트워크-또는-캐시 fetchfetchParams, isAuthenticationFetch, true로 실행한 결과로 설정한다.

  17. isAuthenticationFetch가 true이면, request와 주어진 realm에 대한 authentication entry를 만든다.

  18. response를 반환한다. 일반적으로 responsebodystream은 반환 후에도 계속 enqueue된다.

4.7. HTTP-네트워크 fetch

HTTP-네트워크 fetchfetch params fetchParams, 선택적 boolean includeCredentials (기본값 false), 선택적 boolean forceNewConnection (기본값 false)를 입력으로 받아, 다음 단계를 실행한다:

  1. requestfetchParamsrequest로 설정한다.

  2. response를 null로 설정한다.

  3. timingInfofetchParamstiming info로 설정한다.

  4. networkPartitionKey네트워크 파티션 키 결정하기request에 대해 실행한 결과로 설정한다.

  5. newConnectionforceNewConnection이 true이면 "yes", 아니면 "no"로 설정한다.

  6. requestmode에 따라 분기한다:

    "websocket"

    connectionWebSocket 연결 획득requestcurrent URL에 대해 실행한 결과로 설정한다.

    그 외의 경우

    connection연결 획득networkPartitionKey, requestcurrent URL, includeCredentials, newConnection을 사용하여 실행한 결과로 설정한다.

  7. 다음 단계를 실행하되, abort when fetchParams취소됨이면 중단한다:

    1. connection이 실패이면 network error를 반환한다.

    2. timingInfo최종 연결 타이밍 정보연결 타이밍 정보 클램프 및 조정하기connection타이밍 정보, timingInfo리다이렉트 후 시작 시간, fetchParamscross-origin 격리 기능으로 실행한 결과로 설정한다.

    3. connection이 HTTP/1.x 연결이고 requestbody가 null이 아니며 requestbodysource가 null이면 network error를 반환한다.

    4. timingInfo최종 네트워크 요청 시작 시간공유 현재 시간(조정됨)fetchParamscross-origin 격리 기능으로 실행한 결과로 설정한다.

    5. responseconnection에서 request를 사용하여 HTTP 요청을 만들어 얻은 결과로 설정하되, 다음 주의사항을 따른다:

      Fetch와 HTTP의 정확한 계층화는 아직 정리될 필요가 있으며, 여기서 responseresponse와 HTTP 응답을 모두 의미한다.

      HTTP 요청으로 인해 TLS 클라이언트 인증서 다이얼로그가 발생하면:

      1. request프롬프트를 위한 탐색 가능탐색 가능 객체라면, 그 대화 상자를 request프롬프트를 위한 탐색 가능에서 사용할 수 있도록 한다.

      2. 그렇지 않으면 network error를 반환한다.

      requestbody body를 전송하려면 다음 단계를 실행한다:

      1. body가 null이고 fetchParamsprocess request end-of-body가 null이 아니면, fetch task 큐잉fetchParamsprocess request end-of-bodyfetchParamstask destination으로 실행한다.

      2. 그렇지 않고 body가 null이 아니면:

        1. processBodyChunkbytes를 입력으로 다음 단계로 정의한다:

          1. fetchParams취소됨이면 이 단계를 중단한다.

          2. 병렬로 bytes를 전송한다.

          3. fetchParamsprocess request body chunk length가 null이 아니면, fetchParamsprocess request body chunk lengthbytes길이로 실행한다.

        2. processEndOfBody를 다음 단계로 정의한다:

          1. fetchParams취소됨이면 이 단계를 중단한다.

          2. fetchParamsprocess request end-of-body가 null이 아니면, fetchParamsprocess request end-of-body를 실행한다.

        3. processBodyErrore를 입력으로 다음 단계로 정의한다:

          1. fetchParams취소됨이면 이 단계를 중단한다.

          2. e가 "AbortError" DOMException이면 컨트롤러 중단fetchParamscontroller에 실행한다.

          3. 그 외에는 컨트롤러 종료fetchParamscontroller에 실행한다.

        4. body 점진적 읽기requestbody, processBodyChunk, processEndOfBody, processBodyError, fetchParamstask destination으로 실행한다.

  8. 중단된 경우:

    1. connection이 HTTP/2를 사용하면 RST_STREAM 프레임을 전송한다.

    2. fetchParams에 대한 적절한 네트워크 오류를 반환한다.

  9. buffer를 빈 바이트 시퀀스로 설정한다.

    이는 사용자 에이전트의 네트워크 계층 내부 버퍼를 의미한다.

  10. stream새로운 ReadableStream으로 설정한다.

  11. pullAlgorithm을 다음 단계로 정의한다:

    1. promise새로운 promise로 설정한다.

    2. 다음 단계를 병렬로 실행한다:

      1. buffer의 크기가 사용자 에이전트가 선택한 하한보다 작고 진행 중인 fetch가 중단됨이라면, fetch 재개를 실행한다.

      2. buffer가 비어 있지 않을 때까지 대기한다.

      3. fetch task 큐잉을 실행하여 다음 단계를 fetchParamstask destination으로 실행한다.

        1. bytes에서 pullbuffer에서 stream으로 실행한다.

        2. streamerrored 상태이면 컨트롤러 종료fetchParamscontroller에 실행한다.

        3. resolve promise를 undefined로 실행한다.

    3. promise를 반환한다.

  12. cancelAlgorithmreason을 입력받아 컨트롤러 중단fetchParamscontrollerreason과 함께 실행하는 알고리즘으로 설정한다.

  13. byte 읽기 지원으로 stream 설정stream에 대해 실행하되, pullAlgorithmpullAlgorithm으로, cancelAlgorithmcancelAlgorithm으로 설정한다.

  14. responsebodybody로 새로 만들고, streamstream으로 설정한다.

  15. (This is a tracking vector.) includeCredentials가 true이면, 사용자 에이전트는 응답 Set-Cookie 헤더 파싱 및 저장requestresponse로 실행해야 한다.

  16. 다음 단계를 병렬로 실행한다:

    1. 다음 단계를 abort when fetchParams취소됨이면 중단한다:

      1. 다음이 참일 동안:

        1. response의 메시지 body에서 하나 이상의 바이트가 전송되었다면:

          1. bytes를 전송된 바이트로 설정한다.

          2. codings헤더 리스트 값 추출을 `Content-Encoding`과 responseheader list에 대해 실행한 결과로 설정한다.

          3. filteredCoding을 "@unknown"으로 설정한다.

          4. codings가 null 또는 실패이면 filteredCoding을 빈 문자열로 설정한다.

          5. 그 외에 codingssize가 1보다 크면 filteredCoding을 "multiple"로 설정한다.

          6. 그 외에 codings[0]이 빈 문자열이거나, 사용자 에이전트가 지원하고, 바이트 대소문자 구분 없이 HTTP Content Coding Registry에 포함된 엔트리와 일치하면, filteredCoding바이트 소문자화 codings[0]으로 설정한다. [IANA-HTTP-PARAMS]

          7. responsebody infocontent encodingfilteredCoding으로 설정한다.

          8. responsebody infoencoded sizebytes길이만큼 증가시킨다.

          9. bytes콘텐츠 코딩 처리codingsbytes로 실행한 결과로 설정한다.

            이로 인해 `Content-Length` 헤더의 신뢰성이 저하될 수 있다.

          10. responsebody infodecoded sizebytes길이만큼 증가시킨다.

          11. bytes가 실패이면 컨트롤러 종료fetchParamscontroller에 실행한다.

          12. bytesbuffer에 추가한다.

          13. buffer의 크기가 사용자 에이전트가 선택한 상한보다 크면, 진행 중인 fetch를 중단하도록 사용자 에이전트에 요청한다.

        2. 그 외에 response의 메시지 body 바이트 전송이 정상적으로 완료되고 streamreadable이면, stream 닫기stream에 실행하고 병렬 실행 단계를 중단한다.

    2. 중단된 경우:

      1. fetchParamsaborted이면:

        1. responseaborted flag를 설정한다.

        2. streamreadable이면, stream errorstream에 실행하고, 중단 이유 역직렬화fetchParamscontrollerserialized abort reason과 구현 정의 realm으로 실행한 결과로 실행한다.

      2. 그 외에 streamreadable이면, stream errorstreamTypeError로 실행한다.

      3. connection이 HTTP/2를 사용하면 RST_STREAM 프레임을 전송한다.

      4. 그 외에는, 다음 fetch에 성능 저하가 없다면 사용자 에이전트가 connection을 닫아야 한다.

        예를 들어, 재사용 가능한 연결에서 몇 바이트만 남았다는 것을 알고 있다면 닫지 않는 것이 더 좋을 수 있다. 이 경우 연결을 닫고 다음 fetch에서 핸드셰이크를 다시 하는 것이 오히려 더 나쁠 수 있다.

    이 단계는 병렬로 실행되며, 이 시점에서는 responsebody가 관련 있는지 알 수 없다(response가 리다이렉트일 수 있음).

  17. response를 반환한다. 일반적으로 responsebodystream은 반환 후에도 계속 enqueue된다.

4.8. CORS-프리플라이트 fetch

이 알고리즘은 CORS 프로토콜을 이해하는지 사용자 에이전트가 확인하는 구현이다. 이른바 CORS-프리플라이트 요청이다. 성공하면 CORS-프리플라이트 캐시를 채워 이런 fetch의 수를 최소화한다.

CORS-프리플라이트 fetchrequest request를 입력으로 받아 다음 단계를 실행한다:

  1. preflight를 새로운 request로 생성한다. 이때 method는 `OPTIONS`, URL listrequestURL list복제본, initiatorrequestinitiator, destinationrequestdestination, originrequestorigin, referrerrequestreferrer, referrer policyrequestreferrer policy, mode는 "cors", 그리고 response tainting은 "cors"로 설정한다.

    preflightservice-workers mode는 중요하지 않다. 이 알고리즘은 HTTP-네트워크-또는-캐시 fetch를 사용하며 HTTP fetch는 사용하지 않는다.

  2. Append (`Accept`, `*/*`)를 preflightheader list에 추가한다.

  3. Append (`Access-Control-Request-Method`, requestmethod)를 preflightheader list에 추가한다.

  4. headersrequestheader listCORS-비안전 요청 헤더 이름을 구한 결과로 설정한다.

  5. headers비어 있지 않으면:

    1. valueheaders의 항목을 `,`로 연결한 문자열로 설정한다.

    2. Append (`Access-Control-Request-Headers`, value)를 preflightheader list에 추가한다.

    이 단계는 combine을 사용하지 않는다. 0x2C 뒤에 0x20이 붙는 방식이 실제 구현과 다르기 때문이다.

  6. responseHTTP-네트워크-또는-캐시 fetch를 새로운 fetch paramsrequestpreflight로 설정해서 실행한 결과로 설정한다.

  7. CORS 체크requestresponse에 대해 실행한 결과가 성공이고 responsestatusok status이면:

    CORS 체크preflight가 아닌 request에 대해 실행하며 이는 올바른 credentials mode를 사용하도록 하기 위함이다.

    1. methods헤더 리스트 값 추출을 `Access-Control-Allow-Methods`와 responseheader list에 대해 실행한 결과로 설정한다.

    2. headerNames헤더 리스트 값 추출을 `Access-Control-Allow-Headers`와 responseheader list에 대해 실행한 결과로 설정한다.

    3. methodsheaderNames가 실패이면 network error를 반환한다.

    4. methods가 null이고 requestuse-CORS-preflight flag 가 설정되어 있으면, methodsrequestmethod를 포함한 새 리스트로 설정한다.

      CORS-프리플라이트 fetchrequestuse-CORS-preflight flag에 의해 발생했다면 캐시된다.

    5. requestmethodmethods에 없고, requestmethodCORS-허용 메서드가 아니고, requestcredentials mode가 "include"이거나 methods에 `*`가 없으면 network error를 반환한다.

    6. requestheader list이름들 중 하나라도 CORS non-wildcard 요청 헤더 이름이면서 headerNames항목바이트 대소문자 구분 없이 일치하지 않으면 network error를 반환한다.

    7. For each unsafeName of CORS-비안전 요청 헤더 이름requestheader list로 구한 결과 중, unsafeNameheaderNames항목바이트 대소문자 구분 없이 일치하지 않고, requestcredentials mode가 "include"이거나 headerNames에 `*`가 없으면, network error를 반환한다.

    8. max-age헤더 리스트 값 추출을 `Access-Control-Max-Age`와 responseheader list에 대해 실행한 결과로 설정한다.

    9. max-age가 실패 또는 null이면 max-age를 5로 설정한다.

    10. max-agemax-age의 제한값을 초과하면 max-age를 제한값으로 설정한다.

    11. 사용자 에이전트가 캐시를 제공하지 않으면 response를 반환한다.

    12. methods에 있는 각 methodrequest를 사용하여 method 캐시 엔트리 일치가 있으면, 해당 엔트리의 max-agemax-age로 설정한다.

    13. methods에 있는 각 methodrequest를 사용하여 method 캐시 엔트리 일치가 없으면, 새 캐시 엔트리 생성request, max-age, method, null로 실행한다.

    14. headerNames에 있는 각 headerName으로 request를 사용하여 헤더 이름 캐시 엔트리 일치가 있으면, 해당 엔트리의 max-agemax-age로 설정한다.

    15. headerNames에 있는 각 headerName으로 request를 사용하여 헤더 이름 캐시 엔트리 일치가 없으면, 새 캐시 엔트리 생성request, max-age, null, headerName으로 실행한다.

    16. response를 반환한다.

  8. 그 외에는 network error를 반환한다.

4.9. CORS-프리플라이트 캐시

사용자 에이전트는 CORS-프리플라이트 캐시를 가진다. CORS-프리플라이트 캐시리스트이며, 캐시 엔트리들의 리스트이다.

캐시 엔트리는 다음으로 구성된다:

캐시 엔트리는 저장된 후 max-age 필드에 지정된 초가 지나면 제거되어야 한다. 캐시 엔트리는 그 이전에 제거될 수도 있다.

새 캐시 엔트리 생성request, max-age, method, headerName을 입력으로, 다음 단계를 실행한다:

  1. entry캐시 엔트리로 설정하며, 초기화는 다음과 같이 한다:

    key

    네트워크 파티션 키 결정하기request로 실행한 결과

    byte-serialized origin

    요청 origin을 바이트 직렬화request로 실행한 결과

    URL

    requestcurrent URL

    max-age

    max-age

    credentials

    requestcredentials mode가 "include"이면 true, 아니면 false

    method

    method

    header name

    headerName

  2. Append entry를 사용자 에이전트의 CORS-프리플라이트 캐시에 추가한다.

캐시 엔트리 삭제request를 입력으로, remove를 사용해 사용자 에이전트의 CORS-프리플라이트 캐시에서 다음 조건에 해당하는 캐시 엔트리를 모두 제거한다: key네트워크 파티션 키 결정하기request로 실행한 결과, byte-serialized origin요청 origin 바이트 직렬화request로 실행한 결과, URLrequestcurrent URL인 경우.

캐시 엔트리 일치캐시 엔트리 entryrequest에 대해 다음이 모두 참인 경우이다: entrykey네트워크 파티션 키 결정하기request로 실행한 결과, entrybyte-serialized origin요청 origin 바이트 직렬화request로 실행한 결과, entryURLrequestcurrent URL이며, 다음 중 하나가 참일 때이다:

위 조건이 참이다.

method 캐시 엔트리 일치methodrequest에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시에 다음이 있는 경우이다: 캐시 엔트리가 있고, 캐시 엔트리 일치request에 대해 참이며, 해당 캐시 엔트리의 methodmethod 또는 `*`일 때.

헤더 이름 캐시 엔트리 일치headerNamerequest에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시에 다음이 있는 경우이다: 캐시 엔트리가 있고, 캐시 엔트리 일치request에 대해 참이며, 다음 중 하나가 참일 때:

위 조건이 참이다.

4.10. CORS 체크

CORS 체크requestresponse에 대해 다음 단계를 실행한다:

  1. origin가져오기로 `Access-Control-Allow-Origin`을 responseheader list에서 가져온 값으로 설정한다.

  2. origin이 null이면 실패를 반환한다.

    null은 `null`와 다르다.

  3. requestcredentials mode가 "include"가 아니고 origin이 `*`이면 성공을 반환한다.

  4. 요청 origin 바이트 직렬화request로 실행한 결과가 origin과 다르면 실패를 반환한다.

  5. requestcredentials mode가 "include"가 아니면 성공을 반환한다.

  6. credentials가져오기로 `Access-Control-Allow-Credentials`를 responseheader list에서 가져온 값으로 설정한다.

  7. credentials가 `true`이면 성공을 반환한다.

  8. 실패를 반환한다.

4.11. TAO 체크

TAO 체크requestresponse에 대해 다음 단계를 실행한다:

  1. Assert: requestorigin은 "client"가 아니다.

  2. requesttiming allow failed flag가 설정되어 있으면 실패를 반환한다.

  3. values가져오기, 디코드, 분할로 `Timing-Allow-Origin`을 responseheader list에서 얻은 값으로 설정한다.

  4. values가 "*"를 포함하면 성공을 반환한다.

  5. values요청 origin 직렬화request로 실행한 결과를 포함하면 성공을 반환한다.

  6. requestmode가 "navigate"이고 requestcurrent URLoriginrequestorigin동일 출처가 아니면 실패를 반환한다.

    이는 중첩된 navigable의 네비게이션에 필요하다. 이 경우 requestorigin은 컨테이너 문서의 origin이 되고, TAO 체크는 실패를 반환한다. 네비게이션 타이밍은 TAO 체크 결과를 검증하지 않으므로, 중첩 문서는 전체 타이밍 정보를 얻지만 컨테이너 문서는 얻지 못한다.

  7. requestresponse tainting이 "basic"이면 성공을 반환한다.

  8. 실패를 반환한다.

4.12. 지연 fetch

지연 fetch는 호출자가 fetch를 가능한 가장 늦은 시점에 실행하도록 요청할 수 있게 해준다. 즉, fetch group종료될 때나, 타임아웃 후에 fetch가 실행된다.

지연 fetch 태스크 소스태스크 소스이며, 지연 fetch 결과를 업데이트하는 데 사용된다. 사용자 에이전트는 이 태스크 소스의 태스크를, 스크립트 실행을 유발할 수 있는 다른 태스크 소스들(예: DOM 조작 태스크 소스)보다 우선적으로 실행해야 한다. 이는 fetchLater() 호출의 최신 상태가, 그에 의존할 수 있는 스크립트 실행 전에 반영되도록 하기 위함이다.

지연 fetch 큐잉request request, null 또는 DOMHighResTimeStamp activateAfter, 그리고 인자를 받지 않는 알고리즘 onActivatedWithoutTermination을 입력으로 한다:

  1. 클라이언트로부터 request 채우기request에 대해 실행한다.

  2. requestservice-workers mode를 "none"으로 설정한다.

  3. requestkeepalive를 true로 설정한다.

  4. deferredRecord를 새로운 지연 fetch 레코드로 생성하며, requestrequest, notify invokedonActivatedWithoutTermination로 한다.

  5. Append deferredRecordrequestclientfetch groupdeferred fetch records에 추가한다.

  6. activateAfter가 null이 아니면, 다음 단계를 병렬로 실행한다:

    1. 사용자 에이전트는 다음 중 하나의 조건이 만족될 때까지 대기해야 한다:

      • activateAfter 밀리초가 경과함

      • 사용자 에이전트가 스크립트 실행 기회를 곧 잃을 것이라고 판단함(예: 브라우저가 백그라운드로 이동하거나, requestclientglobal objectWindow 객체이고, 연결된 document가 오랜 기간 "hidden" visibility state를 갖는 경우)

    2. 지연 fetch 처리deferredRecord에 실행한다.

  7. deferredRecord를 반환한다.

request 총 길이 계산request request를 입력으로 한다:

  1. totalRequestLengthrequestURL직렬화(단, exclude fragment는 true)한 길이로 설정한다.

  2. totalRequestLengthrequestreferrer직렬화길이를 더한다.

  3. requestheader list의 각 (name, value)에 대해, totalRequestLengthname길이 + value길이를 더한다.

  4. totalRequestLengthrequestbody길이를 더한다.

  5. totalRequestLength를 반환한다.

지연 fetch 처리들fetch group fetchGroup을 입력으로 한다:

  1. For each deferred fetch record deferredRecord of fetchGroupdeferred fetch records에 대해, 지연 fetch 처리deferredRecord에 실행한다.

지연 fetch 처리deferredRecord를 입력으로 한다:

  1. deferredRecordinvoke state가 "pending"이 아니면 return 한다.

  2. deferredRecord