패치

현행 표준 — 마지막 갱신

참여:
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.
process request body chunk length (기본값 null)
process request end-of-body (기본값 null)
process early hints response (기본값 null)
process response (기본값 null)
process response end-of-body (기본값 null)
process response consume body (기본값 null)
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` 헤더용).

문서 `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"를 반환한다.

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 fetchfetchParams로 실행한 결과를 반환한다.

    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 fetchfetchParams로 실행한 결과를 반환한다.

    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. corsWithPreflightResponseHTTP fetchfetchParams와 true로 실행한 결과로 둔다.

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

    4. corsWithPreflightResponse를 반환한다.

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

    2. HTTP fetchfetchParams로 실행한 결과를 반환한다.

  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

스킴 fetch를 실행하려면, fetch 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는 빈 바이트 시퀀스 as a body로 설정하여 반환한다.

    URL 중 "about:config" 등은 탐색 중 처리되며, fetching에서는 네트워크 에러가 된다.

    "blob"
    1. blobURLEntryrequestcurrent URLblob URL entry로 둔다.

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

      `GET` method 제한은 상호 운용성 이외에 특별한 목적 없음.

    3. requestEnvironmentdetermine the environmentrequest로 실행한 결과로 둔다.

    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. serializedFullLengthfullLengthserialize하고 isomorphic encode한 결과로 둔다.

    12. typeblobtype으로 둔다.

    13. requestheader list가 `Range`를 포함하지 않으면:

      1. bodyWithTypesafely extractingblob으로 실행한 결과로 둔다.

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

      3. responsebodybodyWithTypebody로 설정한다.

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

    14. 그 외의 경우:

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

      2. rangeHeaderget을 `Range`와 requestheader list로 실행한 결과로 둔다.

      3. rangeValueparsing a single range header valuerangeHeader와 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 헤더는 바이트 범위를 포함하지만, slice blob 알고리즘은 그렇지 않으므로 rangeEnd를 1 증가시켜야 한다.

      9. slicedBodyWithTypesafely extractingslicedBlob으로 실행한 결과로 둔다.

      10. responsebodyslicedBodyWithTypebody로 설정한다.

      11. serializedSlicedLengthslicedBlobsizeserialize하고 isomorphic encode한 결과로 둔다.

      12. contentRangebuild a content rangerangeStart, 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 processorrequestcurrent URL로 실행한 결과로 둔다.

    2. dataURLStruct가 실패면, 네트워크 에러를 반환한다.

    3. mimeTypedataURLStructMIME typeserialize한 결과로 둔다.

    4. response를 생성하여, status message는 `OK`, header list는 « (`Content-Type`, mimeType) », bodydataURLStructbodyas a body로 설정하여 반환한다.

    "file"

    현재로서는 아쉽게도 file: URL은 독자의 몫으로 남겨둔다.

    의심스러울 경우, 네트워크 에러를 반환한다.

    HTTP(S) scheme

    HTTP fetchfetchParams로 실행한 결과를 반환한다.

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

환경 결정을 실행하려면, request request를 받아:

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

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

  3. null을 반환한다.

4.3. HTTP 가져오기

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

  1. requestfetchParamsrequest로 둔다.

  2. responseinternalResponse를 null로 둔다.

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

    1. requestForServiceWorkerrequest복제본으로 둔다.

    2. requestForServiceWorkerbody가 null이 아니면:

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

      2. transformAlgorithmchunk를 받아 다음 단계로 설정한다:

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

        2. chunkUint8Array 객체가 아니면, 종료fetchParamscontroller에 대해 실행한다.

        3. 그 외에는 enqueue chunktransformStream에 넣는다. 사용자 에이전트는 chunk를 구현 정의 실제 크기로 나누어 각각 enqueue 할 수 있다. 또한 여러 chunk를 구현 정의 실제 크기로 합쳐 enqueue할 수 있다.

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

      4. requestForServiceWorkerbodystreamrequestForServiceWorkerbodystream파이프한 결과로 둔다.

    3. serviceWorkerStartTimecoarsened shared current time으로, fetchParamscross-origin isolated capability를 인자로 설정한다.

    4. responsehandle fetchrequestForServiceWorker, fetchParamscontroller, fetchParamscross-origin isolated capability로 실행한 결과로 둔다.

    5. response가 null이 아니면:

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

      2. requestbody가 null이 아니면, cancel requestbody를 undefined로 실행한다.

      3. internalResponseresponsefiltered response가 아니면 response로, 아니면 responseinternal response로 설정한다.

      4. 다음 중 하나라도 true이면

        • responsetype이 "error"임

        • requestmode가 "same-origin"이고, responsetype이 "cors"임

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

        • requestredirect mode가 "manual"가 아니고, responsetype이 "opaqueredirect"임
        • requestredirect mode가 "follow"가 아니고, responseURL list가 한 개를 초과함

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

  4. response가 null이면:

    1. makeCORSPreflight가 true이고 다음 중 하나라도 true이면:

      이 경우:

      1. preflightResponseCORS-preflight fetchrequest로 실행한 결과로 둔다.

      2. preflightResponse네트워크 에러이면 preflightResponse를 반환한다.

      이 단계는 CORS-preflight cache를 확인하고 적절한 엔트리가 없으면 CORS-preflight fetch를 실행한다. 성공하면 캐시에 저장한다. CORS-preflight fetch의 목적은 가져온 리소스가 CORS 프로토콜을 인식하는지 확인하는 것이다. 캐시는 CORS-preflight fetch의 횟수를 최소화한다.

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

      네트워크에서 발생한 리다이렉트(서비스 워커에서 발생한 것이 아닌)는 서비스 워커에 노출되지 않는다.

    3. responseinternalResponseHTTP-network-or-cache fetchfetchParams로 실행한 결과로 설정한다.

    4. requestresponse tainting이 "cors"이고, requestresponse에 대해 CORS check가 실패하면 네트워크 에러를 반환한다.

      CORS checkresponsestatus가 304 또는 407인 경우, 또는 서비스 워커에서 온 경우에는 적용하지 않으며, 여기서 적용한다.

    5. requestresponse에 대해 TAO check가 실패하면 requesttiming allow failed flag를 설정한다.

  5. requestresponse tainting 또는 responsetype이 "opaque"이고, cross-origin resource policy checkrequestorigin, requestclient, requestdestination, internalResponse로 실행하여 blocked를 반환하면 네트워크 에러를 반환한다.

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

  6. internalResponsestatusredirect status이면:

    1. internalResponsestatus가 303이 아니고, requestbody가 null이 아니며, connection이 HTTP/2를 사용하면, 사용자 에이전트는 RST_STREAM 프레임을 전송할 수 있으며, 권장된다.

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

    2. requestredirect mode에 따라 아래 단계를 실행한다:

      "error"
      1. response네트워크 에러로 설정한다.

      "manual"
      1. requestmode가 "navigate"이면, fetchParamscontrollernext manual redirect stepsHTTP-redirect fetchfetchParamsresponse로 실행하는 단계로 설정한다.

      2. 그 외에는 responseopaque-redirect filtered response로 설정하며, internal responseinternalResponse로 둔다.

      "follow"
      1. responseHTTP-redirect fetchfetchParamsresponse로 실행한 결과로 설정한다.

  7. response를 반환한다. 일반적으로 internalResponsebodystream이 반환 후에도 enqueue되고 있을 수 있다.

4.4. HTTP 리다이렉트 fetch

HTTP-redirect fetch를 실행하려면, fetch params fetchParamsresponse response를 받아 다음 단계를 실행한다:

  1. requestfetchParamsrequest로 둔다.

  2. internalResponseresponsefiltered response가 아니면 response로, 아니면 responseinternal response로 둔다.

  3. locationURLinternalResponselocation URL로, requestcurrent URLfragment를 인자로 사용한다.

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

  5. locationURL이 실패면 네트워크 에러를 반환한다.

  6. locationURLschemeHTTP(S) scheme이 아니면 네트워크 에러를 반환한다.

  7. requestredirect count가 20이면, 네트워크 에러를 반환한다.

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

  9. requestmode가 "cors"이고, locationURLcredentials를 포함하며, requestoriginlocationURLoriginsame origin이 아니면, 네트워크 에러를 반환한다.

  10. requestresponse tainting이 "cors"이고, locationURLcredentials를 포함하면, 네트워크 에러를 반환한다.

    이 규칙은 교차 출처 리소스가 동일 출처 URL로 리다이렉트할 때를 잡아낸다.

  11. internalResponsestatus가 303이 아니고, requestbody가 null이 아니며, requestbodysource가 null이면, 네트워크 에러를 반환한다.

  12. 다음 중 하나라도 true이면

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

    • internalResponsestatus가 303이고, requestmethod가 `GET` 또는 `HEAD`가 아님

    이 경우:

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

    2. headerName에 대해 request-body-header name삭제한다. requestheader list에서 headerName을 삭제한다.

  13. requestcurrent URLoriginlocationURLoriginsame origin이 아니면, headerName에 대해 CORS non-wildcard request-header name삭제한다. requestheader list에서 headerName을 삭제한다.

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

  14. requestbody가 null이 아니면, requestbodybody로, safely extractingrequestbodysource로 실행한 결과로 설정한다.

    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 설정requestinternalResponse로 실행한다. [REFERRER]

  20. recursive를 true로 둔다.

  21. requestredirect mode가 "manual"이면:

    1. Assert: requestmode가 "navigate"임

    2. recursive를 false로 설정한다.

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

    이 단계는 main fetch를 호출하여 requestresponse tainting 값을 올바르게 설정한다.

4.5. HTTP-네트워크-또는-캐시 가져오기

HTTP-네트워크-또는-캐시 가져오기를 실행하려면, fetch params fetchParams, 선택적 불리언 isAuthenticationFetch(기본값 false), 선택적 불리언 isNewConnectionFetch(기본값 false)를 받아 다음 단계를 수행한다:

일부 구현체는 HTTP 캐싱에 따라 부분 콘텐츠의 캐싱을 지원할 수 있습니다. 하지만 브라우저 캐시에서는 널리 지원되지 않습니다. [HTTP-CACHING]

  1. requestfetchParamsrequest로 둔다.

  2. httpFetchParams를 null로 둔다.

  3. httpRequest를 null로 둔다.

  4. response를 null로 둔다.

  5. storedResponse를 null로 둔다.

  6. httpCache를 null로 둔다.

  7. revalidatingFlag를 unset으로 둔다.

  8. 아래 단계를 실행하지만 abort when fetchParams취소됨이면 중단한다:

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

    2. 그 외의 경우:

      1. httpRequestrequest복제본으로 설정한다.

        구현체는 requestbodystream을 tee하는 것을 피하는 것이 권장된다. requestbodysource가 null인 경우 단일 body만 필요하다. 예를 들어, body의 source가 null이면 리다이렉트와 인증이 fetch 실패로 끝난다.

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

      3. httpFetchParamsrequesthttpRequest로 설정한다.

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

    3. includeCredentials를 아래 중 하나라도 true이면 true로, 아니면 false로 설정한다:

    4. Cross-Origin-Embedder-Policy에서 credentials 허용request로 false를 반환하면 includeCredentials를 false로 설정한다.

    5. contentLengthhttpRequestbodylength로, body가 null이면 null로 설정한다.

    6. contentLengthHeaderValue를 null로 둔다.

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

    8. contentLength가 null이 아니면 contentLengthHeaderValuecontentLength로, serializeisomorphic encode를 적용한 결과로 설정한다.

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

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

      1. inflightKeepaliveBytes를 0으로 둔다.

      2. grouphttpRequestclientfetch group으로 둔다.

      3. inflightRecordsgroupfetch record들 중 requestkeepalive가 true이고, done flag가 unset인 것의 집합으로 둔다.

      4. fetchRecord에 대해:

        1. inflightRequestfetchRecordrequest로 둔다.

        2. inflightKeepaliveBytesinflightRequestbodylength만큼 증가시킨다.

      5. contentLengthinflightKeepaliveBytes의 합이 64키비바이트 넘으면 네트워크 에러를 반환한다.

      위 제한은 body가 있는 요청이 환경 설정 객체보다 오래 살아남을 수 있는 경우, 크기가 제한되고 무한히 살아남지 않도록 보장한다.

    11. httpRequestreferrerURL이면:

      1. referrerValuehttpRequestreferrerserialize하고 isomorphic encode한 값으로 둔다.

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

    12. 요청 `Origin` 헤더 추가httpRequest로 실행한다.

    13. Fetch 메타데이터 헤더 추가httpRequest로 실행한다. [FETCH-METADATA]

    14. httpRequestinitiator가 "prefetch"이면 구조화 필드값 설정을 (`Sec-Purpose`, 토큰 prefetch)로 httpRequestheader list에 설정한다.

    15. httpRequestheader list가 `User-Agent`를 포함하지 않으면, 사용자 에이전트는 append (`User-Agent`, 기본 `User-Agent` 값)을 httpRequestheader list에 추가해야 한다.

    16. httpRequestcache mode가 "default"이고 httpRequestheader list가 `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가 unset이며, httpRequestheader list가 `Cache-Control`을 포함하지 않으면 append (`Cache-Control`, `max-age=0`)를 httpRequestheader list에 추가한다.

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

      1. httpRequestheader list가 `Pragma`를 포함하지 않으면 append (`Pragma`, `no-cache`)를 httpRequestheader list에 추가한다.

      2. httpRequestheader list가 `Cache-Control`을 포함하지 않으면, append (`Cache-Control`, `no-cache`)를 httpRequestheader list에 추가한다.

    19. httpRequestheader list가 `Range`를 포함하면, append (`Accept-Encoding`, `identity`)를 httpRequestheader list에 추가한다.

      이 단계는 콘텐츠 코딩 처리 시 인코딩된 response 일부와 관련된 실패를 방지한다.

      또한, 많은 서버는 비-identity 인코딩이 허용될 때 `Range` 헤더를 잘못 무시한다.

    20. httpRequestheader list를 HTTP에 따라 수정한다. appendhttpRequestheader list에 해당 headername이 이미 있으면 추가하지 않는다.

      이 부분을 더 규범적으로 만들 수 있으면 좋겠다. 이 시점에서 `Accept-Encoding`, `Connection`, `DNT`, `Host`는 필요하면 append된다.

      `Accept`, `Accept-Charset`, `Accept-Language`는 이 시점에 포함되지 않아야 한다.

      `Accept`, `Accept-Language`는 이미 포함됨(fetch()에서는 기본적으로 포함되지 않음), `Accept-Charset`는 불필요한 바이트다. 자세한 내용은 HTTP 헤더 계층 분리 참고.

    21. includeCredentials가 true이면:

      1. 요청 `Cookie` 헤더 추가httpRequest에 대해 실행한다.

      2. httpRequestheader list가 `Authorization`를 포함하지 않으면:

        1. authorizationValue를 null로 둔다.

        2. authentication entryhttpRequest에 대해 존재하고, httpRequestuse-URL-credentials flag가 unset이거나, 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. httpCacheHTTP 캐시 파티션 결정httpRequest로 실행한 결과로 설정한다.

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

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

      1. storedResponsehttpCache에서 응답을 선택한 결과로 설정한다. 필요하면 검증해야 한다. 자세한 내용은 HTTP 캐싱의 "Constructing Responses from Caches" 챕터 참고. [HTTP-CACHING]

        HTTP 요구에 따라, `Vary` 헤더도 고려된다.

      2. storedResponse가 null이 아니면:

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

          1. responsestoredResponse로 설정한다.

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

          3. revalidateRequestrequest복제본으로 설정한다.

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

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

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

          7. 병렬로 main fetch를 새 fetch params로 실행한다. requestrevalidateRequest로 둔다.

            이 fetch는 httpCache의 상태를 갱신하는 용도이며, 응답은 다음 캐시 접근 전까지 사용되지 않는다. stale 응답이 현재 요청의 응답으로 사용된다. 이 fetch는 client 컨텍스트에서 발행되므로 client가 사라지면 요청도 종료된다.

        2. 그 외의 경우:

          1. storedResponsestale response이면 revalidatingFlag를 설정한다.

          2. revalidatingFlag가 설정되어 있고, httpRequestcache mode가 "force-cache" 또는 "only-if-cached"가 아니면:

            1. storedResponseheader list에 `ETag`가 포함되어 있으면 append (`If-None-Match`, `ETag`의 value)를 httpRequestheader list에 추가한다.

            2. storedResponseheader list에 `Last-Modified`가 포함되어 있으면 append (`If-Modified-Since`, `Last-Modified`의 value)를 httpRequestheader list에 추가한다.

            HTTP 캐싱의 "검증 요청 보내기" 챕터 참고. [HTTP-CACHING]

          3. 그 외에는 responsestoredResponse로 설정하고 responsecache state를 "local"로 설정한다.

  9. aborted라면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.

  10. response가 null이면:

    1. httpRequestcache mode가 "only-if-cached"이면 네트워크 에러를 반환한다.

    2. forwardResponseHTTP-network fetchhttpFetchParams, includeCredentials, isNewConnectionFetch로 실행한 결과로 설정한다.

    3. httpRequestmethodunsafe이고 forwardResponsestatus가 200~399 범위면, httpCache에서 적절한 저장된 response를 무효화한다. 자세한 내용은 HTTP 캐싱의 "저장된 응답 무효화" 챕터 참고. [HTTP-CACHING] storedResponse를 null로 설정한다.

    4. revalidatingFlag가 설정되어 있고 forwardResponsestatus가 304이면:

      1. storedResponseheader listforwardResponseheader list로 갱신한다. 자세한 내용은 HTTP 캐싱의 "검증 시 저장된 응답 신선화" 챕터 참고. [HTTP-CACHING]

        이 단계는 캐시에 저장된 응답도 갱신한다.

      2. responsestoredResponse로 설정한다.

      3. responsecache state를 "validated"로 설정한다.

    5. response가 null이면:

      1. responseforwardResponse로 설정한다.

      2. httpRequestforwardResponsehttpCache에 저장한다. 자세한 내용은 HTTP 캐싱의 "캐시에 응답 저장" 챕터 참고. [HTTP-CACHING]

        forwardResponse네트워크 에러이면, 이는 네거티브 캐싱(네트워크 에러 캐싱)이다.

        관련 body info도 캐시에 함께 저장된다.

  11. responseURL listhttpRequestURL list복제본으로 설정한다.

  12. httpRequestheader list가 `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이면 네트워크 에러를 반환한다.

      2. requestbodybody로, safely extractingrequestbodysource로 실행한 결과로 설정한다.

    3. requestuse-URL-credentials flag가 unset이거나 isAuthenticationFetch가 true이면:

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

      2. usernamepassword를 최종 사용자에게 각각 요청하여 입력받고, requesttraversable for user prompts에서 입력한다.

      3. username 설정requestcurrent URLusername으로 실행한다.

      4. password 설정requestcurrent URLpassword로 실행한다.

    4. responseHTTP-네트워크-또는-캐시 가져오기fetchParams와 true로 실행한 결과로 설정한다.

  15. responsestatus가 407이면:

    1. requesttraversable for user prompts가 "no-traversable"이면 네트워크 에러를 반환한다.

    2. 테스트 필요: 다중 `Proxy-Authenticate` 헤더, 누락, 파싱 이슈.

    3. fetchParams취소됨이면 fetchParams에 대한 적절한 네트워크 에러를 반환한다.

    4. 최종 사용자에게 requesttraversable for user prompts에서 적절히 프롬프트하고, 결과를 proxy-authentication entry로 저장한다. [HTTP]

      프록시 인증 관련 세부 사항은 HTTP에서 정의된다.

    5. responseHTTP-네트워크-또는-캐시 가져오기fetchParams로 실행한 결과로 설정한다.

  16. 아래 모두 true이면:

    • responsestatus가 421임

    • isNewConnectionFetch가 false임

    • requestbody가 null이거나, requestbody가 null이 아니고, requestbodysource가 null이 아님

    이 경우:

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

    2. responseHTTP-네트워크-또는-캐시 가져오기fetchParams, isAuthenticationFetch, true로 실행한 결과로 설정한다.

  17. isAuthenticationFetch가 true이면 authentication entryrequest와 주어진 realm에 대해 생성한다.

  18. response를 반환한다. 일반적으로 responsebodystream은 반환 후에도 enqueue되고 있을 수 있다.

4.6. HTTP-네트워크 가져오기

HTTP-네트워크 가져오기를 실행하려면, fetch params fetchParams, 선택적 불리언 includeCredentials(기본값 false), 선택적 불리언 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이 실패면 네트워크 에러를 반환한다.

    2. timingInfofinal connection timing infoclamp and coarsen connection timing infoconnectiontiming info, timingInfopost-redirect start time, fetchParamscross-origin isolated capability로 실행한 결과로 설정한다.

    3. connection이 HTTP/1.x 연결이고, requestbody가 null이 아니며, requestbodysource가 null이면 네트워크 에러를 반환한다.

    4. timingInfofinal network-request start timecoarsened shared current time으로, fetchParamscross-origin isolated capability를 인자로 설정한다.
    5. responseconnection을 통해 request를 사용해 HTTP 요청을 수행한 결과로 설정하며, 다음 사항에 유의한다:

      Fetch와 HTTP 계층화는 더 정리되어야 하며, responseresponse와 HTTP 응답을 모두 나타낸다.

      HTTP 요청이 TLS 클라이언트 인증서 대화 상자를 발생시키면:

      1. requesttraversable for user promptstraversable navigable이면, 해당 대화 상자를 requesttraversable for user prompts에서 보여준다.

      2. 그 외에는 네트워크 에러를 반환한다.

      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이 아니면, process request body chunk lengthbyteslength로 실행한다.

        2. processEndOfBody를 다음 단계로 설정한다:

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

          2. fetchParamsprocess request end-of-body가 null이 아니면, process request end-of-body를 실행한다.

        3. processBodyErrore를 받아 다음 단계로 설정한다:

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

          2. e가 "AbortError" DOMException이면, abort fetchParamscontroller를 실행한다.

          3. 그 외에는 terminate fetchParamscontroller를 실행한다.

        4. body 점진적 읽기requestbody, processBodyChunk, processEndOfBody, processBodyError, fetchParamstask destination으로 실행한다.

  8. aborted이면:

    1. connection이 HTTP/2를 사용하면 RST_STREAM 프레임을 전송한다.

    2. fetchParams에 대한 적절한 네트워크 에러를 반환한다.

  9. buffer를 빈 바이트 시퀀스로 둔다.

    이 버퍼는 사용자 에이전트의 네트워크 계층 내 내부 버퍼를 나타낸다.

  10. streamnew ReadableStream으로 둔다.

  11. pullAlgorithm을 다음 단계로 설정한다:

    1. promise새 Promise로 둔다.

    2. 아래 단계를 병렬로 실행한다:

      1. buffer의 크기가 사용자 에이전트가 선택한 하한 미만이고, fetch가 일시 중단됨이면 재개한다.

      2. buffer가 비어있지 않을 때까지 대기한다.

      3. fetch task 큐에 넣기를 실행하여 아래 단계를 fetchParamstask destination과 함께 실행한다.

        1. Pull from bytesbufferstream으로 실행한다.

        2. streamerrored면, terminate fetchParamscontroller를 실행한다.

        3. resolve promise를 undefined로 실행한다.

    3. promise를 반환한다.

  12. cancelAlgorithmabort fetchParamscontrollerreason으로 실행하는 알고리즘으로 설정한다.

  13. byte reading 지원으로 stream 설정을 실행하여, pullAlgorithmpullAlgorithm으로, cancelAlgorithmcancelAlgorithm으로 설정한다.

  14. responsebodybody의 새 인스턴스로 설정하고, streamstream으로 둔다.

  15. (This is a tracking vector.) includeCredentials가 true면, 사용자 에이전트는 응답 `Set-Cookie` 헤더 파싱 및 저장requestresponse로 실행해야 한다.

  16. 아래 단계를 병렬로 실행한다:

    1. 아래 단계를 abort when fetchParams취소됨이면 중단한다:

      1. 다음이 true인 동안:

        1. response의 메시지 body에서 1바이트 이상 전송되면:

          1. bytes를 전송된 바이트로 둔다.

          2. codingsextracting header list values를 `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 sizebyteslength만큼 증가시킨다.

          9. bytes콘텐츠 코딩 처리codingsbytes로 실행한 결과로 설정한다.

            이 단계로 `Content-Length` 헤더의 신뢰도가 보장되지 않는다.

          10. responsebody infodecoded sizebyteslength만큼 증가시킨다.

          11. bytes가 실패면 terminate fetchParamscontroller를 실행한다.

          12. bytesbuffer에 append한다.

          13. buffer 크기가 사용자 에이전트가 선택한 상한 초과면 fetch를 일시 중단하도록 요청한다.

        2. 그 외에 response의 메시지 body 바이트 전송이 정상적으로 끝났고, streamreadable이면, close stream을 실행하고, 병렬 단계를 중단한다.

    2. aborted이면:

      1. fetchParamsaborted이면:

        1. responseaborted flag를 설정한다.

        2. streamreadable이면, error streamdeserialize a serialized abort reasonfetchParamscontrollerserialized abort reason과 구현 정의 realm을 인자로 실행한 결과로 error한다.

      2. 그 외에 streamreadable이면, error streamTypeError로 실행한다.

      3. connection이 HTTP/2를 사용하면 RST_STREAM 프레임을 전송한다.

      4. 그 외에는 사용자 에이전트는 성능에 악영향이 없다면 connection을 닫아야 한다.

        예를 들어, 재사용 가능한 연결에서 남은 바이트가 적은 경우, 연결을 닫고 다음 fetch를 위해 핸드셰이크를 다시 하는 것보다 열어두는 것이 더 나을 수 있다.

    이 단계들은 병렬로 실행되며, 이 시점에서 responsebody가 관련 있는지(예: 리다이렉트) 불분명하다.

  17. response를 반환한다. 일반적으로 responsebodystream은 반환 후에도 enqueue되고 있을 수 있다.

4.7. CORS-프리플라이트 가져오기

이 단계는 CORS 프로토콜이 이해되는지 확인하는 사용자 에이전트 구현이다. 이른바 CORS-프리플라이트 요청이다. 성공하면 CORS-프리플라이트 캐시를 채워 fetch 횟수를 최소화한다.

CORS-프리플라이트 가져오기를 실행하려면, request 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-네트워크-또는-캐시 가져오기를 사용하며, HTTP 가져오기를 사용하지 않는다.

  2. append (`Accept`, `*/*`)를 preflightheader list에 추가한다.

  3. append (`Access-Control-Request-Method`, requestmethod)를 preflightheader list에 추가한다.

  4. headersCORS-비안전 요청 헤더 이름으로, requestheader list로 구한다.

  5. headers비어있지 않으면:

    1. valueheaders의 각 항목을 `,`로 연결한 문자열로 둔다.

    2. append (`Access-Control-Request-Headers`, value)를 preflightheader list에 추가한다.

    이 단계는 combine을 사용하지 않는다. 즉, 0x2C 뒤에 0x20을 추가하지 않는다. 이는 구현상의 이유 때문이다.

  6. responseHTTP-네트워크-또는-캐시 가져오기를 새 fetch params로 실행한 결과로 둔다. 이 때 requestpreflight이다.

  7. CORS 검사requestresponse에 대해 실행하여 성공하고, responsestatusok status이면:

    CORS 검사preflight가 아니라 request에 대해 실행한다. 올바른 credentials mode 사용을 보장하기 위해서다.

    1. methodsextracting header list values를 `Access-Control-Allow-Methods` 와 responseheader list로 실행한 결과로 둔다.

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

    3. methodsheaderNames가 실패면 네트워크 에러를 반환한다.

    4. methods가 null이고 requestuse-CORS-preflight flag가 설정되어 있으면, methodsrequestmethod만 포함하는 새 리스트로 설정한다.

      이는 requestuse-CORS-preflight flag 때문에 발생한 CORS-프리플라이트 가져오기캐시에 저장되도록 한다.

    5. requestmethodmethods에 없고, requestmethodCORS-safelisted method가 아니며, requestcredentials mode가 "include"이거나, methods에 `*`가 없으면 네트워크 에러를 반환한다.

    6. requestheader listname 중 하나가 CORS non-wildcard request-header name이고, headerNames바이트 대소문자 구분 없이 일치하는 항목이 없으면 네트워크 에러를 반환한다.

    7. unsafeName에 대해, CORS-비안전 요청 헤더 이름requestheader list와 함께 구하고, unsafeNameheaderNames바이트 대소문자 구분 없이 일치하지 않고, requestcredentials mode가 "include"이거나, headerNames에 `*`가 없으면 네트워크 에러를 반환한다.

    8. max-ageextracting header list values를 `Access-Control-Max-Age` 와 responseheader list로 실행한 결과로 둔다.

    9. max-age가 실패 또는 null이면 max-age를 5로 설정한다.

    10. max-agemax-age 제한을 초과하면, max-age를 제한값으로 설정한다.

    11. 사용자 에이전트가 캐시를 제공하지 않으면 response를 반환한다.

    12. methods의 각 method에 대해, method cache entry matchrequest를 사용해 존재하면 해당 엔트리의 max-agemax-age로 설정한다.

    13. methods의 각 method에 대해, method cache entry matchrequest를 사용해 없다면, 캐시 엔트리 생성request, max-age, method, null로 실행한다.

    14. headerNames의 각 headerName에 대해, header-name cache entry matchrequest를 사용해 존재하면 해당 엔트리의 max-agemax-age로 설정한다.

    15. headerNames의 각 headerName에 대해, header-name cache entry matchrequest를 사용해 없다면, 캐시 엔트리 생성request, max-age, null, headerName으로 실행한다.

    16. response를 반환한다.

  8. 그 외의 경우 네트워크 에러를 반환한다.

4.8. CORS-프리플라이트 캐시

사용자 에이전트는 CORS-프리플라이트 캐시를 가진다. CORS-프리플라이트 캐시리스트이며, 캐시 엔트리로 구성된다.

캐시 엔트리는 다음으로 구성된다:

캐시 엔트리max-age 필드에 지정된 초가 저장 이후 경과하면 삭제되어야 한다. 캐시 엔트리는 그 이전에 삭제될 수도 있다.

새 캐시 엔트리 생성을 실행하려면 request, max-age, method, headerName을 받아 다음 단계를 실행한다:

  1. entry캐시 엔트리로 생성하고, 다음으로 초기화한다:

    네트워크 파티션 키 결정request로 실행한 결과

    바이트 직렬화된 오리진

    요청 오리진 바이트 직렬화request에 대해 실행한 결과

    URL

    requestcurrent URL

    max-age

    max-age

    자격 증명

    requestcredentials mode가 "include"이면 true, 아니면 false

    메서드

    method

    헤더 이름

    headerName

  2. Append entry를 사용자 에이전트의 CORS-프리플라이트 캐시에 추가한다.

캐시 엔트리 삭제를 실행하려면 request를 받아, remove 사용자 에이전트의 CORS-프리플라이트 캐시에서 다음 조건을 모두 만족하는 캐시 엔트리들을 삭제한다: 네트워크 파티션 키 결정request로 실행한 결과와 같고, 바이트 직렬화된 오리진요청 오리진 바이트 직렬화request로 실행한 결과와 같으며, URLrequestcurrent URL과 같다.

캐시 엔트리 일치캐시 엔트리 entryrequest에 대해 entry네트워크 파티션 키 결정request로 실행한 결과와 같고, entry바이트 직렬화된 오리진요청 오리진 바이트 직렬화request로 실행한 결과와 같고, entryURLrequestcurrent URL과 같으며, 아래 중 하나가 true일 때를 말한다:

위 조건이 true이면 캐시 엔트리 일치이다.

메서드 캐시 엔트리 일치methodrequest에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시캐시 엔트리가 있고, 캐시 엔트리 일치이며, 그 메서드method 또는 `*`인 경우를 뜻한다.

헤더 이름 캐시 엔트리 일치headerNamerequest에 대해, 사용자 에이전트의 CORS-프리플라이트 캐시캐시 엔트리가 있고, 캐시 엔트리 일치이며, 아래 중 하나가 true일 때를 말한다:

위 조건이 true이면 헤더 이름 캐시 엔트리 일치이다.

4.9. CORS 검사

CORS 검사를 실행하려면 requestresponse를 받아 다음 단계를 실행한다:

  1. originget `Access-Control-Allow-Origin` 을 responseheader list로 실행한 결과로 둔다.

  2. origin이 null이면 실패를 반환한다.

    null은 `null`과 다르다.

  3. requestcredentials mode가 "include"가 아니고, origin이 `*`이면 성공을 반환한다.

  4. 요청 오리진 바이트 직렬화request로 실행한 결과가 origin과 다르면 실패를 반환한다.

  5. requestcredentials mode가 "include"가 아니면 성공을 반환한다.

  6. credentialsget `Access-Control-Allow-Credentials` 을 responseheader list로 실행한 결과로 둔다.

  7. credentials가 `true`이면 성공을 반환한다.

  8. 실패를 반환한다.

4.10. TAO 검사

TAO 검사를 실행하려면 requestresponse를 받아 다음 단계를 실행한다:

  1. Assert: requestorigin이 "client"가 아님

  2. requesttiming allow failed flag가 설정되어 있으면 실패를 반환한다.

  3. valuesgetting, decoding, and splitting을 `Timing-Allow-Origin`과 responseheader list로 실행한 결과로 둔다.

  4. values에 "*"가 있으면 성공을 반환한다.

  5. values요청 오리진 직렬화request로 실행한 결과가 있으면 성공을 반환한다.

  6. requestmode가 "navigate"이고, requestcurrent URLoriginrequestoriginsame origin이 아니면 실패를 반환한다.

    이 단계는 중첩 네비게이션의 탐색에 필요하다. 여기서 requestorigin은 컨테이너 문서의 origin이 되고, TAO 검사는 실패를 반환한다. 네비게이션 타이밍은 TAO 검사 결과를 검증하지 않으므로, 중첩 문서는 전체 타이밍 정보를 볼 수 있지만 컨테이너 문서는 볼 수 없다.

  7. requestresponse tainting이 "basic"이면 성공을 반환한다.

  8. 실패를 반환한다.

4.11. 지연 fetch

지연 fetch는 호출자가 fetch를 가능한 가장 늦은 시점에 실행하도록 요청할 수 있게 해주며, 즉 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 객체이고, 연관된 문서가 "hidden" visibility state를 오랜 시간 가졌을 때)

    2. 지연 fetch 처리deferredRecord로 실행한다.

  7. deferredRecord를 반환한다.

총 요청 길이 계산을 실행하려면 request request를 받아:

  1. totalRequestLengthrequestURLserialize하고, exclude fragment를 true로 한 후 길이로 둔다.

  2. totalRequestLengthrequestreferrerserialize한 길이만큼 증가시킨다.

  3. (name, value)에 대해, requestheader list에서, totalRequestLengthname길이 + value길이만큼 증가시킨다.

  4. totalRequestLengthrequestbody길이만큼 증가시킨다.

  5. totalRequestLength를 반환한다.

지연 fetch들 처리을 실행하려면 fetch 그룹 fetchGroup을 받아:

  1. deferred fetch record deferredRecordfetchGroupdeferred fetch records에서 지연 fetch 처리deferredRecord로 실행한다.

지연 fetch 처리를 실행하려면 deferredRecord를 받아:

  1. deferredRecordinvoke state가 "pending"이 아니면 return한다.

  2. deferredRecordinvoke state를 "sent"으로 설정한다.

  3. FetchdeferredRecordrequest로 실행한다.

  4. 글로벌 태스크 큐에 넣기지연 fetch 태스크 소스에, deferredRecordrequestclientglobal object와 함께, deferredRecordnotify invoked를 실행한다.

4.11.1. 지연 fetch 할당량

이 절은 비규범적입니다.

지연 fetch 할당량은 최상위 traversable("탭")에 640키비바이트가 할당됩니다. 최상위 문서와 동일 출처의 직접 중첩 문서는 이 할당량을 사용해 지연 fetch를 큐에 넣을 수 있으며, 일부를 교차 출처 중첩 문서에 권한 정책을 통해 위임할 수도 있습니다.

기본적으로, 이 640키비바이트 중 128키비바이트가 교차 출처 중첩 문서에 할당하도록 예약되며, 각 중첩 문서는 8키비바이트를 예약합니다.

최상위 문서와 그 중첩 문서는 권한 정책을 통해 교차 출처 하위 문서에 얼마를 위임할지 제어할 수 있습니다. 기본적으로 "deferred-fetch-minimal" 정책은 모든 오리진에 대해 활성화되어 있고, "deferred-fetch"는 최상위 문서의 오리진에만 활성화되어 있습니다. 특정 오리진과 중첩 문서에 대해 "deferred-fetch" 정책을 완화하면 해당 중첩 문서에 64키비바이트를 할당할 수 있습니다. 반대로 "deferred-fetch-minimal" 정책을 특정 오리진이나 중첩 문서에 대해 제한하면, 문서가 기본적으로 받을 8키비바이트 할당을 막을 수 있습니다. 최상위 문서 자체에 대해 "deferred-fetch-minimal" 정책을 비활성화하면, 전체 128키비바이트 위임 할당량이 640키비바이트의 메인 풀로 다시 합쳐집니다.

문서에 할당된 할당량 중, 동일 보고 오리진(즉, requestURLorigin)에 대해 동시 사용 가능한 최대 용량은 64키비바이트입니다. 이는 특정 서드파티 라이브러리가 데이터를 보내기 전에 기회주의적으로 할당량을 예약하는 상황을 방지합니다.

아래의 fetchLater() 호출은 요청 자체가 한 보고 오리진에 할당된 64키비바이트 할당량을 초과하므로 예외가 발생합니다. 요청의 크기에는 URLbody, header list, referrer가 모두 포함됩니다.

fetchLater(a_72_kb_url);
fetchLater("https://origin.example.com", {headers: headers_exceeding_64kb});
fetchLater(a_32_kb_url, {headers: headers_exceeding_32kb});
fetchLater("https://origin.example.com", {method: "POST", body: body_exceeding_64_kb});
fetchLater(a_62_kb_url /* with a 3kb referrer */);

다음 시퀀스에서 처음 두 요청은 성공하지만, 세 번째는 예외가 발생합니다. 처음 두 번은 전체 640키비바이트 할당량을 초과하지 않지만, 세 번째 요청은 https://a.example.com에 대한 보고 오리진 할당량을 초과하기 때문에 예외가 발생합니다.

fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});
fetchLater("https://a.example.com");

동일 출처 중첩 문서는 부모의 할당량을 공유합니다. 하지만 교차 출처 또는 교차 agent iframe은 기본적으로 8kb만 할당받습니다. 따라서 아래 예에서 처음 세 번 호출은 성공하고, 마지막은 예외가 발생합니다.

// In main page
fetchLater("https://a.example.com", {method: "POST", body: a_64kb_body});

// In same-origin nested document
fetchLater("https://b.example.com", {method: "POST", body: a_64kb_body});

// In cross-origin nested document at https://fratop.example.com
fetchLater("https://a.example.com", {body: a_5kb_body});
fetchLater("https://a.example.com", {body: a_12kb_body});

이전 예에서 예외가 발생하지 않게 하려면, 최상위 문서가 https://fratop.example.com에 일부 할당량을 위임할 수 있습니다. 예를 들어 다음 헤더를 제공하면 됩니다:

Permissions-Policy: deferred-fetch=(self "https://fratop.example.com")

각 중첩 문서는 자체 할당량을 예약합니다. 따라서 다음 예는 각 프레임이 8키비바이트를 예약하므로 정상적으로 동작합니다:

// In cross-origin nested document at https://fratop.example.com/frame-1
fetchLater("https://a.example.com", {body: a_6kb_body});

// In cross-origin nested document at https://fratop.example.com/frame-2
fetchLater("https://a.example.com", {body: a_6kb_body});

아래 트리는 트리 내 다른 중첩 문서에 할당량이 어떻게 분배되는지 보여줍니다:

위 예에서, 최상위 traversable동일 출처 자손들은 384키비바이트 할당량을 공유합니다. 그 값 계산은 다음과 같습니다:

이 명세는 "deferred-fetch" 문자열로 식별되는 정책 제어 기능을 정의합니다. 그 기본 허용 리스트는 "self"입니다.

이 명세는 "deferred-fetch-minimal" 문자열로 식별되는 정책 제어 기능을 정의합니다. 그 기본 허용 리스트는 "*"입니다.

deferred-fetch-minimal에 예약된 할당량은 128키비바이트입니다.

navigable container예약된 지연 fetch 할당량을 갖습니다. 가능한 값은 최소 할당량(8키비바이트)과 일반 할당량(0 또는 64키비바이트)입니다. 별다른 언급이 없으면 0입니다.

사용 가능 지연 fetch 할당량을 얻으려면, document documentorigin-또는-null origin을 받아:

  1. controlDocumentdocument지연 fetch 제어 문서로 둔다.

  2. navigablecontrolDocumentnode navigable로 둔다.

  3. isTopLevelcontrolDocumentnode navigable최상위 traversable이면 true, 아니면 false로 둔다.

  4. deferredFetchAllowedcontrolDocument사용 허가됨이고, 정책 제어 기능 "deferred-fetch"도 허가됨이면 true, 아니면 false.

  5. deferredFetchMinimalAllowedcontrolDocument사용 허가됨이고, 정책 제어 기능 "deferred-fetch-minimal"도 허가됨이면 true, 아니면 false.

  6. quota를 다음과 같이 결정된 첫 번째 일치 조건의 결과로 둔다:

    isTopLevel이 true이고 deferredFetchAllowed가 false임
    0
    isTopLevel이 true이고 deferredFetchMinimalAllowed가 false임

    640키비바이트

    640kb면 누구에게나 충분한 용량입니다.

    isTopLevel이 true임

    512키비바이트

    기본값 640키비바이트에서 deferred-fetch-minimal에 예약된 할당량 만큼 차감됨

    deferredFetchAllowed가 true이고, navigablenavigable container예약된 지연 fetch 할당량일반 할당량이면
    일반 할당량
    deferredFetchMinimalAllowed가 true이고, navigablenavigable container예약된 지연 fetch 할당량최소 할당량이면
    최소 할당량
    그 외의 경우
    0
  7. quotaForRequestOrigin을 64키비바이트로 둔다.

  8. navigable에 대해, controlDocumentnode navigable포함 자손 navigable들active document지연 fetch 제어 문서controlDocument인 것만 대상으로:

    1. container에 대해, navigableactive documentshadow-including inclusive descendantsnavigable container인 것: quotacontainer예약된 지연 fetch 할당량만큼 차감한다.

    2. 지연 fetch 레코드 deferredRecord에 대해, navigableactive document관련 설정 객체fetch groupdeferred fetch records에 대해:

      1. requestLength총 요청 길이deferredRecordrequest로 실행한 결과로 둔다.

      2. quotarequestLength만큼 차감한다.

      3. 만약 deferredRecordrequestURLoriginorigin동일 출처이면, quotaForRequestOriginrequestLength만큼 차감한다.

  9. quota가 0 이하이면 0을 반환한다.

  10. quotaquotaForRequestOrigin보다 작으면 quota를 반환한다.

  11. quotaForRequestOrigin을 반환한다.

지연 fetch 할당량 예약을 실행하려면, navigable container containerorigin originToNavigateTo를 받아:

이 알고리즘은 탐색 시, 탐색의 소스 문서가 navigable의 부모 문서일 때 호출된다. 권한 정책에 따라 컨테이너 및 그 navigable에 대해 64kb 또는 8kb의 할당량을 잠재적으로 예약한다. 실제로 예약된 할당량이 사용됐는지는 컨테이너 문서에서 관찰할 수 없다. 이 알고리즘은 컨테이너의 문서가 탐색된 컨테이너에 할당량을 위임할 수 있고, 예약된 할당량은 그 경우에만 적용되며, 공유될 경우 무시됨을 가정한다. 할당량이 예약되었고 문서가 결국 부모와 동일 출처가 되면, 할당량은 해제된다.

  1. container예약된 지연 fetch 할당량을 0으로 설정한다.

  2. controlDocumentcontainernode document지연 fetch 제어 문서로 둔다.

  3. "deferred-fetch"에 대한 상속된 정책containeroriginToNavigateTo에 대해 "Enabled"이고, 사용 가능 지연 fetch 할당량controlDocument에 대해 일반 할당량 이상이면, container예약된 지연 fetch 할당량일반 할당량으로 설정하고 반환한다.

  4. 아래 조건이 모두 true이면:

    이 경우 container예약된 지연 fetch 할당량최소 할당량으로 설정한다.

지연 fetch 할당량 해제 가능을 실행하려면, document document를 받아, documentnode navigablecontainer document가 null이 아니고, 그 origindocument동일 출처이면, documentnode navigablenavigable container예약된 지연 fetch 할당량을 0으로 설정한다.

이 알고리즘은 문서가 생성될 때 호출된다. 동일 출처 중첩 문서는 어차피 부모의 할당량을 공유하므로 할당량을 예약하지 않도록 한다. 이는 문서 생성 시에만 호출될 수 있는데, origin은 리다이렉트가 처리된 후에만 알 수 있기 때문이다.

지연 fetch 제어 문서를 얻으려면, document document를 받아:

  1. documentnode navigablecontainer document가 null이거나, 문서origindocument동일 출처가 아니면, document를 반환한다. 그 외에는, 지연 fetch 제어 문서documentnode navigablecontainer document로 실행한 결과를 반환한다.

5. Fetch API

fetch() 메서드는 리소스 가져오기를 위한 비교적 저수준의 API입니다. XMLHttpRequest보다 약간 더 넓은 영역을 다루지만, 현재는 요청 진행 상황(응답 진행 상황 아님)에 있어 부족한 부분이 있습니다.

fetch() 메서드를 사용하면 리소스를 가져오고 그 내용을 Blob으로 추출하는 것이 매우 간단합니다:

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => res.blob()).then(playBlob)

특정 응답 헤더만 로그로 남기고 싶다면:

fetch("/", {method:"HEAD"})
  .then(res => log(res.headers.get("strict-transport-security")))

교차 출처 리소스의 특정 응답 헤더를 확인한 뒤 응답을 처리하려면:

fetch("https://pk.example/berlin-calling.json", {mode:"cors"})
  .then(res => {
    if(res.headers.get("content-type") &&
       res.headers.get("content-type").toLowerCase().indexOf("application/json") >= 0) {
      return res.json()
    } else {
      throw new TypeError()
    }
  }).then(processJSON)

URL 쿼리 파라미터를 다루고 싶다면:

var url = new URL("https://geo.example.org/api"),
    params = {lat:35.696233, long:139.570431}
Object.keys(params).forEach(key => url.searchParams.append(key, params[key]))
fetch(url).then(/* … */)

바디 데이터를 점진적으로 받고 싶다면:

function consume(reader) {
  var total = 0
  return pump()
  function pump() {
    return reader.read().then(({done, value}) => {
      if (done) {
        return
      }
      total += value.byteLength
      log(`received ${value.byteLength} bytes (${total} bytes in total)`)
      return pump()
    })
  }
}

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => consume(res.body.getReader()))
  .then(() => log("전체 바디를 메모리에 보존하지 않고 모두 소비함!"))
  .catch(e => log("문제가 발생함: " + e))

5.1. Headers 클래스

typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;

[Exposed=(Window,Worker)]
interface Headers {
  constructor(optional HeadersInit init);

  undefined append(ByteString name, ByteString value);
  undefined delete(ByteString name);
  ByteString? get(ByteString name);
  sequence<ByteString> getSetCookie();
  boolean has(ByteString name);
  undefined set(ByteString name, ByteString value);
  iterable<ByteString, ByteString>;
};

Headers 객체는 헤더 리스트(헤더 리스트)를 가지며, 처음에는 비어 있습니다. 이 리스트는 다른 객체의 헤더 리스트를 가리키는 포인터일 수 있습니다. 예를 들어 Request 객체처럼.

Headers 객체는 guard도 가지며, 이는 헤더 guard입니다. 헤더 guard는 "immutable", "request", "request-no-cors", "response", "none" 중 하나입니다.


headers = new Headers([init])

Headers 객체를 생성합니다. init을 사용해 내부 헤더 리스트를 채울 수 있습니다. 아래 예시 참고.

const meta = { "Content-Type": "text/xml", "Breaking-Bad": "<3" };
new Headers(meta);

// 위 예시는 다음과 동일합니다
const meta2 = [
  [ "Content-Type", "text/xml" ],
  [ "Breaking-Bad", "<3" ]
];
new Headers(meta2);
headers . append(name, value)

headers에 헤더를 추가합니다.

headers . delete(name)

headers에서 헤더를 제거합니다.

headers . get(name)

name인 모든 헤더 값들을 문자열로 반환하며, 값들은 콤마와 공백으로 구분됩니다.

headers . getSetCookie()

이름이 `Set-Cookie`인 모든 헤더 값을 리스트로 반환합니다.

headers . has(name)

name인 헤더가 존재하는지 여부를 반환합니다.

headers . set(name, value)

이름이 name인 첫 번째 헤더 값을 value로 대체하고, 동일한 이름의 남은 헤더는 모두 제거합니다.

for(const [name, value] of headers)

headers를 반복(iterate)할 수 있습니다.


유효성 검사header (name, value)에 대해 Headers 객체 headers로 실행하려면:

  1. name헤더 이름이 아니거나 value헤더 값이 아니면, TypeError를 던진다.

  2. headersguard가 "immutable"이면 TypeError를 던진다.

  3. headersguard가 "request"이고, (name, value)가 금지된 요청 헤더면 false를 반환한다.

  4. headersguard가 "response"이고, name금지된 응답 헤더 이름이면 false를 반환한다.

  5. true를 반환한다.

"request-no-cors"의 단계는 공유되지 않습니다. delete()에서 항상 성공하는 가짜 값(CORS 안전 목록 요청 헤더에 대해)이 있을 수 없기 때문입니다.

추가header (name, value)에 대해 Headers 객체 headers에 실행하려면:

  1. value 정규화value에 실행한다.

  2. 유효성 검사 (name, value)를 headers에 대해 실행한 결과가 false면 return한다.

  3. headersguard가 "request-no-cors"이면:

    1. temporaryValueget nameheaders헤더 리스트로 실행한 결과로 둔다.

    2. temporaryValue가 null이면 temporaryValuevalue로 설정한다.

    3. 그 외에는 temporaryValue에 0x2C 0x20을 이어 붙이고, value를 이어 붙인다.

    4. (name, temporaryValue)가 no-CORS 안전 목록 요청 헤더가 아니면 return 한다.

  4. append (name, value)를 headers헤더 리스트에 추가한다.

  5. headersguard가 "request-no-cors"이면 권한 없는 no-CORS 요청 헤더 제거headers에 실행한다.

채우기Headers 객체 headers와 객체 object로 실행하려면:

  1. objectsequence이면, header에 대해 object에서:

    1. header크기가 2가 아니면, TypeError를 던진다.

    2. append (header[0], header[1])를 headers에 실행한다.

  2. 그 외에 objectrecord이면, keyvalue에 대해 object에서, append (key, value)를 headers에 실행한다.

권한 없는 no-CORS 요청 헤더 제거Headers 객체 (headers)에 실행하려면:

  1. headerName에 대해 권한 있는 no-CORS 요청 헤더 이름들에서:

    1. Delete headerNameheaders헤더 리스트에서 삭제한다.

이 단계는 권한 없는 코드가 헤더를 수정할 때 호출된다.

new Headers(init) 생성자 단계:

  1. thisguard를 "none"으로 설정한다.

  2. init이 주어지면, 채우기thisinit으로 실행한다.

append(name, value) 메서드 단계는 추가 (name, value)를 this에 실행한다.

delete(name) 메서드 단계:

  1. 유효성 검사 (name, ``)를 this에 실행한 결과가 false면 return한다.

    임의의 헤더 값을 전달해도 부작용이 없어야 한다.

  2. thisguard가 "request-no-cors"이고, nameno-CORS 안전 목록 요청 헤더 이름이 아니고, name권한 있는 no-CORS 요청 헤더 이름이 아니면 return한다.

  3. this헤더 리스트name이 없으면 return한다.

  4. Delete namethis헤더 리스트에서 삭제한다.

  5. thisguard가 "request-no-cors"이면 권한 없는 no-CORS 요청 헤더 제거this에 실행한다.

get(name) 메서드 단계:

  1. name헤더 이름이 아니면 TypeError를 던진다.

  2. get namethis헤더 리스트로 실행한 결과를 반환한다.

getSetCookie() 메서드 단계:

  1. this헤더 리스트에 `Set-Cookie`가 없으면 « »를 반환한다.

  2. 들을 반환한다. 헤더this헤더 리스트에서 이름이 `Set-Cookie`와 바이트 대소문자 구분 없이 일치하는 모든 헤더의 값을 순서대로 반환한다.

has(name) 메서드 단계:

  1. name헤더 이름이 아니면 TypeError를 던진다.

  2. this헤더 리스트name이 있으면 true, 아니면 false를 반환한다.

set(name, value) 메서드 단계:

  1. value 정규화value에 실행한다.

  2. 유효성 검사 (name, value)를 this에 실행한 결과가 false면 return한다.

  3. thisguard가 "request-no-cors"이고, (name, value)가 no-CORS 안전 목록 요청 헤더가 아니면 return한다.

  4. set (name, value)를 this헤더 리스트에 실행한다.

  5. thisguard가 "request-no-cors"이면 권한 없는 no-CORS 요청 헤더 제거this에 실행한다.

반복할 값 쌍정렬 및 결합this헤더 리스트에 실행한 결과이다.

5.2. BodyInit 유니언

typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) XMLHttpRequestBodyInit;

typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit;

안전 추출타입이 지정된 body바이트 시퀀스 또는 BodyInit 객체 object에서 추출하려면 다음 단계를 수행한다:

  1. objectReadableStream 객체라면:

    1. Assert: object흔들림(disturbed)도 아니고 locked도 아니다.

  2. 추출object에 실행한 결과를 반환한다.

안전 추출 동작은 예외를 던지지 않는 추출의 부분집합이다.

추출타입이 지정된 body바이트 시퀀스 또는 BodyInit 객체 object에서, 선택적 불리언 keepalive(기본값 false)로 실행하려면 다음 단계를 수행한다:

  1. stream을 null로 둔다.

  2. objectReadableStream 객체라면 streamobject로 설정한다.

  3. 그 외에 objectBlob 객체라면, streamobjectget stream 실행 결과로 설정한다.

  4. 그 외에는 stream ReadableStream 객체로 두고, 바이트 읽기 지원으로 set upstream에 실행한다.

  5. Assert: streamReadableStream 객체다.

  6. action을 null로 둔다.

  7. source를 null로 둔다.

  8. length를 null로 둔다.

  9. type을 null로 둔다.

  10. object 타입에 따라 다음을 실행한다:

    Blob

    sourceobject로 설정한다.

    lengthobjectsize로 설정한다.

    objecttype 속성이 빈 바이트 시퀀스가 아니면, type을 해당 값으로 설정한다.

    바이트 시퀀스

    sourceobject로 설정한다.

    BufferSource

    sourceobject가 가진 바이트의 복사본으로 설정한다.

    FormData

    action을 다음 단계로 설정: multipart/form-data 인코딩 알고리즘objectentry listUTF-8로 실행.

    sourceobject로 설정한다.

    length불명확, 개선은 html/6424 참고로 설정한다.

    type을 `multipart/form-data; boundary=` + multipart/form-data 경계 문자열로 설정한다.

    URLSearchParams

    sourceapplication/x-www-form-urlencoded serializerobjectlist에 실행한 결과로 설정한다.

    type을 `application/x-www-form-urlencoded;charset=UTF-8`으로 설정한다.

    스칼라 값 문자열

    sourceUTF-8 인코딩object에 실행한 결과로 설정한다.

    type을 `text/plain;charset=UTF-8`로 설정한다.

    ReadableStream

    keepalive가 true면 TypeError를 던진다.

    object흔들림(disturbed)이나 locked이면 TypeError를 던진다.

  11. source바이트 시퀀스라면, actionsource를 반환하는 단계로 설정하고, lengthsource길이로 둔다.

  12. action이 null이 아니면, 아래 단계를 병렬로 실행한다:

    1. action을 실행한다.

      바이트가 하나 이상 사용 가능하고 streamerrored가 아니면, enqueue를, Uint8Array 생성을 사용하여 사용 가능한 바이트를 stream에 추가한다.

      action 실행이 끝나면, closestream에 실행한다.

  13. bodybody의 새 인스턴스로 두고, streamstream, sourcesource, lengthlength로 설정한다.

  14. (body, type)을 반환한다.

5.3. Body 믹스인

interface mixin Body {
  readonly attribute ReadableStream? body;
  readonly attribute boolean bodyUsed;
  [NewObject] Promise<ArrayBuffer> arrayBuffer();
  [NewObject] Promise<Blob> blob();
  [NewObject] Promise<Uint8Array> bytes();
  [NewObject] Promise<FormData> formData();
  [NewObject] Promise<any> json();
  [NewObject] Promise<USVString> text();
};

네트워크 계층에 의존하면 안 되는 포맷(예: HTML)은 여기서 노출하지 않습니다. 대신 HTML 파서 API가 스트림을 받도록 설계될 수 있습니다.

Body 인터페이스 믹스인을 포함한 객체는 body (null 또는 body)를 가진다.

Body 인터페이스 믹스인을 포함한 객체는 사용 불가로 간주되는데, body가 null이 아니고, bodystreamdisturbed 또는 locked인 경우를 말한다.


requestOrResponse . body

requestOrResponse의 body를 ReadableStream으로 반환합니다.

requestOrResponse . bodyUsed

requestOrResponse의 body가 읽혔는지 여부를 반환합니다.

requestOrResponse . arrayBuffer()

requestOrResponse의 body를 ArrayBuffer로 반환하는 promise를 반환합니다.

requestOrResponse . blob()

requestOrResponse의 body를 Blob으로 반환하는 promise를 반환합니다.

requestOrResponse . bytes()

requestOrResponse의 body를 Uint8Array로 반환하는 promise를 반환합니다.

requestOrResponse . formData()

requestOrResponse의 body를 FormData로 반환하는 promise를 반환합니다.

requestOrResponse . json()

requestOrResponse의 body를 JSON으로 파싱해 반환하는 promise를 반환합니다.

requestOrResponse . text()

requestOrResponse의 body를 문자열로 반환하는 promise를 반환합니다.


MIME 타입 얻기Request 또는 Response 객체 requestOrResponse를 받아 다음을 수행한다:

  1. headers를 null로 둔다.

  2. requestOrResponseRequest이면, headersrequestOrResponserequest헤더 리스트로 설정한다.

  3. 그 외에는 headersrequestOrResponseresponse헤더 리스트로 설정한다.

  4. mimeTypeMIME 타입 추출headers로 실행한 결과로 두는다.

  5. mimeType이 실패이면 null을 반환한다.

  6. mimeType을 반환한다.

body getter 단계는 thisbody가 null이면 null을 반환하고, 아니면 thisbodystream을 반환한다.

bodyUsed getter 단계는 thisbody가 null이 아니고, thisbodystreamdisturbed면 true를, 아니면 false를 반환한다.

body 소비 알고리즘은 Body 믹스인을 포함한 객체 object와, 바이트 시퀀스를 받아 JS 값이나 예외를 반환하는 알고리즘 convertBytesToJSValue를 받아 다음을 수행한다:

  1. object사용 불가면, TypeError로 reject된 promise를 반환한다.

  2. promise새 promise로 둔다.

  3. errorStepserror를 받아 promise를 reject하는 단계로 둔다.
  4. successSteps바이트 시퀀스 data를 받아, promise를 resolve하는 단계로 둔다. convertBytesToJSValuedata에 실행해 예외가 발생하면 errorSteps를 실행한다.
  5. objectbody가 null이면, successSteps를 빈 바이트 시퀀스로 실행한다.

  6. 그 외에는 완전히 읽기objectbody, successSteps, errorSteps, object관련 글로벌 객체로 실행한다.

  7. promise를 반환한다.

arrayBuffer() 메서드 단계는, body 소비this와 다음 단계로 실행한 결과를 반환한다. 바이트 시퀀스 bytes를 받아 ArrayBuffer 생성bytes에, this관련 realm에서 실행한다.

위 메서드는 RangeError로 reject될 수 있습니다.

blob() 메서드 단계는, body 소비this와 다음 단계로 실행한 결과를 반환한다. 바이트 시퀀스 bytes를 받아 Blob 객체를 생성하며, 내용은 bytes이고, type 속성은 MIME 타입 얻기this에 실행한 결과로 설정한다.

bytes() 메서드 단계는, body 소비this와 다음 단계로 실행한 결과를 반환한다. 바이트 시퀀스 bytes를 받아 Uint8Array 생성bytes에, this관련 realm에서 실행한다.

위 메서드는 RangeError로 reject될 수 있습니다.

formData() 메서드 단계는, body 소비this와 아래 단계를 실행한 결과를 반환한다. 바이트 시퀀스 bytes를 받아:

  1. mimeTypeMIME 타입 얻기this에 실행한 결과로 둔다.

  2. mimeType이 null이 아니면, mimeTypeessence에 따라 다음을 실행한다:

    "multipart/form-data"
    1. bytes를 `boundary` 파라미터 값으로 파싱한다. 규칙은 Returning Values from Forms: multipart/form-data를 따른다. [RFC7578]

      `Content-Disposition` 헤더에 `filename` 파라미터가 있으면, 해당 부분을 entry로 파싱하며, 값은 File 객체이고, 내용은 해당 부분 내용이다. name 속성은 `filename` 파라미터 값으로, type 속성은 해당 부분의 `Content-Type` 헤더 값, 없으면 `text/plain`로 한다([RFC7578] 4.4 절).

      `Content-Disposition` 헤더에 `filename` 파라미터가 없으면, 해당 부분을 entry로 파싱하며, 값은 해당 부분 내용을 UTF-8로 BOM 없이 디코딩한 문자열이다. `Content-Type` 헤더나 `charset` 파라미터가 있든 없든 무관하게 처리한다.

      `Content-Disposition` 헤더에 `name`이 `_charset_`이면 다른 부분과 동일하게 파싱하며, 인코딩은 변경하지 않는다.

    2. 실패하면 TypeError를 던진다.

    3. FormData 객체를 반환하며, 파싱 결과의 entry들로 entry list를 채운다.

    위 설명은 `multipart/form-data`에 대해 대략적이며, 더 상세한 파싱 명세가 필요합니다. 기여자 환영.

    "application/x-www-form-urlencoded"
    1. entries파싱bytes에 실행한 결과로 둔다.

    2. FormData 객체를 반환하며, entry listentries로 채운다.

  3. TypeError를 던진다.

json() 메서드 단계는, body 소비thisJSON 바이트를 파싱해 JS 값으로 변환으로 실행한 결과를 반환한다.

위 메서드는 SyntaxError로 reject될 수 있습니다.

text() 메서드 단계는, body 소비thisUTF-8 디코드로 실행한 결과를 반환한다.

5.4. Request 클래스

typedef (Request or USVString) RequestInfo;

[Exposed=(Window,Worker)]
interface Request {
  constructor(RequestInfo input, optional RequestInit init = {});

  readonly attribute ByteString method;
  readonly attribute USVString url;
  [SameObject] readonly attribute Headers headers;

  readonly attribute RequestDestination destination;
  readonly attribute USVString referrer;
  readonly attribute ReferrerPolicy referrerPolicy;
  readonly attribute RequestMode mode;
  readonly attribute RequestCredentials credentials;
  readonly attribute RequestCache cache;
  readonly attribute RequestRedirect redirect;
  readonly attribute DOMString integrity;
  readonly attribute boolean keepalive;
  readonly attribute boolean isReloadNavigation;
  readonly attribute boolean isHistoryNavigation;
  readonly attribute AbortSignal signal;
  readonly attribute RequestDuplex duplex;

  [NewObject] Request clone();
};
Request includes Body;

dictionary RequestInit {
  ByteString method;
  HeadersInit headers;
  BodyInit? body;
  USVString referrer;
  ReferrerPolicy referrerPolicy;
  RequestMode mode;
  RequestCredentials credentials;
  RequestCache cache;
  RequestRedirect redirect;
  DOMString integrity;
  boolean keepalive;
  AbortSignal? signal;
  RequestDuplex duplex;
  RequestPriority priority;
  any window; // can only be set to null
};

enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "frame", "iframe", "image", "json", "manifest", "object", "paintworklet", "report", "script", "sharedworker", "style",  "track", "video", "worker", "xslt" };
enum RequestMode { "navigate", "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
enum RequestDuplex { "half" };
enum RequestPriority { "high", "low", "auto" };

"serviceworker"는 RequestDestination에서 생략되며, JavaScript에서 관찰할 수 없기 때문이다. 구현체는 여전히 destination으로 지원해야 한다. "websocket"은 RequestMode에서 생략되며, JavaScript에서 사용할 수도, 관찰할 수도 없다.

Request 객체는 request(request 객체)을 가진다.

Request 객체는 또한 headers(null 또는 Headers 객체, 초기값은 null)을 가진다.

Request 객체는 signal(null 또는 AbortSignal 객체, 초기값은 null)을 가진다.

Request 객체의 bodyrequestbody이다.


request = new Request(input [, init])

request를 반환하며, url 속성은 input이 문자열이면 input이고, inputRequest 객체면 inputurl이다.

init 인자는 아래와 같이 속성을 설정할 수 있는 객체이다:

method
문자열로 requestmethod를 설정한다.
headers
Headers 객체, 객체 리터럴, 또는 2-항목 배열의 배열로 requestheaders를 설정한다.
body
BodyInit 객체 또는 null로 requestbody를 설정한다.
referrer
동일 출처 URL, "about:client", 또는 빈 문자열 값의 문자열로 requestreferrer를 설정한다.
referrerPolicy
referrer policyrequestreferrerPolicy를 설정한다.
mode
문자열로 요청이 CORS를 사용할지, 동일 출처 URL로 제한될지를 나타낸다. requestmode를 설정한다. input이 문자열이면 기본값은 "cors"이다.
credentials
문자열로 인증 정보가 항상, 절대, 또는 동일 출처 URL일 때만 요청과 함께 전송될지를 나타낸다. 응답에서 인증 정보를 사용할지도 결정한다. requestcredentials를 설정한다. input이 문자열이면 기본값은 "same-origin"이다.
cache
문자열로 요청이 브라우저 캐시와 어떻게 상호작용할지 나타내며, requestcache를 설정한다.
redirect
문자열로 request가 리다이렉트 시 어떻게 동작할지 나타내며, requestredirect를 설정한다.
integrity
request가 가져올 리소스의 암호학적 해시로, requestintegrity를 설정한다.
keepalive
불리언으로 requestkeepalive를 설정한다.
signal
AbortSignal 객체로 requestsignal을 설정한다.
window
null만 가능. request를 어떤 Window와도 연결하지 않도록 한다.
duplex
"half"만 유효하며, 반이중 fetch(즉, 사용자 에이전트가 요청 전체를 전송한 후 응답을 처리함)를 시작한다. "full"은 추후에 사용될 예약 값이며, 전이중 fetch(사용자 에이전트가 전체 요청을 보내기 전에 응답을 처리 가능)를 의미한다. bodyReadableStream 객체일 때 필요하다. "full" 정의는 issue #1254 참고.
priority
문자열로 requestpriority를 설정한다.
request . method
request의 HTTP 메서드를 반환하며, 기본값은 "GET"이다.
request . url
request의 URL을 문자열로 반환한다.
request . headers
request와 연결된 Headers 객체를 반환한다. 네트워크 계층에서 사용자 에이전트가 추가한 헤더(예: "Host")는 이 객체에 포함되지 않는다.
request . destination
request가 요청한 리소스 종류(예: "document" 또는 "script")를 반환한다.
request . referrer
request의 referrer를 반환한다. init에서 명시적으로 설정하면 동일 출처 URL이 될 수 있고, 빈 문자열이면 referrer가 없음을 의미하며, 기본값은 "about:client"이다. fetch 시 `Referer` 헤더 값을 결정할 때 사용된다.
request . referrerPolicy
request에 연결된 referrer policy를 반환한다. fetch 시 request의 referrer 값을 계산할 때 사용된다.
request . mode
request와 연결된 mode를 반환한다. 요청이 CORS를 사용할지, 동일 출처 URL에만 제한될지를 문자열로 나타낸다.
request . credentials
request와 연결된 credentials mode를 반환한다. 인증 정보가 항상, 절대, 또는 동일 출처 URL일 때만 요청과 함께 전송될지를 문자열로 나타낸다.
request . cache
request와 연결된 cache mode를 반환한다. 요청이 fetch 시 브라우저 캐시와 어떻게 상호작용할지를 문자열로 나타낸다.
request . redirect
request와 연결된 redirect mode를 반환한다. fetch 시 요청의 리다이렉트 처리 방식을 문자열로 나타내며, 기본적으로 request는 리다이렉트를 따름.
request . integrity
request가 fetch하는 리소스의 서브 리소스 무결성(Subresource Integrity) 메타데이터를 반환한다. 값은 공백으로 구분된 여러 해시로 구성된다. [SRI]
request . keepalive
request가 생성된 글로벌 객체보다 오래 살아남을 수 있는지 여부를 boolean으로 반환한다.
request . isReloadNavigation
request가 reload 네비게이션인지 여부를 boolean으로 반환한다.
request . isHistoryNavigation
request가 히스토리 네비게이션(뒤로/앞으로 네비게이션)인지 여부를 boolean으로 반환한다.
request . signal
request와 연결된 signal을 반환한다. AbortSignal 객체로, request가 abort됐는지, abort 이벤트 핸들러를 포함한다.
request . duplex
"half"를 반환하며, fetch가 반이중(사용자 에이전트가 전체 요청을 전송한 후 응답을 처리)임을 의미한다. 추후에 "full"도 반환할 수 있으며, fetch가 전이중(전체 요청을 보내기 전에 응답을 처리)임을 의미한다. "full" 정의는 issue #1254 참고.
request . clone()

request의 복제본을 반환한다.


생성을 실행하려면, Request 객체를 만들 때, request request, headers guard guard, AbortSignal 객체 signal, 그리고 realm realm을 받아 다음을 수행한다:

  1. requestObject새로운 Request 객체로 realm과 함께 생성한다.

  2. requestObjectrequestrequest로 설정한다.

  3. requestObjectheaders새로운 Headers 객체로 realm과 함께 생성하며, 헤더 리스트request헤더 리스트로, guardguard로 설정한다.

  4. requestObjectsignalsignal로 설정한다.

  5. requestObject를 반환한다.


new Request(input, init) 생성자 단계:

  1. request를 null로 둔다.

  2. fallbackMode를 null로 둔다.

  3. baseURLthis관련 설정 객체API 기본 URL로 둔다.

  4. signal을 null로 둔다.

  5. input이 문자열이면:

    1. parsedURL파싱inputbaseURL로 실행한 결과로 둔다.

    2. parsedURL이 실패이면 TypeError를 던진다.

    3. parsedURL인증 정보를 포함하면 TypeError를 던진다.

    4. requestrequest 새 객체로 생성하고 URLparsedURL로 설정한다.

    5. fallbackMode를 "cors"로 설정한다.

  6. 그 외에는:

    1. Assert: inputRequest 객체다.

    2. requestinputrequest로 설정한다.

    3. signalinputsignal로 설정한다.

  7. originthis관련 설정 객체origin으로 둔다.

  8. traversableForUserPrompts를 "client"로 둔다.

  9. request사용자 프롬프트용 traversable환경 설정 객체이고, 그 originorigin동일 출처면, traversableForUserPromptsrequest사용자 프롬프트용 traversable로 설정한다.

  10. init["window"]가 있고 null이 아니면, TypeError를 던진다.

  11. init["window"]가 있으면, traversableForUserPrompts를 "no-traversable"로 설정한다.

  12. request를 다음 속성으로 하는 request 새 객체로 둔다:

    URL
    requestURL.
    method
    requestmethod.
    header list
    requestheader list의 복사본.
    unsafe-request flag
    설정됨.
    client
    this관련 설정 객체.
    사용자 프롬프트용 traversable
    traversableForUserPrompts.
    internal priority
    requestinternal priority.
    origin
    requestorigin. 이 origin 전파는 서비스 워커가 탐색 요청을 처리할 때만 중요하다. 이 경우에는 요청의 origin이 현재 client와 달라질 수 있다.
    referrer
    requestreferrer.
    referrer policy
    requestreferrer policy.
    mode
    requestmode.
    credentials mode
    requestcredentials mode.
    cache mode
    requestcache mode.
    redirect mode
    requestredirect mode.
    integrity metadata
    requestintegrity metadata.
    keepalive
    requestkeepalive.
    reload-navigation flag
    requestreload-navigation flag.
    history-navigation flag
    requesthistory-navigation flag.
    URL list
    requestURL list복제본.
    initiator type
    "fetch".
  13. init비어있지 않으면:

    1. requestmode가 "navigate"이면 "same-origin"으로 설정한다.

    2. requestreload-navigation flag를 해제한다.

    3. requesthistory-navigation flag를 해제한다.

    4. requestorigin을 "client"로 설정한다.

    5. requestreferrer를 "client"로 설정한다.

    6. requestreferrer policy를 빈 문자열로 설정한다.

    7. requestURLrequestcurrent URL로 설정한다.

    8. requestURL list를 « requestURL »로 설정한다.

    서비스 워커가 요청을 "리다이렉트"할 때, 예를 들어 교차 출처 스타일시트의 이미지에서, 요청을 수정하면 더 이상 원본이 아닌(즉, 교차 출처 스타일시트가 아닌) 서비스 워커가 "리다이렉트"한 것처럼 보이도록 한다. 이는 원본이 동일한 종류의 요청을 생성하지 못할 수도 있기 때문에 필요하다. 원본을 신뢰하는 서비스가 있다면 이를 악용할 수 있지만, 현실적으로는 드문 일이다.

  14. init["referrer"]가 있으면:

    1. referrerinit["referrer"]로 둔다.

    2. referrer가 빈 문자열이면 requestreferrer를 "no-referrer"로 설정한다.

    3. 그 외에는:

      1. parsedReferrer파싱referrerbaseURL로 실행한 결과로 둔다.

      2. parsedReferrer가 실패이면 TypeError를 던진다.

      3. 다음 중 하나가 true면

        이면 requestreferrer를 "client"로 설정한다.

      4. 그 외에는 requestreferrerparsedReferrer로 설정한다.

  15. init["referrerPolicy"]가 있으면, requestreferrer policy를 그 값으로 설정한다.

  16. modeinit["mode"]가 있으면 그 값으로, 아니면 fallbackMode로 둔다.

  17. mode가 "navigate"이면 TypeError를 던진다.

  18. mode가 null이 아니면 requestmodemode로 설정한다.

  19. init["credentials"]가 있으면, requestcredentials mode를 그 값으로 설정한다.

  20. init["cache"]가 있으면, requestcache mode를 그 값으로 설정한다.

  21. requestcache mode가 "only-if-cached"이고, requestmode가 "same-origin"이 아니면, TypeError를 던진다.

  22. init["redirect"]가 있으면, requestredirect mode를 그 값으로 설정한다.

  23. init["integrity"]가 있으면, requestintegrity metadata를 그 값으로 설정한다.

  24. init["keepalive"]가 있으면, requestkeepalive를 그 값으로 설정한다.

  25. init["method"]가 있으면:

    1. methodinit["method"]로 둔다.

    2. methodmethod가 아니거나 method금지된 메서드이면 TypeError를 던진다.

    3. 정규화method에 실행한다.

    4. requestmethodmethod로 설정한다.

  26. init["signal"]가 있으면, signal을 그 값으로 설정한다.

  27. init["priority"]가 있으면:

    1. requestinternal priority가 null이 아니면, requestinternal priority구현 정의 방식으로 갱신한다.

    2. 그 외에는 requestpriorityinit["priority"]로 설정한다.

  28. thisrequestrequest로 설정한다.

  29. signalssignal이 null이 아니면 « signal »로, 아니면 « »로 둔다.

  30. thissignal종속 abort signal 생성signalsAbortSignal, this관련 realm으로 실행한 결과로 설정한다.

  31. thisheaders새로운 Headers 객체로, this관련 realm을 사용하고, 헤더 리스트requestheader list, guard는 "request"로 설정한다.

  32. thisrequestmode가 "no-cors"이면:

    1. thisrequestmethodCORS 안전 목록 메서드가 아니면 TypeError를 던진다.

    2. thisheadersguard를 "request-no-cors"로 설정한다.

  33. init비어있지 않으면:

    헤더가 이 모드에서 허용되지 않는 헤더가 있을 수 있으므로 정제(sanitized)된다. 그렇지 않으면 이전에 정제되었거나 권한 있는 API에서 설정된 이후 수정되지 않은 상태이다.

    1. headersthisheaders와 그 헤더 리스트의 복사본으로 둔다.

    2. init["headers"]가 있으면, headersinit["headers"]로 설정한다.

    3. thisheaders헤더 리스트를 비운다.

    4. headersHeaders 객체이면, header에 대해, 그 헤더 리스트에서, append headerthisheaders에 실행한다.

    5. 그 외에는 fillthisheadersheaders로 실행한다.

  34. inputBodyinputRequest 객체이면, inputrequestbody로, 아니면 null로 둔다.

  35. init["body"]가 있고 null이 아니거나 inputBody가 null이 아니고, requestmethod가 `GET` 또는 `HEAD`이면 TypeError를 던진다.

  36. initBody를 null로 둔다.

  37. init["body"]가 있고 null이 아니면:

    1. bodyWithType추출init["body"]에, keepaliverequestkeepalive로 설정해 실행한 결과로 둔다.

    2. initBodybodyWithTypebody로 설정한다.

    3. typebodyWithTypetype으로 둔다.

    4. type이 null이 아니고 thisheaders헤더 리스트에 `Content-Type`이 없으면, append (`Content-Type`, type)를 thisheaders에 실행한다.

  38. inputOrInitBodyinitBody가 null이 아니면 initBody로, 아니면 inputBody로 둔다.

  39. inputOrInitBody가 null이 아니고 그 source가 null이면:

    1. initBody가 null이 아니고 init["duplex"]가 없으면 TypeError를 던진다.

    2. thisrequestmode가 "same-origin" 또는 "cors"가 아니면 TypeError를 던진다.

    3. thisrequestuse-CORS-preflight flag를 설정한다.

  40. finalBodyinputOrInitBody로 둔다.

  41. initBody가 null이고 inputBody가 null이 아니면:

    1. input사용 불가TypeError를 던진다.

    2. finalBody프록시 생성inputBody로 실행한 결과로 설정한다.

  42. thisrequestbodyfinalBody로 설정한다.

method getter 단계는 thisrequestmethod를 반환한다.

url getter 단계는 thisrequestURLserialize하여 반환한다.

headers getter 단계는 thisheaders를 반환한다.

destination getter 단계는 thisrequestdestination을 반환한다.

referrer getter 단계:

  1. thisrequestreferrer가 "no-referrer"면 빈 문자열을 반환한다.

  2. thisrequestreferrer가 "client"면 "about:client"를 반환한다.

  3. thisrequestreferrerserialize하여 반환한다.

referrerPolicy getter 단계는 thisrequestreferrer policy를 반환한다.

mode getter 단계는 thisrequestmode를 반환한다.

credentials getter 단계는 thisrequestcredentials mode를 반환한다.

cache getter 단계는 thisrequestcache mode를 반환한다.

redirect getter 단계는 thisrequestredirect mode를 반환한다.

integrity getter 단계는 thisrequestintegrity metadata를 반환한다.

keepalive getter 단계는 thisrequestkeepalive를 반환한다.

isReloadNavigation getter 단계는 thisrequestreload-navigation flag가 설정되어 있으면 true, 아니면 false를 반환한다.

isHistoryNavigation getter 단계는 thisrequesthistory-navigation flag가 설정되어 있으면 true, 아니면 false를 반환한다.

signal getter 단계는 thissignal을 반환한다.

duplex getter 단계는 "half"를 반환한다.


clone() 메서드 단계:

  1. this사용 불가TypeError를 던진다.

  2. clonedRequestclonethisrequest로 실행한 결과로 둔다.

  3. Assert: thissignal은 null이 아니다.

  4. clonedSignal종속 abort signal 생성을 « thissignal », AbortSignal, this관련 realm으로 실행한 결과로 둔다.

  5. clonedRequestObject생성Request 객체, clonedRequest, thisheadersguard, clonedSignal, this관련 realm으로 실행한 결과로 둔다.

  6. clonedRequestObject를 반환한다.

5.5. Response 클래스

[Exposed=(Window,Worker)]interface Response {
  constructor(optional BodyInit? body = null, optional ResponseInit init = {});

  [NewObject] static Response error();
  [NewObject] static Response redirect(USVString url, optional unsigned short status = 302);
  [NewObject] static Response json(any data, optional ResponseInit init = {});

  readonly attribute ResponseType type;

  readonly attribute USVString url;
  readonly attribute boolean redirected;
  readonly attribute unsigned short status;
  readonly attribute boolean ok;
  readonly attribute ByteString statusText;
  [SameObject] readonly attribute Headers headers;

  [NewObject] Response clone();
};
Response includes Body;

dictionary ResponseInit {
  unsigned short status = 200;
  ByteString statusText = "";
  HeadersInit headers;
};

enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };

Response 객체는 response(response 객체)을 가진다.

Response 객체는 또한 headers(null 또는 Headers 객체, 초기값은 null)을 가진다.

Response 객체의 bodyresponsebody이다.


response = new Response(body = null [, init])

response의 body가 body이고, status, status message, headers는 init으로 설정된 Response를 생성한다.

response = Response . error()

네트워크 오류 Response를 생성한다.

response = Response . redirect(url, status = 302)

urlstatus 상태로 리다이렉트하는 Response를 생성한다.

response = Response . json(data [, init])

body가 JSON 인코딩된 data이고, status, status message, headers가 init으로 설정된 Response를 생성한다.

response . type

response의 타입을 반환한다(예: "cors").

response . url

response의 URL을 반환하며, 없으면 빈 문자열을 반환한다.

response . redirected

response가 리다이렉트를 통해 얻어졌는지 여부를 반환한다.

response . status

response의 status를 반환한다.

response . ok

response의 status가 ok status라면 true를 반환한다.

response . statusText

response의 status message를 반환한다.

response . headers

response의 headers를 Headers 객체로 반환한다.

response . clone()

response의 복제본을 반환한다.


생성을 실행하려면, Response 객체를 만들 때, response response, headers guard guard, realm realm을 받아 다음을 수행한다:

  1. responseObject새로운 Response 객체로 realm과 함께 생성한다.

  2. responseObjectresponseresponse로 설정한다.

  3. responseObjectheaders새로운 Headers 객체로 realm과 함께 생성하며, 헤더 리스트response헤더 리스트, guardguard로 설정한다.

  4. responseObject를 반환한다.

response 초기화를 실행하려면, Response 객체 response, ResponseInit init, null 또는 body with type body를 받아 다음을 수행한다:

  1. init["status"] 값이 200~599 범위에 없으면 RangeError를 던진다.

  2. init["statusText"] 값이 빈 문자열이 아니고 reason-phrase 토큰 생성식과 일치하지 않으면 TypeError를 던진다.

  3. responseresponsestatusinit["status"]로 설정한다.

  4. responseresponsestatus messageinit["statusText"]로 설정한다.

  5. init["headers"]가 있으면 fillresponseheadersinit["headers"]로 실행한다.

  6. body가 null이 아니면:

    1. responsestatusnull body status이면 TypeError를 던진다.

      101과 103은 null body status에 포함되지만 이 단계에 영향은 없다.

    2. responsebodybodybody로 설정한다.

    3. bodytype이 null이 아니고, response헤더 리스트에 `Content-Type`이 없으면, append (`Content-Type`, bodytype)를 response헤더 리스트에 추가한다.


new Response(body, init) 생성자 단계:

  1. thisresponse를 새로운 response로 설정한다.

  2. thisheaders새로운 Headers 객체로 this관련 realm을 사용하고, 헤더 리스트thisresponse헤더 리스트, guard는 "response"로 설정한다.

  3. bodyWithType을 null로 둔다.

  4. body가 null이 아니면 bodyWithType추출body로 실행한 결과로 둔다.

  5. response 초기화this, init, bodyWithType으로 실행한다.

정적 error() 메서드 단계는, 새로운 network error, "immutable", 현재 realm을 받아 생성을 실행한 Response 객체를 반환한다.

정적 redirect(url, status) 메서드 단계:

  1. parsedURL파싱url현재 settings 객체API 기본 URL로 실행한 결과로 둔다.

  2. parsedURL이 실패면 TypeError를 던진다.

  3. statusredirect status가 아니면 RangeError를 던진다.

  4. responseObject생성을 새로운 response, "immutable", 현재 realm으로 실행한 결과로 둔다.

  5. responseObjectresponsestatusstatus로 설정한다.

  6. valueparsedURLserialize하고 isomorphic encode한 결과로 둔다.

  7. append(`Location`, value)를 responseObjectresponse헤더 리스트에 추가한다.

  8. responseObject를 반환한다.

정적 json(data, init) 메서드 단계:

  1. bytesJavaScript 값을 JSON 바이트로 직렬화data에 실행한 결과로 둔다.

  2. body추출bytes로 실행한 결과로 둔다.

  3. responseObject생성을 새로운 response, "response", 현재 realm으로 실행한 결과로 둔다.

  4. response 초기화responseObject, init, (body, "application/json")로 실행한다.

  5. responseObject를 반환한다.

type getter 단계는 thisresponsetype을 반환한다.

url getter 단계는, thisresponseURL이 null이면 빈 문자열을, 아니면 thisresponseURLserialize(exclude fragment true)하여 반환한다.

redirected getter 단계는, thisresponseURL 리스트크기가 1보다 크면 true, 아니면 false를 반환한다.

리다이렉트 결과인 response를 필터링하려면 API에서 직접 수행한다. 예: fetch(url, { redirect:"error" }). 이렇게 하면 잠재적으로 안전하지 않은 response가 실수로 유출되지 않게 된다.

status getter 단계는 thisresponsestatus를 반환한다.

ok getter 단계는, thisresponsestatusok status라면 true, 아니면 false를 반환한다.

statusText getter 단계는, thisresponsestatus message를 반환한다.

headers getter 단계는, thisheaders를 반환한다.


clone() 메서드 단계:

  1. this사용 불가TypeError를 던진다.

  2. clonedResponseclonethisresponse로 실행한 결과로 둔다.

  3. 생성Response 객체, clonedResponse, thisheadersguard, this관련 realm으로 실행한 결과를 반환한다.

5.6. fetch 메서드

partial interface mixin WindowOrWorkerGlobalScope {
  [NewObject] Promise<Response> fetch(RequestInfo input, optional RequestInit init = {});
};

dictionary DeferredRequestInit : RequestInit {
  DOMHighResTimeStamp activateAfter;
};

[Exposed=Window]
interface FetchLaterResult {
  readonly attribute boolean activated;
};

partial interface Window {
  [NewObject] FetchLaterResult fetchLater(RequestInfo input, optional DeferredRequestInit init = {});
};

fetch(input, init) 메서드 단계:

  1. p새로운 promise로 둔다.

  2. requestObjectRequest 생성자를 input, init 인자로 호출한 결과로 둔다. 예외가 발생하면 p를 reject하고 p를 반환한다.

  3. requestrequestObjectrequest로 둔다.

  4. requestObjectsignalaborted면:

    1. fetch() 호출 중단p, request, null, requestObjectsignalabort reason으로 실행한다.

    2. p를 반환한다.

  5. globalObjectrequestclientglobal object로 둔다.
  6. globalObjectServiceWorkerGlobalScope 객체이면, requestservice-workers mode를 "none"으로 설정한다.
  7. responseObject를 null로 둔다.

  8. relevantRealmthis관련 realm으로 둔다.

  9. locallyAborted를 false로 둔다.

    동일 스레드에서 abort 요청이 올 때 promise를 예측 가능한 타이밍에 reject할 수 있게 한다.

  10. controller를 null로 둔다.

  11. 다음 abort 단계 추가requestObjectsignal에 대해 수행한다:

    1. locallyAborted를 true로 설정한다.

    2. Assert: controller는 null이 아니다.

    3. Abort controllerrequestObjectsignalabort reason으로 실행한다.

    4. fetch() 호출 중단p, request, responseObject, requestObjectsignalabort reason으로 실행한다.

  12. controllerfetchrequest, processResponseresponse에 대해 아래 단계로 호출한 결과로 둔다:

    1. locallyAborted가 true이면 이 단계 중단.

    2. responseaborted flag가 설정되어 있으면:

      1. deserializedErrorserialize된 abort reason 역직렬화controllerserialized abort reason, relevantRealm에 대해 실행한 결과로 둔다.

      2. fetch() 호출 중단p, request, responseObject, deserializedError로 실행한다.

      3. 이 단계 중단.

    3. responsenetwork error면, p를 reject하고 TypeError로 중단.

    4. responseObject생성Response 객체, response, "immutable", relevantRealm으로 실행한 결과로 둔다.

    5. p를 resolve한다(responseObject로).

  13. p를 반환한다.

fetch() 호출 중단 단계는 promise, request, responseObject, error를 받아:

  1. promise를 error로 reject한다.

    promise가 이미 fulfilled된 경우 아무 동작도 하지 않는다.

  2. requestbody가 null이 아니고 readable이면, body를 cancel한다(error로).

  3. responseObject가 null이면 반환.

  4. responseresponseObjectresponse로 둔다.

  5. responsebody가 null이 아니고 readable이면, body를 error로 error한다.

FetchLaterResult 객체는 activated getter 단계를 가지며, 이는 boolean을 반환하는 알고리즘이다.

activated getter 단계는 thisactivated getter 단계를 실행한 결과를 반환한다.

fetchLater(input, init) 메서드 단계:

  1. requestObjectRequest 생성자를 input, init 인자로 호출한 결과로 둔다.

  2. requestObjectsignalaborted면, signalabort reason을 throw한다.

  3. requestrequestObjectrequest로 둔다.

  4. activateAfter를 null로 둔다.

  5. init이 주어지고 init["activateAfter"]가 있으면, activateAfter를 그 값으로 설정한다.

  6. activateAfter가 0보다 작으면 RangeError를 throw한다.

  7. this관련 글로벌 객체연결된 document완전히 활성이 아니면, TypeError를 throw한다.

  8. requestURLschemeHTTP(S) scheme이 아니면 TypeError를 throw한다.

  9. requestURL신뢰할 수 있는 URL이 아니면 TypeError를 throw한다.

  10. requestbody가 null이 아니고, requestbodylength가 null이면 TypeError를 throw한다.

    body가 ReadableStream 객체인 요청은 지연할 수 없다.

  11. 사용 가능한 deferred-fetch quotarequestclient, requestURLorigin에 대해 requesttotal request length보다 작으면, "QuotaExceededError" DOMException을 throw한다.

  12. activated를 false로 둔다.

  13. deferredRecordqueue a deferred fetchrequest, activateAfter, 아래 단계(activated를 true로 설정함)로 실행한 결과로 둔다.

  14. 다음 abort 단계 추가requestObjectsignal에 대해 수행한다: deferredRecordinvoke state를 "aborted"로 설정한다.

  15. FetchLaterResult 객체를 반환하며, activated getter 단계는 activated를 반환한다.

다음 호출은 문서가 종료될 때 가져올 요청을 큐에 추가합니다:

fetchLater("https://report.example.com", {
  method: "POST",
  body: JSON.stringify(myReport),
  headers: { "Content-Type": "application/json" }
})

다음 호출은 5초 후에도 이 요청을 큐에 추가하며, 반환된 값으로 호출자가 실제로 활성화되었는지 관찰할 수 있습니다. 사용자 에이전트가 타이머를 제한하는 경우에도 요청은 반드시 호출됩니다.

const result = fetchLater("https://report.example.com", {
  method: "POST",
  body: JSON.stringify(myReport),
  headers: { "Content-Type": "application/json" },
  activateAfter: 5000
});

function check_if_fetched() {
  return result.activated;
}

FetchLaterResult 객체는 AbortSignal 과 함께 사용할 수 있습니다. 예시:

let accumulated_events = [];
let previous_result = null;
const abort_signal = new AbortSignal();
function accumulate_event(event) {
  if (previous_result) {
    if (previous_result.activated) {
      // 요청이 이미 활성화되었으므로, 새롭게 시작할 수 있습니다.
      accumulated_events = [];
    } else {
      // 이 요청을 중단하고, 모든 이벤트로 새로운 요청을 시작합니다.
      signal.abort();
    }
  }

  accumulated_events.push(event);
  result = fetchLater("https://report.example.com", {
    method: "POST",
    body: JSON.stringify(accumulated_events),
    headers: { "Content-Type": "application/json" },
    activateAfter: 5000,
    abort_signal
  });
}

다음 fetchLater() 호출은 모두 예외를 발생시킵니다:

// 오직 신뢰할 수 있는 URL만 지원됩니다.
fetchLater("http://untrusted.example.com");

// 지연된 요청의 길이는 반드시 미리 알아야 합니다.
fetchLater("https://origin.example.com", {body: someDynamicStream});

// 지연된 fetch는 활성 윈도우에서만 동작합니다.
const detachedWindow = iframe.contentWindow;
iframe.remove();
detachedWindow.fetchLater("https://origin.example.com");

지연 fetch 할당량 예시를 참고하면 지연 fetch 할당량이 어떻게 동작하는지 알 수 있습니다.

5.7. 가비지 컬렉션

사용자 에이전트는 종료가 스크립트로 관찰될 수 없는 경우 진행 중인 fetch를 종료할 수 있습니다.

"스크립트로 관찰 가능"하다는 것은 fetch()의 인자와 반환값을 통해 관찰할 수 있다는 의미입니다. 서버와의 사이드 채널 통신과 같은 다른 방식은 포함되지 않습니다.

서버가 가비지 컬렉션을 관찰할 수 있는 사례는 WebSocketXMLHttpRequest 객체에서 이미 존재합니다.

사용자 에이전트는 종료가 관찰될 수 없으므로 fetch를 종료할 수 있습니다.

fetch("https://www.example.com/")

사용자 에이전트는 종료가 promise를 통해 관찰될 수 있으므로 fetch를 종료할 수 없습니다.

window.promise = fetch("https://www.example.com/")

연관된 body가 관찰될 수 없으므로 사용자 에이전트가 fetch를 종료할 수 있습니다.

window.promise = fetch("https://www.example.com/").then(res => res.headers)

종료가 관찰될 수 없으므로 사용자 에이전트가 fetch를 종료할 수 있습니다.

fetch("https://www.example.com/").then(res => res.body.getReader().closed)

promise 객체에 핸들러를 등록하여 종료를 관찰할 수 있으므로 사용자 에이전트가 fetch를 종료할 수 없습니다.

window.promise = fetch("https://www.example.com/")
  .then(res => res.body.getReader().closed)

핸들러 등록을 통해 종료가 관찰될 수 있으므로 사용자 에이전트가 fetch를 종료할 수 없습니다.

fetch("https://www.example.com/")
  .then(res => {
    res.body.getReader().closed.then(() => console.log("stream closed!"))
  })

(위의 비관찰성 예시는 body.getReader() 등 내장 속성과 함수가 덮어써지지 않았다고 가정합니다.)

6. data: URL

data: URL에 대한 설명은 RFC 2397을 참고하세요. 이 섹션은 현행 표준에 맞게 배포된 콘텐츠와 호환되도록 RFC의 규범 처리 요구사항을 대체합니다. [RFC2397]

data: URL 구조체구조체이며, MIME 타입 (MIME 타입)과 본문(body) (바이트 시퀀스)로 이루어져 있습니다.

data: URL 프로세서URL dataURL을 받아 다음 단계들을 실행합니다:

  1. 단언(Assert): dataURLscheme이 "data"임을 확인합니다.

  2. inputURL serializerdataURL에 실행하고, exclude fragment를 true로 설정하여 얻은 결과로 합니다.

  3. input에서 앞의 "data:"를 제거합니다.

  4. positioninput의 시작 위치로 설정합니다.

  5. mimeType시퀀스 수집을 통해 U+002C(,)가 아닌 코드 포인트 시퀀스로 합니다.

  6. 앞뒤 ASCII 공백 제거mimeType에 적용합니다.

    이 작업은 U+0020 SPACE 코드 포인트만 제거합니다.

  7. positioninput의 끝을 지난 경우 실패를 반환합니다.

  8. position을 1만큼 이동합니다.

  9. encodedBodyinput의 나머지로 설정합니다.

  10. bodypercent-decodingencodedBody에 적용한 값으로 합니다.

  11. mimeType이 U+003B(;)로 끝나고, 0개 이상의 U+0020 SPACE 뒤에 ASCII 대소문자 구분 없이 "base64"가 있다면 다음을 수행합니다:

    1. stringBodyisomorphic decodebody에 적용한 값으로 합니다.

    2. bodyforgiving-base64 decodestringBody에 적용한 값으로 합니다.

    3. body가 실패라면 실패를 반환합니다.

    4. mimeType에서 마지막 6개의 코드 포인트를 제거합니다.

    5. mimeType에서 마지막의 U+0020 SPACE 코드 포인트를 제거합니다.

    6. mimeType에서 마지막 U+003B(;)를 제거합니다.

  12. mimeType이 ";"로 시작하면 "text/plain"을 mimeType 앞에 붙입니다.

  13. mimeTypeRecordMIME 타입 파싱mimeType에 적용한 값으로 합니다.

  14. mimeTypeRecord가 실패라면 text/plain;charset=US-ASCII로 설정합니다.

  15. 새로운 data: URL 구조체를 반환하며, MIME 타입mimeTypeRecord, 본문body로 설정합니다.

배경 읽기

이 섹션과 하위 섹션들은 참고용입니다.

HTTP 헤더 레이어 구분

fetch 관점에서 API 레이어(HTML의 img, CSS의 background-image), 초기 fetch 레이어, 서비스 워커 레이어, 네트워크 & 캐시 레이어가 있습니다. `Accept` 및 `Accept-Language`는 초기 fetch 레이어(일반적으로 사용자 에이전트에 의해)에서 설정됩니다. 대부분의 사용자 에이전트가 제어하는 다른 헤더들, 예를 들어 `Accept-Encoding`, `Host`, `Referer`는 네트워크 & 캐시 레이어에서 설정됩니다. 개발자는 API 레이어 또는 서비스 워커 레이어(일반적으로 Request 객체를 통해)에서 헤더를 설정할 수 있습니다. 개발자는 금지된 요청 헤더에 거의 접근할 수 없으나, `Accept`는 제어할 수 있고, `Referer`는 제한하거나 생략할 수 있는 수단이 있습니다.

원자적 HTTP 리다이렉트 처리

리다이렉트(응답상태 또는 내부 응답(있다면)의 상태리다이렉트 상태인 경우)는 API에 노출되지 않습니다. 리다이렉트를 노출하면 교차 사이트 스크립팅 공격을 통해서만 얻을 수 있는 정보를 노출할 수 있습니다.

https://example.org/auth로 fetch할 때 HttpOnly로 표시된 Cookie가 포함되면 https://other-origin.invalid/4af955781ea1c84a3b11로 리다이렉트될 수 있습니다. 이 새로운 URL에는 비밀이 포함되어 있습니다. 리다이렉트를 노출하면 해당 비밀이 교차 사이트 스크립팅 공격을 통해 얻어질 수 있습니다.

기본 안전 CORS 프로토콜 설정

IP 인증 또는 방화벽을 통해 데이터가 보호되는 리소스(아직도 꽤 흔함)의 경우 CORS 프로토콜을 사용하는 것은 안전하지 않습니다. (이 때문에 CORS 프로토콜이 만들어졌습니다.)

그러나, 다음 헤더를 사용하는 것은 안전합니다:

Access-Control-Allow-Origin: *

리소스가 추가 정보를 쿠키나 HTTP 인증에 따라 노출한다 해도, 위 헤더를 사용하면 그 정보를 노출하지 않습니다. API(XMLHttpRequest 등)와 마찬가지로 curl, wget에도 동일하게 공유됩니다.

즉, curl이나 wget으로 웹에 연결된 임의의 장치에서 리소스에 접근할 수 없다면 위 헤더를 포함하지 않아야 합니다. 그러나 접근 가능하다면 포함해도 괜찮습니다.

CORS 프로토콜과 HTTP 캐시

CORS 프로토콜 요구사항이 `Access-Control-Allow-Origin`을 * 또는 정적 origin으로 설정하는 것보다 더 복잡하다면, `Vary`를 사용해야 합니다. [HTML] [HTTP] [HTTP-CACHING]

Vary: Origin

특히, 서버가 특정 리소스에 대해 Access-Control-Allow-Origin을 CORS 요청에만 응답하도록 구성되고, `Vary`가 사용되지 않는다면을 고려해보세요. 사용자 에이전트가 해당 리소스에 대해 비-CORS 요청(예: navigation 요청의 결과)으로 응답을 받으면, 응답에 `Access-Control-Allow-Origin`이 없고 해당 응답을 캐시합니다. 이후 CORS 요청이 오면 해당 비-CORS 요청에서 캐시된 응답을 사용하고, `Access-Control-Allow-Origin`이 없습니다.

그러나 동일 시나리오에서 `Vary: Origin`을 사용하면 사용자 에이전트가 `Access-Control-Allow-Origin`이 포함된 응답을 fetch하게 되며, 비-CORS 요청에서 캐시된 응답(헤더 없음)은 사용하지 않습니다.

반면, 특정 리소스에 대해 `Access-Control-Allow-Origin`을 * 또는 정적 origin으로 설정했다면, 서버를 항상 해당 리소스 응답에 `Access-Control-Allow-Origin`을 포함하도록 구성하고 비-CORS 요청 및 CORS 요청 모두에 대해 보내야 하며, `Vary`는 사용하지 않아야 합니다.

웹소켓(WebSockets)

연결을 설정하는 과정에서 WebSocket 객체는 특수한 종류의 fetch를 시작합니다(`mode`가 "websocket"인 request를 사용). 이로 인해 많은 fetch 정책 결정(예: HTTP Strict Transport Security (HSTS))을 공유하게 됩니다. 궁극적으로 fetch는 WebSockets에 전용 연결을 얻기 위해 호출됩니다. [WEBSOCKETS] [HSTS]

Fetch는 이전에 WebSocket 연결 얻기WebSocket 연결 설정을 직접 정의했으나, 현재는 모두 WebSockets에서 정의됩니다. [WEBSOCKETS]

다른 표준에서 fetch 사용하기

본질적으로 fetchingrequestresponse의 교환입니다. 실제로 표준에서 올바르게 채택하고 사용하기에는 꽤 복잡한 메커니즘입니다. 이 섹션은 몇 가지 조언을 제공합니다.

반드시 도메인 전문가에게 검토를 받으세요.

작업 진행 중입니다.

요청 설정하기

fetching의 첫 번째 단계는 request를 생성하고, items를 채우는 것입니다.

HTTP에서 정의한 대로 requestURLmethod를 먼저 설정하세요. 만약 `POST` 또는 `PUT` request에 body가 필요한 경우, requestbodybyte sequence로 설정하거나, 직접 생성한 ReadableStreambodystream으로 설정할 수 있습니다. [HTTP]

requestdestinationdestination table 안내에 따라 선택하세요. DestinationsContent Security Policy에 영향을 주고, `Sec-Fetch-Dest` 헤더 등 다양한 의미를 갖습니다. 새로운 기능에 destination이 필요하지만 destination table에 없다면, 이슈를 등록해 논의해주세요. [CSP]

requestclient를 작업 중인 environment settings object로 설정하세요. 웹에 노출된 API는 일반적으로 Web IDL로 정의되며, 각 interface를 구현하는 객체마다 relevant settings object가 있습니다. 예를 들어, requestelement와 연관된 경우, requestclient를 해당 element의 node documentrelevant settings object로 설정합니다. JavaScript, HTML, CSS 또는 기타 Document 하위 리소스에 직접적으로 웹에 노출되는 모든 기능은 client가 있어야 합니다.

fetching이 직접적으로 웹에 노출되지 않는 경우, 예를 들어 현재 WindowWorker에 의존하지 않고 백그라운드에서 전송되는 경우, requestclient를 null로 두고, requestorigin, policy container, service-workers mode, referrer를 적절하게 설정하세요. 예를 들어 미리 environment settings object에서 복사하여 사용할 수 있습니다. 이런 고급 케이스에서는 Content Security Policyreferrer policy 처리를 반드시 명확히 해야 합니다. 또한 콜백이 fetch 호출 및 응답 처리에서 parallel queue에 게시되므로, 동시성도 처리해야 합니다. [REFERRER] [CSP]

크로스 오리진 리소스 처리 방식을 잘 고민하세요. 어떤 기능은 same origin에서만 동작해야 할 수 있으므로, requestmode를 "same-origin"으로 설정하세요. 그 외의 경우, 대부분의 새로운 웹 노출 기능은 mode를 "cors"로 설정해야 합니다. 만약 기능이 웹에 노출되지 않거나, CORS 없이 크로스 오리진 리소스를 fetch해야 할 다른 이유가 있다면, 이슈를 등록해 논의하세요.

크로스 오리진 요청의 경우, credentials 포함 여부도 결정하세요. 포함해야 한다면 requestcredentials mode를 "include"로 설정하세요.

fetch가 Resource Timing에 보고되어야 하는지, 어떤 initiator type으로 보고할지 결정하세요. initiator typerequest에 전달하면, fetch 완료 시 response가 전부 다운로드된 뒤 자동으로 Resource Timing에 보고됩니다. [RESOURCE-TIMING]

추가 HTTP 헤더가 필요하다면, header list를 원하는 헤더를 포함하는 header list로 설정하세요. 예: « (`My-Header-Name`, `My-Header-Value`) ». 커스텀 헤더를 보내면 CORS-preflight fetch가 필요할 수 있으므로 주의가 필요합니다.

기본 캐싱 메커니즘을 오버라이드하거나, 예를 들어 request에 대해 캐싱을 비활성화하고 싶다면, cache mode를 "default" 외의 값으로 설정하세요.

요청이 리다이렉트를 지원할지 여부도 결정하세요. 지원하지 않을 경우 redirect mode를 "error"로 설정하세요.

request의 나머지 파라미터들도 필요하다면 참고하세요. 이 파라미터들은 특수 목적에 더 자주 사용되며, 현행 표준의 § 2.2.5 Requests에서 자세히 설명되어 있습니다.

fetch 호출 및 응답 처리

request 외에도 fetch 연산은 몇 가지 선택적 인자를 받습니다. 알고리즘을 받는 인자에 대해서는: 해당 알고리즘은 태스크(또는 parallel queue에서 useParallelQueue가 true일 때)에서 호출됩니다.

request가 준비되면, fetch에 어떤 알고리즘을 전달할지 결정하려면, response를 어떻게 처리할지, 특히 어떤 단계에서 콜백을 받을지 결정하세요:

완료 시점에 처리

대부분의 호출자가 response를 이렇게 처리합니다. 예를 들어 스크립트스타일 리소스가 해당됩니다. responsebody를 전체 byte sequence로 읽은 뒤 호출자가 처리합니다.

response를 완료 시점에 처리하려면, fetchprocessResponseConsumeBody 인자에 알고리즘을 전달하세요. 전달된 알고리즘은 responsebody를 모두 읽은 결과(내부 responseinternal response)를 받게 됩니다. 두 번째 인자의 값 의미는 다음과 같습니다:

null
responsebody가 null인 경우로, network error가 발생했거나 null body status일 때입니다.
failure
responsebody 내용을 완전히 읽으려다 실패한 경우입니다. 예: I/O 오류 등.
byte sequence

responseinternal responsebody완전히 읽은 경우입니다.

전체 내용을 담은 byte sequencerequestmode가 "no-cors"일 때도 전달됩니다. 이런 콘텐츠는 요청한 origin에 노출되지 않아야 하므로, 처리할 때 주의해야 합니다. 예를 들어, "no-cors" response의 내용을 사용자에게 이미지로 직접 보여줄 수 있으나, 임베딩 문서의 스크립트에는 직접 노출해서는 안 됩니다.

  1. requestrequest로 두되, URLhttps://stuff.example.com/이고, clientthisrelevant settings object로 설정합니다.

  2. Fetch request를 호출하는데, processResponseConsumeBody를 아래 단계로 설정합니다. response response와 null, failure, 또는 byte sequence contents를 인자로 받습니다:

    1. contents가 null 또는 failure면 사용자에게 오류를 알립니다.

    2. 그 외에는 response의 메타데이터를 참고해 contents를 파싱하고, 필요한 작업을 수행합니다.

헤더 먼저, 그 다음 청크 단위

예를 들어 비디오 재생이나 이미지 점진적 로딩 등 일부 경우에는, 호출자가 응답을 스트리밍 처리하며 청크 단위로 처리하고 싶을 수 있습니다. response는 헤더가 처리된 뒤 fetch 호출자에게 전달되며, 그 뒤로 호출자가 직접 처리합니다.

response를 청크 단위로 처리하려면, fetchprocessResponse 인자에 알고리즘을 전달하세요. 전달된 알고리즘은 응답 헤더가 수신되면 response를 인자로 받고, responsebodystream을 직접 읽어 남은 응답을 다운로드해야 합니다. 편의를 위해 processResponseEndOfBody 인자에도 알고리즘을 전달할 수 있는데, 이는 응답 및 body를 모두 읽은 뒤 호출됩니다. processResponseConsumeBody와 달리, processResponse 또는 processResponseEndOfBody 인자를 전달해도 응답이 완전히 읽힌다는 보장은 없으므로, 호출자가 직접 읽어야 합니다.

processResponse 인자는 responseheader liststatus만 처리하고 body는 전혀 처리하지 않을 때 유용합니다. 예: ok status가 아닌 응답 처리 등.

  1. requestrequest로 두되, URLhttps://stream.example.com/이고, clientthisrelevant settings object로 설정합니다.

  2. Fetch request를 호출하는데, processResponse를 아래 단계로 설정합니다. response response를 인자로 받습니다:

    1. responsenetwork error면 사용자에게 오류를 알립니다.

    2. 그 외에 responsestatusok status가 아니면, 사용자에게 대체값을 제시합니다.

    3. 그 외에는 readerresponsebodystream에 대해 얻고, extracting a MIME type으로 확인한 MIME 타입에 따라 적절히 처리합니다.

응답 무시

어떤 경우에는 response 자체가 필요 없는 경우도 있습니다. 예: navigator.sendBeacon() 등. fetch에 콜백을 전달하는 것은 선택 사항이므로, 콜백을 생략하면 응답을 기대하지 않고 fetch가 동작합니다. 이런 경우 responsebodystream은 폐기되며, 호출자는 불필요하게 내용을 다운로드하는 것을 신경 쓸 필요가 없습니다.

Fetch request를 호출합니다. URLhttps://fire-and-forget.example.com/, method는 `POST`, clientthisrelevant settings object입니다.

응답 처리를 위한 콜백 외에도, fetch는 고급 케이스용 추가 콜백을 받습니다. processEarlyHintsResponseresponsestatus가 103일 때를 위한 것으로, 현재는 네비게이션만 처리됩니다. processRequestBodyChunkLengthprocessRequestEndOfBody는 요청 body 업로드 진행 상황을 호출자에게 알려줍니다.

fetch 연산은 호출된 동일 스레드에서 시작한 뒤 내부 작업을 병렬로 실행합니다. 위 콜백들은 기본적으로 이벤트 루프(기본값은 clientglobal object)에 게시됩니다. 응답을 병렬로 처리하고 메인 스레드와의 상호작용을 직접 처리하려면, fetch 호출 시 useParallelQueue를 true로 설정하세요.

진행 중인 fetch 조작하기

이미 시작된 fetch 연산을 조작하려면, fetch를 호출해 반환된 fetch controller를 사용하세요. 예를 들어, 사용자 또는 페이지 로직에 따라 fetch controllerabort하거나, 브라우저 내부 상황에 따라 terminate할 수 있습니다.

종료 및 중단 외에도, 호출자는 타이밍 보고를 할 수 있으며, initiator type을 전달해 자동으로 처리하지 않은 경우에만 해당합니다. 또는 전체 타이밍 정보 추출 후 호출자 측에서 처리할 수도 있습니다(이 기능은 네비게이션만 사용함). fetch controllerrequestredirect mode가 "manual"로 설정된 경우, 다음 수동 리다이렉트 처리에도 사용됩니다.

감사의 글

감사합니다: Adam Barth, Adam Lavin, Alan Jeffrey, Alexey Proskuryakov, Andreas Kling, Andrés Gutiérrez, Andrew Sutherland, Andrew Williams, Ángel González, Anssi Kostiainen, Arkadiusz Michalski, Arne Johannessen, Artem Skoretskiy, Arthur Barstow, Arthur Sonzogni, Asanka Herath, Axel Rauschmayer, Ben Kelly, Benjamin Gruenbaum, Benjamin Hawkes-Lewis, Benjamin VanderSloot, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Bryan Smith, Caitlin Potter, Cameron McCormack, Carlo Cannas, 白丞祐 (Cheng-You Bai), Chirag S Kumar, Chris Needham, Chris Rebert, Clement Pellerin, Collin Jackson, Daniel Robertson, Daniel Veditz, Dave Tapuska, David Benjamin, David Håsäther, David Orchard, Dean Jackson, Devdatta Akhawe, Domenic Denicola, Dominic Farolino, Dominique Hazaël-Massieux, Doug Turner, Douglas Creager, Eero Häkkinen, Ehsan Akhgari, Emily Stark, Eric Lawrence, Eric Orth, Feng Yu, François Marier, Frank Ellerman, Frederick Hirsch, Frederik Braun, Gary Blackwood, Gavin Carothers, Glenn Maynard, Graham Klyne, Gregory Terzian, Guohui Deng(邓国辉), Hal Lockhart, Hallvord R. M. Steen, Harris Hancock, Henri Sivonen, Henry Story, Hiroshige Hayashizaki, Honza Bambas, Ian Hickson, Ilya Grigorik, isonmad, Jake Archibald, James Graham, Jamie Mansfield, Janusz Majnert, Jeena Lee, Jeff Carpenter, Jeff Hodges, Jeffrey Yasskin, Jensen Chappell, Jeremy Roman, Jesse M. Heines, Jianjun Chen, Jinho Bang, Jochen Eisinger, John Wilander, Jonas Sicking, Jonathan Kingston, Jonathan Watt, 최종찬 (Jongchan Choi), Jordan Stephens, Jörn Zaefferer, Joseph Pecoraro, Josh Matthews, jub0bs, Julian Krispel-Samsel, Julian Reschke, 송정기 (Jungkee Song), Jussi Kalliokoski, Jxck, Kagami Sascha Rosylight, Keith Yeung, Kenji Baheux, Lachlan Hunt, Larry Masinter, Liam Brummitt, Linus Groh, Louis Ryan, Luca Casonato, Lucas Gonze, Łukasz Anforowicz, 呂康豪 (Kang-Hao Lu), Maciej Stachowiak, Malisa, Manfred Stock, Manish Goregaokar, Marc Silbey, Marcos Caceres, Marijn Kruisselbrink, Mark Nottingham, Mark S. Miller, Martin Dürst, Martin O’Neal, Martin Thomson, Matt Andrews, Matt Falkenhagen, Matt Menke, Matt Oshry, Matt Seddon, Matt Womer, Mhano Harkness, Michael Ficarra, Michael Kohler, Michael™ Smith, Mike Pennisi, Mike West, Mohamed Zergaoui, Mohammed Zubair Ahmed, Moritz Kneilmann, Ms2ger, Nico Schlömer, Nicolás Peña Moreno, Nidhi Jaju, Nikhil Marathe, Nikki Bee, Nikunj Mehta, Noam Rosenthal, Odin Hørthe Omdal, Olli Pettay, Ondřej Žára, O. Opsec, Patrick Meenan, Perry Jiang, Philip Jägenstedt, R. Auburn, Raphael Kubo da Costa, Robert Linder, Rondinelly, Rory Hewitt, Ross A. Baker, Ryan Sleevi, Sam Atkins, Samy Kamkar, Sébastien Cevey, Sendil Kumar N, Shao-xuan Kang, Sharath Udupa, Shivakumar Jagalur Matt, Shivani Sharma, Sigbjørn Finne, Simon Pieters, Simon Sapin, Simon Wülker, Srirama Chandra Sekhar Mogali, Stephan Paul, Steven Salat, Sunava Dutta, Surya Ismail, Tab Atkins-Bittner, Takashi Toyoshima, 吉野剛史 (Takeshi Yoshino), Thomas Roessler, Thomas Steiner, Thomas Wisniewski, Tiancheng "Timothy" Gu, Tobie Langel, Tom Schuster, Tomás Aparicio, triple-underscore, 保呂毅 (Tsuyoshi Horo), Tyler Close, Ujjwal Sharma, Vignesh Shanmugam, Vladimir Dzhuvinov, Wayne Carr, Xabier Rodríguez, Yehuda Katz, Yoav Weiss, Youenn Fablet, Yoichi Osato, 평野裕 (Yutaka Hirano), 그리고 Zhenbin Xu 모두에게 감사드립니다.

이 표준은 Anne van Kesteren (Apple, annevk@annevk.nl)가 작성했습니다.

지적 재산권

Copyright © WHATWG (Apple, Google, Mozilla, Microsoft). 이 문서는 크리에이티브 커먼즈 저작자표시 4.0 국제 라이선스로 제공됩니다. 일부가 소스 코드에 포함되는 경우, 해당 소스 코드 부분은 BSD 3-Clause License로 제공됩니다.

이 문서는 현행 표준입니다. 특허 검토 버전에 관심 있으신 분들은 현행 표준 검토 초안을 참조하세요.

색인

이 명세서에서 정의한 용어

참조로 정의된 용어

참고 문헌

규범 참고 문헌

[ABNF]
D. Crocker, Ed.; P. Overell. 구문 명세를 위한 확장 BNF(ABNF). 2008년 1월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc5234
[BEACON]
Ilya Grigorik; Alois Reitbauer. Beacon. URL: https://w3c.github.io/beacon/
[COOKIES]
Johann Hofmann; Anne van Kesteren. Cookies: HTTP 상태 관리 메커니즘. URL: https://httpwg.org/http-extensions/draft-ietf-httpbis-layered-cookies.html
[CSP]
Mike West; Antonio Sartori. 콘텐츠 보안 정책 레벨 3. URL: https://w3c.github.io/webappsec-csp/
[CSS-VALUES-4]
Tab Atkins Jr.; Elika Etemad. CSS 값 및 단위 모듈 레벨 4. URL: https://drafts.csswg.org/css-values-4/
[DOM]
Anne van Kesteren. DOM 표준. 현행 표준. URL: https://dom.spec.whatwg.org/
[ECMASCRIPT]
ECMAScript 언어 명세. URL: https://tc39.es/ecma262/multipage/
[ENCODING]
Anne van Kesteren. 인코딩 표준. 현행 표준. URL: https://encoding.spec.whatwg.org/
[FETCH-METADATA]
Mike West. Fetch 메타데이터 요청 헤더. URL: https://w3c.github.io/webappsec-fetch-metadata/
[FILEAPI]
Marijn Kruisselbrink. File API. URL: https://w3c.github.io/FileAPI/
[HR-TIME-3]
Yoav Weiss. 고해상도 시간. URL: https://w3c.github.io/hr-time/
[HSTS]
J. Hodges; C. Jackson; A. Barth. HTTP 엄격 전송 보안(HSTS). 2012년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6797
[HTML]
Anne van Kesteren; et al. HTML 표준. 현행 표준. URL: https://html.spec.whatwg.org/multipage/
[HTTP]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 의미론. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9110.html
[HTTP-CACHING]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP 캐싱. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9111.html
[HTTP1]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. HTTP/1.1. 2022년 6월. 인터넷 표준. URL: https://httpwg.org/specs/rfc9112.html
[HTTP3]
M. Bishop, Ed.. HTTP/3. 2022년 6월. 제안 표준. URL: https://httpwg.org/specs/rfc9114.html
[HTTP3-DATAGRAM]
D. Schinazi; L. Pardue. HTTP 데이터그램 및 캡슐 프로토콜. 2022년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9297
[IANA-HTTP-PARAMS]
하이퍼텍스트 전송 프로토콜(HTTP) 파라미터. URL: https://www.iana.org/assignments/http-parameters/http-parameters.xhtml
[INFRA]
Anne van Kesteren; Domenic Denicola. Infra 표준. 현행 표준. URL: https://infra.spec.whatwg.org/
[MIMESNIFF]
Gordon P. Hemsley. MIME Sniffing 표준. 현행 표준. URL: https://mimesniff.spec.whatwg.org/
[MIX]
Emily Stark; Mike West; Carlos IbarraLopez. 혼합 콘텐츠. URL: https://w3c.github.io/webappsec-mixed-content/
[PERMISSIONS-POLICY-1]
Ian Clelland. Permissions Policy. URL: https://w3c.github.io/webappsec-permissions-policy/
[REFERRER]
Jochen Eisinger; Emily Stark. Referrer Policy. URL: https://w3c.github.io/webappsec-referrer-policy/
[REPORTING]
Douglas Creager; Ian Clelland; Mike West. Reporting API. URL: https://w3c.github.io/reporting/
[RESOURCE-TIMING]
Yoav Weiss; Noam Rosenthal. Resource Timing. URL: https://w3c.github.io/resource-timing/
[RFC7405]
P. Kyzivat. ABNF에서 대소문자 구분 문자열 지원. 2014년 12월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7405
[RFC7578]
L. Masinter. 폼에서 값 반환: multipart/form-data. 2015년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7578
[RFC9218]
K. Oku; L. Pardue. HTTP를 위한 확장 우선순위 지정 체계. 2022년 6월. 제안 표준. URL: https://httpwg.org/specs/rfc9218.html
[RFC9651]
M. Nottingham; P-H. Kamp. HTTP를 위한 구조화 필드 값. 2024년 9월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9651
[SECURE-CONTEXTS]
Mike West. 보안 컨텍스트. URL: https://w3c.github.io/webappsec-secure-contexts/
[SRI]
Devdatta Akhawe; et al. 하위 리소스 무결성. URL: https://w3c.github.io/webappsec-subresource-integrity/
[SRI-2]
Frederik Braun. 하위 리소스 무결성. URL: https://w3c.github.io/webappsec-subresource-integrity/
[STALE-WHILE-REVALIDATE]
M. Nottingham. Stale 컨텐츠를 위한 HTTP Cache-Control 확장. 2010년 5월. 정보성. URL: https://httpwg.org/specs/rfc5861.html
[STREAMS]
Adam Rice; et al. Streams 표준. 현행 표준. URL: https://streams.spec.whatwg.org/
[SVCB]
B. Schwartz; M. Bishop; E. Nygren. DNS를 통한 서비스 바인딩 및 파라미터 명세(SVCB 및 HTTPS 레코드). 2023년 11월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc9460
[SW]
Yoshisato Yanagisawa; Monica CHINTALA. 서비스 워커. URL: https://w3c.github.io/ServiceWorker/
[TLS]
E. Rescorla. 전송 계층 보안(TLS) 프로토콜 버전 1.3. 2018년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc8446
[UPGRADE-INSECURE-REQUESTS]
Mike West. Upgrade Insecure Requests. URL: https://w3c.github.io/webappsec-upgrade-insecure-requests/
[URL]
Anne van Kesteren. URL 표준. 현행 표준. URL: https://url.spec.whatwg.org/
[WEBIDL]
Edgar Chen; Timothy Gu. Web IDL 표준. 현행 표준. URL: https://webidl.spec.whatwg.org/
[WEBSOCKETS]
Adam Rice. WebSockets 표준. 현행 표준. URL: https://websockets.spec.whatwg.org/
[WEBTRANSPORT-HTTP3]
V. Vasiliev. HTTP/3 기반 WebTransport. URL: https://datatracker.ietf.org/doc/html/draft-ietf-webtrans-http3
[XHR]
Anne van Kesteren. XMLHttpRequest 표준. 현행 표준. URL: https://xhr.spec.whatwg.org/

정보 참고 문헌

[HTTPVERBSEC1]
여러 벤더의 웹 서버가 기본적으로 HTTP TRACE 메서드를 활성화함.. URL: https://www.kb.cert.org/vuls/id/867593
[HTTPVERBSEC2]
Microsoft Internet Information Server (IIS)가 HTTP TRACK 메서드를 통해 교차 사이트 스크립팅에 취약함.. URL: https://www.kb.cert.org/vuls/id/288308
[HTTPVERBSEC3]
HTTP 프록시 기본 설정이 임의 TCP 연결을 허용함.. URL: https://www.kb.cert.org/vuls/id/150227
[NAVIGATION-TIMING]
Zhiheng Wang. Navigation Timing. 2012년 12월 17일. REC. URL: https://www.w3.org/TR/navigation-timing/
[ORIGIN]
A. Barth. 웹 오리진 개념. 2011년 12월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6454
[RFC1035]
P. Mockapetris. 도메인 이름 - 구현 및 명세. 1987년 11월. 인터넷 표준. URL: https://www.rfc-editor.org/rfc/rfc1035
[RFC2397]
L. Masinter. "data" URL 스킴. 1998년 8월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc2397
[RFC6960]
S. Santesson; et al. X.509 인터넷 공개 키 인프라 온라인 인증서 상태 프로토콜 - OCSP. 2013년 6월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc6960
[RFC7301]
S. Friedl; et al. 전송 계층 보안(TLS) 애플리케이션 계층 프로토콜 협상 확장. 2014년 7월. 제안 표준. URL: https://www.rfc-editor.org/rfc/rfc7301
[RFC7918]
A. Langley; N. Modadugu; B. Moeller. 전송 계층 보안(TLS) False Start. 2016년 8월. 정보성. URL: https://www.rfc-editor.org/rfc/rfc7918
[RFC8470]
M. Thomson; M. Nottingham; W. Tarreau. HTTP에서 Early Data 사용. 2018년 9월. 제안 표준. URL: https://httpwg.org/specs/rfc8470.html
[RFC9163]
E. Stark. HTTP용 Expect-CT 확장. 2022년 6월. 실험적. URL: https://www.rfc-editor.org/rfc/rfc9163

IDL 색인

typedef (sequence<sequence<ByteString>> or record<ByteString, ByteString>) HeadersInit;

[Exposed=(Window,Worker)]
interface Headers {
  constructor(optional HeadersInit init);

  undefined append(ByteString name, ByteString value);
  undefined delete(ByteString name);
  ByteString? get(ByteString name);
  sequence<ByteString> getSetCookie();
  boolean has(ByteString name);
  undefined set(ByteString name, ByteString value);
  iterable<ByteString, ByteString>;
};

typedef (Blob or BufferSource or FormData or URLSearchParams or USVString) XMLHttpRequestBodyInit;

typedef (ReadableStream or XMLHttpRequestBodyInit) BodyInit;
interface mixin Body {
  readonly attribute ReadableStream? body;
  readonly attribute boolean bodyUsed;
  [NewObject] Promise<ArrayBuffer> arrayBuffer();
  [NewObject] Promise<Blob> blob();
  [NewObject] Promise<Uint8Array> bytes();
  [NewObject] Promise<FormData> formData();
  [NewObject] Promise<any> json();
  [NewObject] Promise<USVString> text();
};
typedef (Request or USVString) RequestInfo;

[Exposed=(Window,Worker)]
interface Request {
  constructor(RequestInfo input, optional RequestInit init = {});

  readonly attribute ByteString method;
  readonly attribute USVString url;
  [SameObject] readonly attribute Headers headers;

  readonly attribute RequestDestination destination;
  readonly attribute USVString referrer;
  readonly attribute ReferrerPolicy referrerPolicy;
  readonly attribute RequestMode mode;
  readonly attribute RequestCredentials credentials;
  readonly attribute RequestCache cache;
  readonly attribute RequestRedirect redirect;
  readonly attribute DOMString integrity;
  readonly attribute boolean keepalive;
  readonly attribute boolean isReloadNavigation;
  readonly attribute boolean isHistoryNavigation;
  readonly attribute AbortSignal signal;
  readonly attribute RequestDuplex duplex;

  [NewObject] Request clone();
};
Request includes Body;

dictionary RequestInit {
  ByteString method;
  HeadersInit headers;
  BodyInit? body;
  USVString referrer;
  ReferrerPolicy referrerPolicy;
  RequestMode mode;
  RequestCredentials credentials;
  RequestCache cache;
  RequestRedirect redirect;
  DOMString integrity;
  boolean keepalive;
  AbortSignal? signal;
  RequestDuplex duplex;
  RequestPriority priority;
  any window; // can only be set to null
};

enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "frame", "iframe", "image", "json", "manifest", "object", "paintworklet", "report", "script", "sharedworker", "style",  "track", "video", "worker", "xslt" };
enum RequestMode { "navigate", "same-origin", "no-cors", "cors" };
enum RequestCredentials { "omit", "same-origin", "include" };
enum RequestCache { "default", "no-store", "reload", "no-cache", "force-cache", "only-if-cached" };
enum RequestRedirect { "follow", "error", "manual" };
enum RequestDuplex { "half" };
enum RequestPriority { "high", "low", "auto" };

[Exposed=(Window,Worker)]interface Response {
  constructor(optional BodyInit? body = null, optional ResponseInit init = {});

  [NewObject] static Response error();
  [NewObject] static Response redirect(USVString url, optional unsigned short status = 302);
  [NewObject] static Response json(any data, optional ResponseInit init = {});

  readonly attribute ResponseType type;

  readonly attribute USVString url;
  readonly attribute boolean redirected;
  readonly attribute unsigned short status;
  readonly attribute boolean ok;
  readonly attribute ByteString statusText;
  [SameObject] readonly attribute Headers headers;

  [NewObject] Response clone();
};
Response includes Body;

dictionary ResponseInit {
  unsigned short status = 200;
  ByteString statusText = "";
  HeadersInit headers;
};

enum ResponseType { "basic", "cors", "default", "error", "opaque", "opaqueredirect" };

partial interface mixin WindowOrWorkerGlobalScope {
  [NewObject] Promise<Response> fetch(RequestInfo input, optional RequestInit init = {});
};

dictionary DeferredRequestInit : RequestInit {
  DOMHighResTimeStamp activateAfter;
};

[Exposed=Window]
interface FetchLaterResult {
  readonly attribute boolean activated;
};

partial interface Window {
  [NewObject] FetchLaterResult fetchLater(RequestInfo input, optional DeferredRequestInit init = {});
};

MDN

Headers/Headers

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/append

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/delete

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/get

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/getSetCookie

In all current engines.

Firefox112+Safari17+Chrome113+
Opera?Edge113+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js19.7.0+
MDN

Headers/has

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/set

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Request/Request

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera27+Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile27+
MDN

Request/arrayBuffer

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/arrayBuffer

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/blob

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/blob

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/body

FirefoxNoneSafari11.1+Chrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/body

In all current engines.

Firefox65+Safari10.1+Chrome43+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/bodyUsed

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/bodyUsed

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/cache

In all current engines.

Firefox48+Safari10.1+Chrome64+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/clone

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/credentials

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/destination

In all current engines.

Firefox61+Safari10.1+Chrome65+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/formData

In all current engines.

Firefox39+Safari14.1+Chrome60+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/formData

In all current engines.

Firefox39+Safari14.1+Chrome60+
Opera?Edge79+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/headers

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/integrity

In all current engines.

Firefox51+Safari10.1+Chrome46+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/json

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/json

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/method

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/mode

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/redirect

In all current engines.

Firefox43+Safari10.1+Chrome46+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/referrer

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/referrerPolicy

In all current engines.

Firefox47+Safari10.1+Chrome52+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet7.2+Opera Mobile?
MDN

Request/signal

In all current engines.

Firefox57+Safari12.1+Chrome66+
Opera?Edge79+
Edge (Legacy)16+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/text

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?

Response/text

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Request/url

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile27+
MDN

Request

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Response/Response

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/clone

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/error_static

In all current engines.

Firefox39+Safari10.1+Chrome43+
Opera?Edge79+
Edge (Legacy)16+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/headers

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/json_static

Firefox115+SafariNoneChrome105+
Opera?Edge105+
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/ok

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/redirect_static

In all current engines.

Firefox39+Safari10.1+Chrome44+
Opera?Edge79+
Edge (Legacy)16+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/redirected

In all current engines.

Firefox49+Safari10.1+Chrome57+
Opera?Edge79+
Edge (Legacy)16+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView60+Samsung Internet8.0+Opera Mobile?
MDN

Response/status

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/statusText

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/type

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response/url

In all current engines.

Firefox39+Safari10.1+Chrome40+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Response

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

fetch

In all current engines.

Firefox39+Safari10.1+Chrome42+
Opera?Edge79+
Edge (Legacy)14+IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
Node.js18.0.0+
MDN

Headers/Access-Control-Allow-Credentials

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Allow-Headers

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Allow-Methods

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Allow-Origin

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Expose-Headers

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Max-Age

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Request-Headers

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Access-Control-Request-Method

In all current engines.

Firefox3.5+Safari4+Chrome4+
Opera12+Edge79+
Edge (Legacy)12+IE10+
Firefox for Android?iOS Safari?Chrome for AndroidYesAndroid WebView2+Samsung Internet?Opera Mobile12+
MDN

Headers/Cross-Origin-Resource-Policy

In all current engines.

Firefox74+Safari12+Chrome73+
OperaNoneEdge79+
Edge (Legacy)NoneIENone
Firefox for AndroidNoneiOS Safari?Chrome for Android?Android WebView?Samsung Internet11.0+Opera MobileNone
MDN

Headers/Origin

In all current engines.

Firefox70+SafariYesChromeYes
Opera?EdgeYes
Edge (Legacy)12+IEYes
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera Mobile?
MDN

Headers/Sec-Purpose

In only one current engine.

Firefox115+SafariNoneChromeNone
Opera?EdgeNone
Edge (Legacy)?IENone
Firefox for Android?iOS Safari?Chrome for Android?Android WebView?Samsung Internet?Opera MobileNone
MDN

Headers/X-Content-Type-Options

In all current engines.

Firefox50+Safari11+Chrome64+
OperaYesEdge79+
Edge (Legacy)12+IE8+
Firefox for Android?iOS Safari?Chrome for Android64+Android WebView?Samsung Internet?Opera MobileYes