Fetch

Fetch

Версия стандарта от 06 августа 2020 г.

Принимать участие:

Фиксации:

Тесты:

Переводы (ненормативные):

 

 

Аннотация

Стандарт Fetch определяет запросы, ответы и процесс, который их связывает: выборка (fetching).

Оглавление

Цели
1 Предисловие

2 Инфраструктура
2.1 URL
2.2 HTTP
2.2.1 Методы
2.2.2 Заголовки
2.2.3 Статусы
2.2.4 Тела
2.2.5 Запросы
2.2.6 Ответы
2.2.7 Разное
2.3 Записи аутентификации
2.4 Группы Выборки
2.5 Разрешение доменов
2.6 Соединения
2.7 Ключи сетевых разделов
2.8 Разделы кеша HTTP
2.9 Блокировка портов
2.10 Должен ли ответ на запрос быть заблокирован из-за его MIME-типа?

3 Расширения HTTP
3.1 Заголовок «Origin«
3.2 Протокол CORS
3.2.1 Общие положения
3.2.2 HTTP-запросы
3.2.3 HTTP-ответы
3.2.4 Синтаксис нового заголовка HTTP
3.2.5 Протокол CORS и учетные данные
3.2.6 Примеры
3.2.7 Исключения протокола CORS
3.3 Заголовок «Content-Length«
3.4 Заголовок «Content-Type«
3.5 Заголовок «X-Content-Type-Options«
3.5.1 Должен ли ответ на запрос быть заблокирован из-за nosniff?
3.6 CORB
3.7 Заголовок «Cross-Origin-Resource-Policy«

4 Выборка
4.1 Основная выборка
4.2 Схема выборки
4.3 Выборка HTTP
4.4 Выборка HTTP-перенаправление
4.5 Выборка HTTP-сеть или кэш
4.6 Выборка HTTP-сеть
4.7 Выборка CORS-предполетная
4.8 Кеш CORS-предполетный
4.9 Проверка CORS
4.10 Проверка TAO

5 Fetch API
5.1 Класс Headers
5.2 Союзы BodyInit
5.3 Миксин Body
5.4 Класс Request
5.5 Класс Response
5.6 Метод Fetch
5.7 Сборка мусора

6 Изменения протокола WebSocket
6.1 Соединения
6.2 Открытие рукопожатия

7 data: URLs
Фоновое чтение
Разделение слоя заголовка HTTP
Атомарная обработка перенаправления HTTP
Базовая безопасная настройка протокола CORS
CORS протокол и HTTP кеши
Благодарности
Индекс
Термины, определенные в этой спецификации
Термины, определенные ссылкой
Ссылки
Нормативные ссылки
Информационные ссылки
Индекс IDL

 

Цели

Цель состоит в том, чтобы унифицировать выборки через веб-платформу и обеспечить согласованную обработку всего, что включает в себя, включая:

  • Схемы URL
  • Перенаправления
  • Семантика перекрестного происхождения
  • CSP [CSP]
  • Сервисные работники [SW — Service workers]
  • Смешанный контент [MIX — Mixed Content]
  • `Referer` [REFERRER]

Для этого он также заменяет семантику заголовка HTTP `Origin`, изначально определенную в The Web Origin Concept. [Происхождения]

 

1. Предисловие

На высоком уровне получение ресурса — довольно простая операция. Запрос поступает, ответ выходит. Детали этой операции, однако, довольно сложны и раньше не были тщательно записаны и отличаются от одного API к другому.

Многочисленные API предоставляют возможность извлечения ресурса, например, HTML-элемент img и script, CSS cursor и list-style-image, JavaScript API navigator.sendBeacon() и self.importScripts(). Стандарт Fetch предоставляет унифицированную архитектуру для этих функций, поэтому они все согласованы, когда речь идет о различных аспектах выборки, таких как перенаправления и протокол CORS.

Стандарт Fetch также определяет JavaScript API fetch(), который предоставляет большую часть сетевых функций на довольно низком уровне абстракции.

 

2. Инфраструктура

Эта спецификация зависит от стандарта Infra. [INFRA]

Эта спецификация использует терминологию из ABNF, Encoding, HTML, HTTP, IDL, MIME Sniffing, Streams и URL стандартов. [ABNF] [ENCODING] [HTML] [HTTP] [WEBIDL] [MIMESNIFF] [STREAMS] [URL]

ABNF означает ABNF, дополненный HTTP (в частности, добавлением #) и RFC 7405. [RFC7405]

Учетными данными являются файлы cookie HTTP, сертификаты клиента TLS и записи аутентификации (для аутентификации HTTP). [COOKIES] [TLS] [HTTP-AUTH]

Задачи, поставленные в очередь этим стандартом, помечены как одна из:

  • процесс тела запроса (process request body)
  • процесс конца тела запроса (process request end-of-body)
  • процесс ответа (process response)
  • процесс конца тела ответа (process response end-of-body)
  • процесс выполнения ответа (process response done)

Чтобы поставить в очередь задачу выборки по request запроса на выполнение операции, выполните следующие действия:

  1. Если запрос клиента null, прекратите эти шаги.
  2. Поставьте задачу в очередь для выполнения операции в цикле ответственных событий запроса клиента с использованием источника сетевых задач.

Чтобы поставить задачу fetch-request-done (выборка-запрос-выполнено) в очередь запроса, поставьте в очередь задачу выборки по запросу, чтобы process request end-of-body (обработать конец тела запроса) для запроса.

Чтобы сериализовать целое число, представьте его как строку кратчайшего возможного десятичного числа.

Это будет заменено более описательным алгоритмом в Infra. См. Ниже / 201.

 

2.1 URL

Локальная схема (local scheme) — это схема «about», «blob» или «data».

URL является локальным, если его схема является локальной схемой.

Это определение также используется в «Политике РеферераReferrer Policy«. [Referrer]

Схема HTTP (S) — это схема «http» или «https«.

Схема сети — это схема «ftp» или схема HTTP (S).

Схема выборки — это схема «about», «blob», «data», «file» или схема сети.

Схема HTTP (S), схема сети и схема выборки также используются HTML,ем. [HTML]

URL-адрес ответа — это URL-адрес, для которого реализация не должна хранить фрагмент, поскольку он никогда не отображается. При сериализации устанавливается флаг исключения фрагмента, что означает, что реализации могут, тем не менее, сохранить фрагмент.

 

2.2 HTTP

Хотя выборка включает в себя больше, чем просто HTTP, она заимствует ряд понятий из HTTP и применяет их к ресурсам, полученным с помощью других средств (например, URL-адресов данных data).

HTTP tab or space (HTTP табулятор или пробел): U + 0009 TAB или U + 0020 SPACE.

HTTP whitespace является U + 000A LF, U + 000D CR или HTTP табулятор или HTTP пробел.

HTTP whitespace полезен только для конкретных конструкций, которые повторно используются вне контекста заголовков HTTP (например, типов MIME). Для значений заголовка HTTP предпочтительнее использовать табулятор или пробел HTTP, и вне этого контекста предпочтительны пробелы ASCII. В отличие от пробелов ASCII это исключает U + 000C FF.

HTTP newline byte (Новый линейный байт HTTP) — 0x0A (LF) или 0x0D (CR).

HTTP tab or space byte — 0x09 (HT) или 0x20 (SP).

HTTP whitespace byte — это HTTP newline byte или HTTP tab or space byte.

HTTPS state value (Значение состояния HTTPS) — это «none«, «deprecated«, или «modern«.

Ответ, доставленный по HTTPS, обычно имеет состояние HTTPS, установленное на «modern» (современный). Пользовательский агент может использовать «deprecated» (не рекомендуется) в переходный период. Например, при удалении поддержки хеш-функции, слабых наборов шифров, сертификатов для «Внутреннего Имени» или сертификатов с чрезмерно длинным периодом действия. Как именно пользовательский агент может использовать «deprecated«, не определено в данной спецификации. Объект настроек среды обычно получает свое HTTPS-состояние из ответа.

Чтобы собрать строку в кавычках HTTP из строкового ввода, учитывая положение переменной позиции и, возможно, флаг извлечения значения, выполните следующие шаги:

1. Пусть positionStart будет позицией.
2. Пусть значение будет пустой строкой.
3. Утверждение: кодовая точка в позиции ввода U + 0022 (").
4. Продвиньте позицию на 1.
5. Пока это правда:
   5.1. Прибавьте результат сбора последовательности кодовых точек, которые не являются U + 0022 (") или U + 005C (\) из ввода, данной позиции, к значению.
   5.2. Если позиция находится за концом ввода, прервитесь.
   5.3. Пусть quoteOrBackslash будет точкой кода в позиции в пределах ввода.
   5.4 Продвиньте позицию на 1.
   5.5 Если quoteOrBackslash равен U + 005C (\), то:
      5.5.1 Если позиция находится за концом ввода, добавьте U + 005C (\) к значению и разбейте.
      5.5.2 Добавьте кодовую точку в позиции в пределах ввода к значению.
      5.5.3 Продвиньте позицию на 1.
   5.6 В противном случае:
      5.6.1 Утверждение: quoteOrBackslash - это U + 0022 (").
      5.6.2 Разбейте
6. Если установлен "extract-value flag" (флаг извлечения-значения), тогда верните значение.
7. Верните кодовые точки из positionStart в позицию, включительно, внутри ввода.

Аргумент флага extract-value делает этот алгоритм пригодным для получения, декодирования и разделения и анализа MIME-типа, а также других анализаторов значений заголовка, которые могут в этом нуждаться.

 

2.2.1 Методы

Метод (Method) — это последовательность байтов, которая соответствует производству токена метода.

CORS-надёжно перечисленный метод (CORS-safelisted method) — это метод `GET`, `HEAD` или `POST`.

Запрещенный метод (Forbidden method) — это метод, который является нечувствительным к регистру байтов совпадением для `CONNECT`, `TRACE` или `TRACK`. [HTTPVERBSEC1], [HTTPVERBSEC2], [HTTPVERBSEC3]

Чтобы нормализовать метод (normalize a method), если это нечувствительное к регистру байтов совпадение для `DELETE`, `GET`, `HEAD`, `OPTIONS`, `POST` или `PUT`, введите его заглавными байтами.

Примечание

Нормализация выполняется для обратной совместимости и согласованности между API, поскольку методы на самом деле «чувствительны к регистру».

 

Пример

Использование `patch` с большой вероятностью приведет к ошибке`405 Method Not Allowed`. `PATCH` с заглавными буквами гораздо более успешен.

 

Примечание

Нет никаких ограничений на методы. `CHICKEN` вполне приемлемо (а не опечатка в `CHECKIN`). Кроме тех, которые нормализованы, также нет ограничений на оболочку. `Egg` или` eGg` подойдут, хотя заглавие рекомендуется для согласованности.

 

2.2.2 Заголовки

Список заголовков (Header list) — это список из нуля или более заголовков. Это изначально пустой список.

Примечание

Список заголовков по сути является специализированной мультикартой. Упорядоченный список пар ключ-значение с потенциально дублирующимися ключами.

Чтобы получить значение структурированного поля (get a structured field value) с указанием имени заголовка name и и строки type из списка заголовков list, выполните следующие действия:

1. Утверждено: type является одним из "dictionary" (словарь), "list" (список) или "item" (элемент).
2. Пусть value будет результатом получения name из list.
3. Если value равно «null», вернуть «null».
4. Пусть result будет результатом синтаксического анализа структурированных полей с «input_string», установленным в value, и «header_type», установленным в type.
5. Если синтаксический анализ не удался, верните «null».
6. Верните result.
Примечание

«Получение значения структурированного поля» намеренно не делает различий между отсутствующим «заголовком» и его «значением«, которое не может быть проанализировано как «значение структурированного поля«. Это обеспечивает равномерную обработку всей веб-платформы.

 

Чтобы установить значение структурированного поля (set a structured field value) для кортежа (имя заголовка name, значение структурированного поля structuredValue) в списке заголовков list, выполните следующие действия:

1. Пусть serializedValue будет результатом выполнения алгоритма сериализации структурированных полей в structuredValue.
2. Набор(name, serializedValue) в list.
Примечание

Значения структурированных полей определяются как объекты, которые HTTP может (в конечном итоге) сериализовать интересными и эффективными способами. На данный момент Fetch поддерживает значения заголовков только в виде байтовых последовательностей, что означает, что эти объекты могут быть установлены в списках заголовков только посредством сериализации, а их можно получить из списков заголовков только путем синтаксического анализа. В будущем то, что они являются объектами, может быть сохранено от начала до конца. [RFC8941]

 

Список заголовков list содержит (contains) имя заголовка name, если list содержит заголовок, имя которого нечувствительно к регистру байтов для name.

Чтобы получить (get) имя заголовка name из списка заголовков list, выполните следующие действия:

1. Если list не содержит name, верните null.
2. Верните значения всех заголовков в list, чье имя является нечувствительным к регистру байтов совпадающим с name, отделенных друг от друга 0x2C 0x20, по порядку.

Чтобы получить, декодировать и разделить (get, decode, and split) имя заголовка name из списка заголовков list, выполните следующие действия:

1. Пусть initialValue будет результатом получения name из list.
2. Если initialValue равно null, вернуть null.
3. Пусть input будет результатом изоморфного декодирования initialValue.
4. Пусть position будет позиционной переменной для input, изначально указывая на начало input.
5. Пусть values будет списком из строк, изначально пустой.
6. Пусть value будет пустой строкой.
7. Пока position не заканчивается после input:
   7.1. Добавьте результат сбора последовательности кодовых точек, которые не являются U+0022 (") или U+002C (,) из input, заданного position, в value.
      Примечание! Результатом может быть пустая строка.
   7.2. Если position не заканчивается после input, то:
      7.2.1. Если кодовая точка в position внутри input равна U+0022 ("), то:
         7.2.1.1. Добавить результат сбора строки в кавычках HTTP из input, заданной position, в value.
         7.2.1.2. Если position не заканчивается после input, то продолжайте.
      7.2.2. В противном случае:
         7.2.2.1. Утверждено: кодовая точка в position внутри input равна U+002C (,).
         7.2.2.2. Продвиньте position на 1.
   7.3. Удалите все табуляции и пробелы HTTP от начала и конца value.
   7.4. Добавьте value к values.
   7.5. Установите value в пустую строку.
8. Верните values

 

Пример

Вот как на практике получают, декодируют и разделяют функции с `A` в качестве аргумента name:

Заголовки (как в сети) Вывод
A: nosniff, « «nosniff», «» »
A: nosniff
B: sniff
A:
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

 

Чтобы добавить (append) заголовок (name, value) в список заголовков list, выполните следующие действия:

1. Если list содержит name, тогда установите name равным имени первого такого заголовка.
Примечание!

Это повторно использует регистр имени заголовка, уже имеющегося в списке list, если таковой имеется. Если есть несколько совпадающих заголовков, их имена будут одинаковыми.

2. Добавьте(name, value) в list.

 

Чтобы удалить (delete) имя заголовка name из списка заголовков list, удалите все заголовки, имя которых НЕ зависит от регистра символов и соответствует name из list.

 

Чтобы установить (set) заголовок (name, value) в списке заголовков list, выполните следующие действия:

1. Если list содержит name, тогда установите значение первого такого заголовка равным value и удалите остальные.
2. В противном случае, добавьте новый заголовок с именем name и значением value в list.

 

Чтобы объединить (combine) пару имя/значение «name/value» в список заголовков «list», выполните следующие действия:

1. Если list содержит name, тогда установите значение первого такого заголовка равным его значению, затем 0x2C, 0x20, а затем «value».
2. В противном случае добавьте новый заголовок с именем name и значением value в list.
Примечание

Объединение (Combine) использует XMLHttpRequest и протоколом рукопожатия WebSocket.

 

Чтобы преобразовать имена заголовков в упорядоченный набор строчных букв (convert header names to a sorted-lowercase set) с учетом списка имен headerNames, выполните следующие действия:

1. Пусть headerNamesSet будет новым упорядоченным набором.
2. Для каждого name из headerNames добавьте результат байтового name в headerNamesSet.
3. Верните результат сортировки headerNamesSet в порядке возрастания с байтом меньше.

 

Чтобы отсортировать и объединить (sort and combine) список заголовков list, выполните следующие действия:

1. Пусть headers будут пустым списком из заголовков (пар имя-значение), ключом является имя и значением является value.
2. Пусть names будет результатом преобразования имен заголовков в набор из отсортированных строчных букв со всеми именами заголовков в list.
3. Для каждого name в names:
   3.1. Пусть value будет результатом получения name из list.
   3.2. Утверждено: value не является null.
   3.3. Добавьте (name, value) к headers.
4. Верните headers

 

Заголовок (header) — это кортеж, состоящий из имени (nameимени заголовка) и значения (valueзначения заголовка). Заголовок состоит из имени и значения.

Имя заголовка (header name) — это последовательность байтов, которая соответствует производству токена имени поля.

Значение заголовка (header value) — это последовательность байтов, которая соответствует следующим условиям:

Примечание

Определение значения заголовка не определяется с точки зрения производства токена HTTP, поскольку оно повреждено.

Чтобы нормализовать (normalize) «potentialValue«, удалите все начальные и конечные байтовые пробелы HTTP из «potentialValue«.

Чтобы нормализовать (normalize) последовательность байтов potentialValue, удалите все начальные и конечные байты HTTP-пробелов  из potentialValue.

 

Чтобы определить, является ли заголовок (name, value) заголовком запроса CORS-safelisted (CORS-safelisted request-header), выполните следующие действия:

1. Если длина value больше 128, вернуть false.
2. Байт-нижний регистр name в нижнем регистре и включите результат:
   `accept`
      Если value содержит байт заголовка запроса небезопасного CORS, то возвращает false.
   `accept-language`
   `content-language`
      Если value содержит байт, который не находится в диапазоне от 0x30 (0) до 0x39 (9), включительно, не находится в диапазоне от 0x41 (A) в 0x5A (Z), включительно, не находится в диапазоне 0x61 (a) в 0x7A (z) включительно, и не 0х20 (SP), 0x2A (*), 0x2C (,), 0x2D (-), 0x2E (.), 0x3B (;) или 0x3D (=), а затем возвращает false.
   `content-type`
      Если value содержит небезопасный CORS-байт заголовка запроса, вернуть false.
      Пусть mimeType будет результатом синтаксического анализа value.
      Если mimeType является ошибкой, вернуть false.
      Если сущность mimeType не является "application/x-www-form-urlencoded", "multipart/form-data" или "text/plain", верните false.

ВНИМАНИЕ!

Это преднамеренно не использует извлечение MIME-типа, поскольку этот алгоритм довольно простителен, и серверы не должны его реализовывать.

Пример

Если используется извлечение типа 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`
      Если value не является значением заголовка простого диапазона, возвращается false.
   В противном случае
      Вернуть false.
3. Вернуть true
Примечание

Существуют ограниченные исключения для списка безопасности заголовка `Content-Type`, как описано в исключениях протокола CORS.

Байт заголовка запроса в небезопасном CORS (CORS-unsafe request-header byte) — это байт byte, для которого выполняется одно из следующих условий:

  • «byte» меньше 0x20 и не равен 0x09 HT
  • «byte» — это 0x22 («), 0x28 (left parenthesis), 0x29 (right parenthesis), 0x3A (:), 0x3C (<), 0x3E (>), 0x3F (?), 0x40 (@), 0x5B ([), 0x5C (\), 0x5D (]), 0x7B ({), 0x7D (}), или 0x7F DEL.

 

Имена заголовка запроса в небезопасном CORS (CORS-unsafe request-header names), учитывает список заголовков headers, определяются следующим образом:

1. Пусть unsafeNames будет новым списком.
2. Пусть potentiallyUnsafeNames будут новым списком.
3. Пусть safelistValueSize будет 0.
4. Для каждого header из headers:
   4.1. Если header не является заголовком запроса, сохраненным в CORS, добавьте имя header в unsafeNames.
   4.2. В противном случае добавьте имя header в potentiallyUnsafeNames и увеличьте safelistValueSize на длину значения header.
5. Если safelistValueSize больше 1024, то для каждого name из potentiallyUnsafeNames добавьте имя name к unsafeNames.
6. Возврат результата преобразования имен заголовков в отсортированный строчный набор с unsafeNames.

 

Имя заголовка запроса без подстановочных знаков CORS (CORS non-wildcard request-header name) — это имя заголовка, которое не зависит от регистра байта и соответствует `Authorization`.

Привилегированное имя заголовка запроса без CORS (privileged no-CORS request-header name) — это имя заголовка, которое является совпадением без учета регистра байтов для одного из

  • `Range`
Примечание

Это заголовки, которые могут быть установлены привилегированными API и будут сохранены, если их связанный объект запроса будет скопирован, но будут удалены, если запрос будет изменен непривилегированными API.

Заголовки `Range` обычно используются загрузками и медиа-выборками, хотя ни один из них в настоящее время не определяет, как. HTML/2914 стремится решить эту проблему.

Предусмотрен помощник для добавления заголовка диапазона к конкретному запросу.

 

Имя заголовка ответа, содержащееся в списке безопасности CORS (CORS-safelisted response-header name), с учетом списка имен заголовков list, является именем заголовка, которое является совпадением без учета регистра байтов для одного из

 

Имя заголовка запроса без CORS-безопасного списка (no-CORS-safelisted request-header name) — это имя заголовка, которое не зависит от регистра байтов для одного из

  • `Accept`
  • `Accept-Language`
  • `Content-Language`
  • `Content-Type`

 

Чтобы определить, является ли заголовок header заголовком запроса без CORS-безопасного списка (no-CORS-safelisted request-header), выполните следующие действия:

1. Если имя header не является именем заголовка запроса без внесенного в CORS списка, верните false.
2. Вернуть, является ли header заголовком запроса в безопасном списке CORS.

 

Запрещенное имя заголовка (forbidden header name) — это имя заголовка, которое не учитывает регистр байтов для одного из

или имя заголовка, которое начинается с нечувствительного к регистру байта совпадения для `proxy-` или `sec-` (включая нечувствительное к регистру байта совпадение только для `Proxy-` или `Sec-`).

Примечание

Они запрещены, поэтому пользовательский агент остается под полным контролем над ними. Имена заголовков, начинающиеся с `Sec-`, зарезервированы для того, чтобы позволять создавать новые заголовки, защищенные от API, использующих fetch, которые позволяют контролировать заголовки разработчикам, таким как XMLHttpRequest. [XHR]

 

Запрещенное имя заголовка ответа (forbidden response-header name) — это имя заголовка, которое без учета регистра байтов соответствует одному из:

  • `Set-Cookie`
  • `Set-Cookie2`

 

Имя заголовка тела запроса (request-body-header name) — это имя заголовка, которое без учета регистра байтов соответствует одному из:

  • `Content-Encoding`
  • `Content-Language`
  • `Content-Location`
  • `Content-Type`

 

Чтобы извлечь значения заголовков (extract header values) с учетом заголовка header, выполните следующие действия:

1. Если при синтаксическом анализе значения header, согласно ABNF для имени header, происходит сбой, возвращается ошибка.
2. Вернуть одно или несколько значений, полученных в результате анализа значения header, в соответствии с ABNF для имени header.

 

Чтобы извлечь значения списка заголовков (extract header list values) с учетом имени заголовка name и списка заголовков list, выполните следующие действия:

1. Если list не содержит name, вернуть null.
2. Если ABNF для name допускает один заголовок, а list содержит более одного, возвращает ошибку.
Примечание

Если требуется другая обработка ошибок, сначала извлеките нужный заголовок.

3. Пусть values будет пустым списком.
4. Для каждого заголовка header список list содержит чье имя name:
   4.1. Пусть extract будет результатом извлечения значений заголовка из header.
   4.2. Если extract является ошибкой, вернуть ошибку.
   4.3. Добавляйте каждое значение в extract по порядку к values.
5. Верните values

 

Чтобы определить, является ли байтовая последовательность value значением простого заголовка диапазона (simple range header value), выполните следующие действия. Они возвращают логическое значение.

1. Пусть данные data будут изоморфным декодированием значения value.
2. Если данные data не начинаются с "bytes=", вернуть false.
3. Пусть позиция position будет переменной позицией для данных data, изначально указывающей на 6-ю кодовую точку data.
4. Пусть rangeStart будет результатом сбора последовательности кодовых точек, которые являются цифрами ASCII, из data, заданных в position.
5. Если кодовая точка в position в data не является U+002D (-), вернуть false.
6. Продвинуть позицию position на 1.
7. Пусть rangeEnd будет результатом сбора последовательности кодовых точек, которые являются цифрами ASCII, из данных data, заданных в позиции position.
8. Если позиция position не превышает конец данных data, вернуть false.
9. Если длина rangeEnd равна 0, вернуть true.
Примечание

Конец диапазона можно не указывать, например, «bytes = 0-» допустимо.

10. Если rangeStart, интерпретируемый как десятичное число, больше, чем rangeEnd, интерпретируемый как десятичное число, возвращается false.
11. Верните true.
Примечание

Простое значение заголовка диапазона — это подмножество разрешенных значений заголовка диапазона, но это наиболее распространенная форма, используемая пользовательскими агентами при запросе мультимедиа или возобновлении загрузки. Этот формат значения заголовка диапазона можно установить с помощью добавления заголовка диапазона.

 

Значение `User-Agent` по умолчанию — это определяемое реализацией значение заголовка для заголовка `User-Agent`.

2.2.3 Статусы

Статус (status) — это целое число в диапазоне от 0 до 999 включительно.

В выпуске № 1156 прорабатываются различные граничные случаи при сопоставлении «status-code» (кода состояния) HTTP/1 с этой концепцией.

Статус тела null (null body status) — это статус 101, 204, 205 или 304.

Статус ok (ok status) — это статус в диапазоне от 200 до 299 включительно.

Статус перенаправления (redirect status) — это статус 301, 302, 303, 307 или 308.

 

2.2.4 Тела

Тело (body) состоит из:

  • Поток (stream) (null или объект ReadableStream).
  • Источник (source) (значение null, последовательность байтов, объект Blob или объект FormData) изначально имеет значение null.
  • Длина (length) (null или целое число), изначально равная null.
  • УДАЛЕНО ИЗ СТАНДАРТА!!! Переданные байты (transmitted bytes) (целое число), изначально 0.
  • УДАЛЕНО ИЗ СТАНДАРТА!!! Общее число байтов (total bytes) (целое число), изначально 0.

 

Чтобы Клонировать (clone) тело «body«, выполните следующие действия:

1. Пусть "out1, out2" будет результатом течения потока "body".
2. Установите поток body в out1.
3. Вернуть тело, поток которого является out2, а другие члены скопированы из body.

 

УДАЛЕНО ИЗ СТАНДАРТА!!! Чтобы обработать кодирование содержимого с заданными кодировками «codings» и байтами «bytes«, выполните следующие действия:

  1. Если кодировки «codings» не поддерживаются, вернуть байты «bytes«.
  2. Возвращает результат декодирования байтов «bytes» с кодировками, как описано в HTTP, если декодирование не приводит к ошибке, а в противном случае к сбою. [HTTP] [HTTP-SEMANTICS]

 

Для постепенного чтения (incrementally read) тела тела с учетом алгоритма processBodyChunk, алгоритма processEndOfBody, алгоритма processBodyError и необязательного значения null, параллельной очереди или глобального объекта taskDestination (значение по умолчанию null) выполните эти шаги. processBodyChunk должен быть алгоритмом, принимающим последовательность байтов. processEndOfBody должен быть алгоритмом, не принимающим аргументов. processBodyError должен быть алгоритмом, принимающим исключение.

1. Если taskDestination имеет значение null, задайте для taskDestination результат запуска новой параллельной очереди.
2. Пусть reader будет результатом получения читателя для потока тела body.
Примечание

Эта операция не вызовет исключения.

3. Выполните цикл с инкрементным чтением для данных reader, taskDestination, processBodyChunk, processEndOfBody и processBodyError.

 

Чтобы выполнить Цикл с инкрементальным чтением (incrementally-read loop), учитывая ReadableStreamDefaultReader объекта reader, параллельную очередь или глобальный объект taskDestination, алгоритм processBodyChunk, алгоритм processEndOfBody и алгоритм processBodyError:

1. Пусть readRequest будет следующим запросом на чтение:


шаги кусочка (chunk steps), учитывая chunk:

   1. Пусть continueAlgorithm будет null.
   2. Если chunk не является объектом Uint8Array, установите continueAlgorithm на этот шаг: запустите processBodyError с учетом TypeError.
   3. Иначе:

      1. Пусть байты bytes будут копией кусочка - chunk.

 

Примечание

Реализациям настоятельно рекомендуется использовать стратегию реализации, которая по возможности избегает этой копии.

      2. Задайте для алгоритма продолжения следующие шаги: 
         1. Запустить processBodyChunk с заданными байтами bytes. 
         2. Выполните цикл с инкрементным чтением для данных reader, taskDestination, processBodyChunk, processEndOfBody и processBodyError. 
   4. Поставьте задачу выборки в очередь с учетом continueAlgorithm и taskDestination. 


близкие шаги (close steps)
   1. Поставить в очередь задачу выборки с учетом processEndOfBody и taskDestination. 


шаги ошибки (error steps), учитывая e

   1. Поставить задачу выборки в очередь для запуска processBodyError с заданным e с помощью taskDestination. 
2. Прочитать кусочек от читателя reader, заданного readRequest.

 

Чтобы полностью прочитать (fully read) тело body с учетом алгоритма processBody, алгоритма processBodyError и необязательного значения null, параллельной очереди или глобального объекта taskDestination (значение по умолчанию null), выполните следующие действия. processBody должен быть алгоритмом, принимающим последовательность байтов. processBodyError должен быть алгоритмом, не принимающим аргументов.

1. Если taskDestination имеет значение null, задайте для taskDestination результат запуска новой параллельной очереди.
2. Пусть promise будет результатом полного чтения тела как обещания, данного body.
3. Пусть finishedSteps с байтовой последовательностью bytes ставит в очередь задачу выборки для запуска processBody с заданными bytes с taskDestination.
4. Пусть rejectedSteps помещает задачу выборки в очередь для запуска processBodyError с taskDestination.
5. Реагируйте на обещание promise с помощью выполненных шагов fulfilledSteps и отклоненных шагов rejectedSteps.

 

Чтобы полностью прочитать тело как обещание (fully read body as promise) для данного тела body, выполните следующие действия:

1. Пусть reader будет результатом получения читателя для потока тела body. Если это вызвало исключение, вернуть обещание, отклоненное с этим исключением.
2. Вернуть результат чтения всех байтов от читателя reader.

 

Чтобы обработать кодирование содержимого (handle content codings) с учетом codings и bytes, выполните следующие действия:

1. Если codings не поддерживаются, вернуть bytes.
2. Возвращает результат декодирования байтов bytes с кодировками codings, как описано в HTTP, если декодирование не приводит к ошибке, и неудачу в противном случае. [HTTP] [HTTP-SEMANTICS]

 

2.2.5 Запросы

Входными данными для выборки является запрос (request).

С запросом связан метод (method). Если не указано иное, это `GET`.

Примечание

Это может быть обновлено во время перенаправления на `GET`, как описано в HTTP-выборке.

С запросом связан URL (URL).

Примечание

Реализациям рекомендуется делать это указателем на первый URL в списке URL-адресов запроса. Он предоставляется как отдельное поле исключительно для удобства подключения других стандартов к Fetch.

С запросом связан флаг только локальных URL (local-URLs-only flag). Если не указано иное, он не установлен.

С запросом связан список заголовков (header list). Если не указано иное, он пуст.

С запросом связан флаг небезопасного запроса (unsafe-request flag). Если не указано иное, он не установлен.

Примечание

Флаг небезопасного запроса устанавливается такими API, как fetch() и XMLHttpRequest, чтобы гарантировать, что предварительная выборка CORS выполняется на основе предоставленного метода и списка заголовков. Это не освобождает API от запрещения запрещенных методов и запрещенных имен заголовков.

У запроса есть связанное тело (bodynull, последовательность байтов или тело). Если не указано иное, он является null.

Примечание

Последовательность байтов будет безопасно извлечена в тело на ранней стадии выборки. Как часть HTTP-выборки, это поле может быть установлено на null из-за определенных перенаправлений.

 

С запросом связан Клиент (clientnull или объект настроек среды).

С запросом связан Зарезервированный клиент (reserved clientnull, среда или объект настроек среды). Если не указано иное, он является null.

Примечание

Это используется только для запросов навигации и рабочих запросов, но не для запросов рабочих служб. Он ссылается на среду для запроса навигации и объект параметров среды для рабочего запроса.

С запросом связан идентификатор клиента замены (replaces client id — строка). Если не указано иное, это пустая строка.

С запросом связано Окно (window) («no-window«, «client» или объект настроек среды, глобальный объект которого является объектом Window). Если не указано иное, это «client«.

Примечание

Значение «client» изменяется на «no-window» или клиент запроса во время выборки. Это удобный способ избавить стандарты от необходимости явно указывать окно запроса.

С запросом связан флаг поддержки активности (keepalive flag). Если не указано иное, он является false.

Примечание

Это можно использовать, чтобы разрешить запросу переживать объект настроек среды, например, navigator.sendBeacon и элемент HTML img устанавливают этот флаг. Запросы с этим установленным флагом подлежат дополнительной обработке.

Запрос имеет связанный с ним Режим Работников Службы (service-workers mode), то есть «all» или «none«. Если не указано иное, это «all«.

Примечание

Это определяет, какие работники службы получат событие «fetch» для этой выборки.

«all«

Соответствующие работники службы получат событие «fetch» для этой выборки.

«none«

Никакие работники службы не получат событий для этой выборки.

 

С запросом связан Инициатор (initiator), который представляет собой пустую строку, «download«, «imageset«, «manifest«, «prefetch«, «prerender» или «xslt«. Если не указано иное, это пустая строка.

Примечание

Инициатор запроса на данный момент не отличается особой детальностью, поскольку этого не требуют другие спецификации. Это в первую очередь устройство спецификации, помогающее определять CSP и смешанный контент. Он не доступен для JavaScript. [CSP] [MIX]

 

С запросом связано Назначение (destination), которое представляет собой пустую строку, «audio«, «audioworklet«, «document«, «embed«, «font«, «frame«, «iframe«, «image«, «manifest«, «object«, «paintworklet«, «report«, «script«, «serviceworker«, «sharedworker«, «style«, «track«, «video«, «worker» или «xslt«. Если не указано иное, это пустая строка.

Пункт назначения запроса Похож на сценарий (script-like), если это «audioworklet«, «paintworklet«, «script«, «serviceworker«, «sharedworker«, или «worker«.

 

Предупреждение!!! Алгоритмы, использующие подобные сценариям, также должны учитывать «xslt«, поскольку это тоже может вызвать выполнение сценария. Он не включен в список, поскольку не всегда актуален и может требовать другого поведения.

 

Примечание

В следующей таблице показана взаимосвязь между инициатором запроса, местом назначения, директивами CSP и функциями. Он не является исчерпывающим в отношении функций. Функции должны иметь соответствующие значения, определенные в соответствующих стандартах.

Инициатор (Initiator) Место назначения (Destination) CSP директива Характеристики
«» «report« CSP, NEL отчёты
«document« Алгоритм навигации HTML (только на верхнем уровне)
«frame« child-src HTML элемент <frame>
«iframe« child-src HTML элемент <iframe>
«» connect-src navigator.sendBeacon(),

EventSource,

HTML элемент <a ping=»»> и <area ping=»»>,

fetch(),

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’s <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
«worker« child-src, script-src, worker-src Worker
«style« style-src HTML элемент <link rel=stylesheet>,

CSS медиа-запрос @import

«track« media-src HTML элемент <track>
«video« media-src HTML элемент <video>
«download» «» HTML’s download=»», «Сохранить ссылку как…» UI-пользовательский интерфейс
«imageset» «image« img-src HTML элемент <img srcset> и <picture>
«manifest» «manifest« manifest-src HTML элемент <link rel=manifest>
«prefetch» «» prefetch-src HTML элемент <link rel=prefetch>
«prerender» «» prefetch-src HTML элемент <link rel=prerender>
«xslt» «xslt« script-src <?xml-stylesheet>

CSP «form-action» должно быть перехватчиком непосредственно в алгоритме навигации HTML или отправки формы.

CSP также потребуется проверить контексты просмотра предков контекста просмотра глобального объекта клиента запроса на наличие различных директив CSP.

 

Запрос имеет связанный Приоритет (prioritynull или объект, определенный пользовательским агентом). Если не указано иное, он имеет значение null.

С запросом связан Источник (origin), которым является «client» или источник. Если не указано иное, это «client«.

Примечание

«client» изменяется на источник во время выборки. Это позволяет стандартам не указывать источник запроса.

С запросом связан Контейнер Политики (policy container), который является «client» или контейнером политики. Если не указано иное, это «client«.

Примечание

«client» заменяется контейнером политики во время выборки. Это удобный способ избавить стандарты от необходимости устанавливать контейнер политики запроса.

С запросом связан Рефёрер — Источник перехода (referrer), который является «no-referrer«, «client» или URL. Если не указано иное, это «client«.

Примечание

«client» заменяется на «no-referrer» или URL-адрес во время выборки. Это позволяет стандартам не указывать источник перехода для запроса.

С запросом связана Политика рефёрера (referrer policy), которая является политикой источника перехода. Если не указано иное, это пустая строка. [Referrer]

Примечание

Это можно использовать для переопределения политики рефёрера, которая будет использоваться для этого запроса.

ЭТО УДАЛЕНО!!! С запросом связан Синхронный Флаг (synchronous flag). Если не указано иное, он не установлен.

 

С запросом связан Режим (mode): «same-origin«, «cors«, «no-cors«, «navigate«, или «websocket«. Если не указано иное, это «no-cors«.

Примечание

«same-origin«

Используется для обеспечения того, чтобы запросы делались на URL-адреса того же происхождения. Fetch вернет сетевую ошибку, если запрос не направлен на URL-адрес того же происхождения.

«cors«

Для запросов, чье повреждение ответа установлено на «cors«, делает запрос CORS-запрос — в этом случае fetch вернет сетевую ошибку, если запрошенный ресурс не понимает протокол CORS или если запрошенный ресурс преднамеренно не участвуют в протоколе CORS.

«no-cors«

Запрещает запросы к использованию методов из списка надежных CORS и заголовков запросов из списка надежных CORS. В случае успеха выборка вернет непрозрачный фильтрованный ответ.

«navigate«

Это специальный режим, используемый только при переходе между документами.

«websocket«

Это специальный режим, используемый только при установке соединения WebSocket.

Несмотря на то, что режим запроса по умолчанию — «no-cors«, стандарты настоятельно не рекомендуют использовать его для новых функций. Это довольно небезопасно.

 

С запросом связан Флаг использования предварительной проверки CORS (use-CORS-preflight). Если не указано иное, он не установлен.

Примечание

Флаг использования предварительной проверки CORS является одним из нескольких условий, которые приводят к запросу CORS-preflight. Флаг использования предварительной проверки CORS устанавливается, если один или несколько прослушивателей событий зарегистрированы в объекте XMLHttpRequestUpload или если в запросе используется объект ReadableStream.

С запросом связан Режим Учётных Данных (credentials mode): «omit«, «same-origin» или «include» («пропустить», «тот же источник» или «включить»). Если не указано иное, он «того же происхождения» — «same-origin«.

Примечание

«omit«

Исключает учётные данные из этого запроса и заставляет игнорировать все учётные данные, отправленные обратно в ответе.

«same-origin«

Включает учётные данные в запросы, отправленные на URL-адреса того же происхождения, и использует любые учётные данные, отправленные обратно в ответах с URL-адресов того же происхождения.

«include«

Всегда включает учётные данные с этим запросом и всегда использует любые учётные данные, отправленные обратно в ответ.

Режим учётных данных запроса контролирует поток учётных данных во время выборки. Когда режим запроса — «navigate» (навигация), предполагается, что его режим учётных данных — «include«, а выборка в настоящее время не учитывает другие значения. Если HTML изменится здесь, этот стандарт потребует соответствующих изменений.

 

С запросом связан Флаг использования-URL-учетных данных (use-URL-credentials flag). Если не указано иное, он не установлен.

С запросом связан Режим Кэширования (cache mode):

  • «default«
  • «no-store«
  • «reload«
  • «no-cache«
  • «force-cache«
  • «only-if-cached«

(«по умолчанию», «без сохранения», «перезагрузка», «без кеширования», «принудительное кеширование» или «только при кэшировании»). Если не указано иное, это «default» (по умолчанию).

Примечание

«default«

Fetch будет проверять HTTP-кеш на пути к сети. Если HTTP-кеш содержит соответствующий свежий ответ, он будет возвращен. Если HTTP-кеш содержит соответствующий ответ устаревшего при повторной проверке, он будет возвращен, и будет произведена условная сетевая выборка для обновления записи в кеше HTTP. Если HTTP-кеш содержит соответствующий устаревший ответ, будет возвращена условная сетевая выборка для обновления записи в кеше HTTP. В противном случае будет возвращена безусловная сетевая выборка для обновления записи в кэше HTTP. [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] [STALE-WHILE-REVALIDATE]

«no-store«

Fetch ведет себя так, как будто HTTP-кеша вообще нет.

«reload«

Fetch ведет себя так, как будто на пути к сети нет HTTP-кеша. Следовательно, он создает обычный запрос и обновляет HTTP-кеш ответом.

«no-cache«

Fetch создает условный запрос, если есть ответ в кеше HTTP, и обычный запрос в противном случае. Затем он обновляет HTTP-кеш ответом.

«force-cache«

Fetch использует любой ответ в HTTP-кеше, соответствующий запросу, не обращая внимания на устаревание. Если ответа нет, он создает обычный запрос и обновляет HTTP-кеш ответом.

«only-if-cached«

Fetch использует любой ответ в HTTP-кеше, соответствующий запросу, не обращая внимания на устаревание. Если ответа нет, возвращается сетевая ошибка. (Может использоваться только в том случае, если режим запроса — «same-origin» (тот же источник). Любые кэшированные перенаправления будут выполняться при условии, что режим перенаправления запроса — «follow» (следовать) и перенаправления не нарушают режим запроса.)

Если список заголовков содержит `If-Modified-Since`, `If-None-Match`, `If-Unmodified-Since`, `If-Match` или`If-Range`, выборка установит режим кеширования на «no-store» если это «default«.

 

С запросом связан Режим Перенаправления (redirect mode): «follow«, «error«, или «manual» («следование», «ошибка» или «ручной»). Если не указано иное, это «follow«.

Примечание

«follow«

Следует всем перенаправлениям, возникающим при получении ресурса.

«error«

Возвращает сетевую ошибку, когда запрос встречается с перенаправлением.

«manual«

Извлекает отфильтрованный ответ с непрозрачным перенаправлением, когда запрос встречается с перенаправлением, чтобы позволить работнику службы воспроизвести перенаправление в автономном режиме. В остальном ответ неотличим от сетевой ошибки, чтобы не нарушать атомарную обработку перенаправления HTTP.

 

С запросом связаны Метаданные Целостности (integrity metadata) (строка). Если не указано иное, это пустая строка.

С запросом связаны Криптографические Одноразовые Метаданные (cryptographic nonce metadata) (строка). Если не указано иное, это пустая строка.

С запросом связаны Метаданные Синтаксического Анализатора (parser metadata), которые представляют собой пустую строку, «parser-inserted» (вставлено синтаксическим анализатором) или «not-parser-inserted» (не вставлено анализатором). Если не указано иное, это пустая строка.

Примечание

Криптографические Одноразовые Метаданные запроса и метаданные синтаксического анализатора обычно заполняются из атрибутов и флагов элемента HTML, ответственного за создание запроса. Они используются различными алгоритмами в Политике Безопасности Контента, чтобы определить, должны ли быть заблокированы запросы или ответы в данном контексте. [CSP]

С запросом связан Флаг перезагрузки-навигации (reload-navigation flag). Если не указано иное, он не установлен.

Примечание

Этот флаг предназначен исключительно для использования алгоритмом навигации HTML. [HTML]

С запросом связан Флаг навигации по истории (history-navigation flag). Если не указано иное, он не установлен.

Примечание

Этот флаг предназначен исключительно для использования алгоритмом навигации HTML. [HTML]

С запросом связана Логическая Активация Пользователя (user-activation). Если не указано иное, это false.

Примечание

Это исключительно для использования алгоритмом навигации HTML. [HTML]

 

 

С запросом связан Флаг Испорченного Происхождения (tainted origin flag). Если не указано иное, он не установлен.

С запросом связан Список URL-адресов (URL listсписок из одного или нескольких URL-адресов). Если не указано иное, это список, содержащий копию URL-адрес запроса.

С запросом связан Текущий URL (current URL). Это указатель на последний URL в списке URL-адресов запроса.

С запросом связан Счётчик перенаправления (redirect count). Если не указано иное, он равен нулю (zero).

С запросом связано Заражение Ответа (response tainting), которое является «basic«, «cors«, или «opaque«. Если не указано иное, это «basic«.

С запросом связан Флаг предотвращения модификации заголовка управления кэшем без кеширования (prevent no-cache cache-control header modification flag). Если не указано иное, он не установлен.

С запросом связан Флаг выполнения (done flag). Если не указано иное, он не установлен.

С запросом связан Флаг ошибки разрешения синхронизации (timing allow failed flag). Если не указано иное, он не установлен.

 

 

Запрос субресурса (subresource request) — это запрос, адресатом которого является «audio«, «audioworklet«, «font«, «image«, «manifest«, «paintworklet«, «script«, «style«, «track«, «video«, «xslt» или пустая строка.

Запрос, не относящийся к подресурсам (non-subresource request) — это запрос, адресатом которого является «document«, «embed«, «frame«, «iframe«, «object«, «report«, «serviceworker«, «sharedworker» или «worker«.

Запрос навигации (navigation request) — это запрос, адресатом которого является «document«, «embed«, «frame«, «iframe» или «object«.

Примечание

Смотри ручную выборку в разделе «Получение дескрипторов». [SW]

 

Сериализация источника запроса (Serializing a request origin) с учетом запроса «request» заключается в выполнении следующих шагов:

1. Если установлен флаг испорченного происхождения запроса request, вернуть "null".
2. Вернуть сериализованный источник request.

Байт-сериализация источника запроса (Byte-serializing a request origin) при наличии запроса «request» должна вернуть результат сериализации источника запроса с изоморфным кодированием «request».

 

Чтобы Клонировать (clone) запрос «request», выполните следующие действия:

1. Пусть newRequest будет копией request, за исключением его тела.
2. Если тело request не равно null, установите тело newRequest равным результату клонирования тела request.
3. Верните newRequest.

 

ЭТО УДАЛЕНО!!! Чтобы Передать тело (transmit body), запроса «request» , выполните следующие действия:

1. Пусть body будет телом request.
2. Если body имеет значение null, то поставьте в очередь задачу выборки по запросу для обработки конца тела запроса для request и прервите эти шаги.
3. Пусть reader будет результатом получения читателя из потока body. (Эта операция не может вызвать исключение.)
4. Выполните цикл передачи тела с учетом request, body и reader.

 

ЭТО УДАЛЕНО!!! Чтобы Выполнить цикл передачи тела (transmit-body loop) с учетом request, body и reader:

1. Пусть readRequest будет следующим запросом на чтение:

шаги блока, заданный блок (chunk steps, given chunk)

1. Если текущая выборка прервана, прервите эти шаги.

2. Если chunk не является объектом Uint8Array, прекратите текущую выборку и прервите эти шаги.

3. Пусть bs будет последовательностью байтов, представленной объектом Uint8Array.

4. В параллели:

4.1 Передайте bs. Каждый раз, когда передается один или несколько байтов, увеличивайте переданные байты body на количество переданных байтов и ставьте в очередь задачу выборки по request для обработки тела запроса для request.

Этот шаг блокируется до полной передачи bs.

4.2 Если текущая выборка не завершена, то поставьте задачу выборки в очередь на «request», чтобы выполнить цикл тела передачи с учетом «request», «body» и «reader».

близкие шаги (close steps)

1. Если текущая выборка прервана, прервите эти шаги.

2. Поставить задачу выборки в очередь на «request» для обработки конца тела запроса для «request».

шаги ошибки, учитывая e (error steps, given e)

1. Если текущая выборка прервана, прервите эти шаги.

2. Если e — это исключение DOMException «AbortError», завершите текущую выборку с установленным флагом прерывания.

3. В противном случае прекратите текущую выборку.

2. Прочтите фрагмент из потока body с помощью reader, которому задан readRequest.

 

Чтобы Добавить заголовок диапазона (add a range header) в запрос request, с целым числом first, и необязательное целое число last, выполните следующие действия:

1. Утверждено: last не указан или first меньше или равен last.
2. Пусть rangeValue будет `bytes=`.
3. Выполните сериализацию и изоморфное кодирование first и добавьте результат в rangeValue.
4. Добавьте 0x2D (-) к rangeValue.
5. Если last задан, то сериализуйте и изоморфно закодируйте его и добавьте результат в rangeValue.
6. Добавьте (`Range`, rangeValue) к списку заголовков запроса request.
Примечание

Заголовок диапазона обозначает включающий диапазон байтов. Заголовок диапазона, где first (первый) — 0 и last (последний) — 500, составляет 501 байт.

Примечание

Функции, объединяющие несколько ответов в один логический ресурс, исторически являются источником ошибок безопасности. Поищите проверку безопасности для функций, которые имеют дело с частичными ответами.

 

Чтобы Сериализовать URL-адрес ответа для создания отчетов (serialize a response URL for reporting) с учетом ответа response, выполните следующие действия:

1. Утверждено: список URL-адресов response не пустой.
2. Пусть url будет копией первого элемента списка URL-адресов response.
Примечание

Это не URL-адрес response, чтобы избежать утечки информации о целях перенаправления (см. Аналогичные соображения для отчетов CSP). [CSP]

3. Установите имя пользователя с указанным url и пустой строкой.
4. Установите пароль, с указанным url и пустой строкой.
5. Верните сериализацию url с установленным флагом исключения фрагмента.

 

Чтобы проверить, разрешены ли Учётные данные политики внедрения из разных источников (Cross-Origin-Embedder-Policy allows credentials), при запросе request выполните следующие действия:

1. Если режим request не "no-cors", верните true.
2. Если клиент request равен null, верните true.
3. Если значение политики встраивания политики контейнера клиента request не равно "credentialless", то верните true.
4. Если источник request совпадает с источником текущего URL-адреса запроса request, а флаг испорченного источника запроса request не установлен, тогда верните true.
5. Вернуть false.

2.2.6 Ответы

Результатом выборки является ответ (response). Ответ со временем развивается. То есть не все его поля доступны сразу.

Ответ имеет связанный тип (type): «basic«, «cors«, «default«, «error«, «opaque» или «opaqueredirect«. Если не указано иное, это «default«.

С ответом может быть связан флаг прерывания (aborted flag), который изначально не установлен.

Примечание

Это означает, что запрос был намеренно прерван разработчиком или конечным пользователем.

Ответ имеет связанный URL. Это указатель на последний URL-адрес ответа в списке URL-адресов ответа и null, если список URL-адресов ответа является пустым.

Ответ имеет связанный список URL-адресов (URL list)(список из нуля или более URL-адресов). Если не указано иное, это пустой список.

Примечание

За исключением последнего URL-адреса, если таковой имеется, список URL-адресов ответа не может быть доступен скрипту. Это нарушит обработку атомарного перенаправления HTTP.

Ответ имеет связанный статус (status), то есть состояние. Если не указано иное, это 200.

С ответом связано сообщение о состоянии (status message). Если не указано иное, это пустая последовательность байтов.

Примечание

Ответы по соединению HTTP/2 всегда будут иметь пустую последовательность байтов в качестве сообщения о состоянии, поскольку HTTP/2 их не поддерживает.

Ответ имеет связанный список заголовков (header list). Если не указано иное, он пуст.

У ответа есть связанное тело (body) (null или тело). Если не указано иное, оно null.

Примечание

Концепции источника и длины тела ответа сети всегда равны null.

Ответ имеет связанное состояние кеша (cache state) (пустая строка, «local» или «validated«). Если не указано иное, это пустая строка.

Примечание

Это предназначено исключительно для использования Service Workers (Работниками Службы) и Resource Timing (Ресурсы Сроки). [SW] [RESOURCE-TIMING]

ЭТО УДАЛЕНО!!! С ответом связан список CSP (CSP list), который представляет собой список объектов политики безопасности содержимого для ответа. Список пуст, если не указано иное. [CSP]

Ответ имеет связанный список имен заголовков, представленный CORS (CORS-exposed header-name list) (список из нуля или более имен заголовков). Список пуст, если не указано иное.

Примечание

Ответ обычно получает свой список имен заголовков, представленный CORS, путем извлечения значений заголовков из заголовка `Access-Control-Expose-Headers`. Этот список используется ответом, отфильтрованным CORS, для определения отображаемых заголовков.

Ответ имеет связанный флаг запрошенного диапазона (range-requested flag), который изначально не установлен.

Примечание

Это используется для предотвращения предоставления частичного ответа от более раннего запроса диапазона к API, который не выполнял запрос диапазона. Смотри раздел «Использование флага для подробного описания атаки».

В ответе есть связанные учетные данные, включающие запрос (request-includes-credentials — логическое значение), что изначально истинно (true).

С ответом связан флаг разрешения передачи по времени (timing allow passed flag), который изначально не установлен.

Примечание

Это используется для того, чтобы вызывающий объект выборки мог определить, разрешены ли конфиденциальные временные данные для извлекаемого ресурса, просмотрев флаг возвращенного ответа. Поскольку флаг ответа на переадресацию должен быть установлен, если он был установлен для предыдущих ответов в цепочке переадресации, это также отслеживается внутренне с помощью флага разрешения времени запроса с ошибкой.

С ответом связана информация о времени (timing info — null или информация о времени выборки), которая изначально равна null.

ЭТО УДАЛЕНО!!! Ответ может иметь связанный URL-адрес местоположения (null, ошибка или URL-адрес). Если не указано иное, в ответе отсутствует URL-адрес местоположения.

Примечание

Эта концепция используется для обработки перенаправления в Fetch и в алгоритме навигации HTML. Это гарантирует, что значение `Location` извлекается последовательно и только один раз. [HTML]

Ответ имеет связанную информацию о времени Работника Службы (service worker timing info — ноль или информация о времени работника службы), которая изначально равна нулю.

 

Ответ, тип которого — «error» и установлен флаг прерывания, известен как прерванная сетевая ошибка (aborted network error).

Ответ, тип которого — «error«, называется сетевой ошибкой (network error).

Сетевая ошибка — это ответ, статус которого всегда равен 0, статусное сообщение всегда представляет собой пустую последовательность байтов, список заголовков всегда пуст, а тело всегда равно null.

 

Отфильтрованный ответ (filtered response)- это ограниченное представление ответа, не являющегося сетевой ошибкой. Этот ответ называется внутренним ответом (internal response) связанным  отфильтрованным ответом.

Примечание

Алгоритм выборки возвращает такое представление, чтобы исключить случайную утечку информации из API. Если информация должна быть раскрыта по унаследованным причинам, например, для подачи данных изображения в декодер, может использоваться связанный внутренний ответ, который «доступен» только для внутренних алгоритмов спецификации и никогда не является отфильтрованным ответом.

Базовый отфильтрованный ответ (basic filtered response) — это отфильтрованный ответ, тип которого — «basic«, а список заголовков исключает любые заголовки из списка заголовков внутреннего ответа, имя которого является запрещенным именем заголовка ответа.

Отфильтрованный ответ CORS (CORS filtered response) — это отфильтрованный ответ, тип которого — «cors» и список заголовков исключает любые заголовки из списка заголовков внутреннего ответа, имя которых НЕ является CORS-безопасным именем заголовка ответа, указанным CORS-заданным списком имен заголовков внутреннего ответа.

Непрозрачный отфильтрованный ответ (opaque filtered response) — это отфильтрованный ответ, тип которого — «opaque«, список URL является пустым списком, статус — 0, статусное сообщение — это пустая последовательность байтов, список заголовков — пустой, а тело — null.

Отфильтрованный ответ с непрозрачным перенаправлением (opaque-redirect filtered response) — это отфильтрованный ответ, тип которого — «opaqueredirect«, статус является 0 (ноль), сообщение о состоянии — это пустая последовательность байтов, список заголовков пуст, а телоnull.

Примечание

Предоставление списка URL-адресов для фильтрованных ответов с непрозрачным перенаправлением безвредно, поскольку перенаправления не выполняются.

Другими словами, непрозрачный фильтрованный ответ и непрозрачный фильтрованный ответ с перенаправлением почти неотличимы от сетевой ошибки. При внедрении новых API не используйте внутренний ответ для алгоритмов внутренней спецификации, поскольку это приведет к утечке информации.

Это также означает, что API-интерфейсы JavaScript, такие как response.ok, будут возвращать довольно бесполезные результаты.

 

Чтобы клонировать (clone) ответ «response», выполните следующие действия:

1. Если response является отфильтрованным ответом, то возвращается новый идентичный отфильтрованный ответ, внутренний ответ которого является клоном внутреннего ответа response.
2. Пусть newResponse будет копией response, за исключением его тела.
3. Если тело response не null, тогда установите тело newResponse на результат клонирования тела response.
4. Верните newResponse.

 

Свежий ответ (fresh response) — это ответ, текущий возраст которого находится в пределах срока его свежести.

Ответ устаревший при повторной проверке (stale-while-revalidate response) — это ответ, который не является свежим ответом, и текущий возраст которого находится в пределах времени жизни устаревшего при повторной проверке.

Устаревший ответ (stale response) — это ответ, который не является свежим ответом или устаревшим при повторной проверке ответом.

 

URL-адрес местоположения (location URL) ответа response, заданный null или строка ASCII requestFragment, является значением, возвращаемым следующими шагами. Они возвращают null, ошибку или URL-адрес.

1. Если статус ответа response не является статусом переадресации, вернуть null.
2. Пусть location будет результатом извлечения значений списка заголовков из заданного "Location" и списка заголовков ответа response.
3. Если location является значением заголовка, установите location как результат синтаксического анализа местоположения location с URL-адресом ответа response.
Примечание

Если ответ response был создан с помощью конструктора Response, URL-адрес ответа response будет null, что означает, что местоположение location будет успешно проанализировано только в том случае, если это строка с абсолютным URL-адресом с фрагментом.

4. Если location является URL-адресом, фрагмент которого равен null, установите для фрагмента location значение requestFragment.
Примечание

Это гарантирует, что синтетические (действительно, все) ответы следуют модели обработки для перенаправлений, определенной HTTP. [HTTP-SEMANTICS]

5. Вернуть location.
Примечание

Алгоритм URL-адреса местоположения используется исключительно для обработки перенаправления в этом стандарте и в алгоритме навигации HTML, который обрабатывает перенаправления вручную. [HTML]

 

2.2.7 Разное

Потенциальный пункт назначения (potential destination) — это «fetch» или пункт назначения, который не является пустой строкой.

Чтобы перевести (translate) потенциальный пункт назначения potentialDestination, выполните следующие действия:

1. Если potentialDestination является "fetch", вернуть пустую строку.
2. Утверждено: potentialDestination - это пункт назначения.
3. Верните potentialDestination.

 

2.3 Записи аутентификации

Запись аутентификации (authentication entry) и запись аутентификации прокси (proxy-authentication entry) — это кортежи имени пользователя, пароля и области, используемые для аутентификации HTTP и аутентификации прокси-сервера HTTP и связанные с одним или несколькими запросами.

Пользовательские агенты должны позволять очищать и то, и другое вместе с файлами cookie HTTP и аналогичными функциями отслеживания.

Дальнейшие подробности определяются в HTTP. [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH]

 

2.4 Группы Выборки

Каждый объект настроек среды имеет связанную группу выборки.

Группа выборки содержит упорядоченный список записей выборки (fetch records).

У записи выборки есть связанный запрос (request).

Запись выборки имеет связанную выборку (fetch) (алгоритм выборки или null).

 

Когда группа выборки завершается, для каждой связанной записи выборки, для которой не установлен флаг выполнения запроса или флаг поддержки активности, завершается выборка записи выборки.

 

2.5 Разрешение доменов

Чтобы разрешить домен (resolve a domain), учитывая ключ раздела сети «key» и домен «domain»:

1. Если domain является хостом, публичный суффикс которого - «localhost», вернуть «:: 1, 127.0.0.1».
2. Выполните операцию, определяемую реализацией, чтобы превратить domain в набор из одного или нескольких IP-адресов. Если эта операция завершится успешно, верните набор IP-адресов.
3. Вернуть неудачу.

Результаты разрешения домена могут быть кэшированы. Если они кэшируются, key следует использовать как часть ключа кеша.

Примечание

Обычно эта операция включает DNS, и поэтому кэширование может происходить на DNS-серверах без учета ключа key. В зависимости от реализации также может оказаться невозможным локальный учет ключа key. [RFC1035]

Порядок IP-адресов, который может быть разрешён доменом, может различаться между вызовами.

Детали (кроме ключа кеша) не привязаны, поскольку они не имеют отношения к системе, установленной стандартом Fetch Standard. Другие документы не должны основываться на этом примитиве без тщательного обсуждения с сообществом Fetch Standard.

Чтобы разрешить источник (resolve an origin), учитывая ключ раздела сети «key» и источник происхождения «origin»:

1. Если хост источника «origin» является IP-адресом, верните «хост источника «origin»».
2. Вернуть результат выполнения разрешения домена с заданным ключом «key» и хостом источника «origin».
Примечание

Применяется то же предостережение. Не делайте этого, без предварительно обдуманного обсуждения с сообществом Fetch Standard.

 

2.6 Соединения

У пользовательского агента есть связанный пул соединений (connection pool). Пул соединений состоит из нуля или более соединений (connections). Каждое соединение идентифицируется ключом (keyключ раздела сети), источником (origin) и учетными данными (credentials — логическим значением).

Каждое соединение имеет связанную информацию о времени (timing infoинформация о времени подключения).

Информация о времени соединения (connection timing info) — это структура, используемая для хранения информации о времени, относящейся к процессу получения соединения. В нем есть следующие элементы:

domain lookup start time (default 0)
domain lookup end time (default 0)
connection start time (default 0)
connection end time (default 0)
secure connection start time (default 0)

DOMHighResTimeStamp

ALPN negotiated protocol (по умолчанию пустая последовательность байтов)

Последовательность байтов

Чтобы зафиксировать и приблизить информацию о времени соединения (clamp and coarsen connection timing info), учитывая информацию о времени соединения timingInfo, значение DOMHighResTimeStamp defaultStartTime и логическое значение crossOriginIsolatedCapability, выполните следующие действия:

1. Если время начала соединения timingInfo меньше, чем defaultStartTime, вернуть новую информация о времени соединения, время начала поиска домена которой - defaultStartTime, время окончания поиска домена - defaultStartTime, время начала соединения - defaultStartTime, время окончания соединения - defaultStartTime, время начала безопасного соединения - defaultStartTime , а согласованный протокол ALPN - это согласованный протокол ALPN для timingInfo.

2. Вернуть новую информацию о времени соединения, время начала поиска домена которой является результатом грубого времени с учетом времени начала поиска домена timingInfo и crossOriginIsolatedCapability, время окончания поиска домена является результатом грубого времени с учетом времени окончания поиска домена timingInfo и crossOriginIsolatedCapability, время начала подключения является результатом грубого времени с учетом времени начала соединения timingInfo и crossOriginIsolatedCapability, время окончания соединения является результатом грубого времени с учетом времени окончания соединения timingInfo и crossOriginIsolatedCapability, время начала безопасного соединения является результатом грубого времени с учетом времени окончания соединения timingInfo и crossOriginIsolatedCapability, и согласованного ALPN Протокол - это согласованный протокол ALPN от timingInfo.

 

Новая настройка подключения (new connection setting) — «нет», «да» или «да и выделено» («no«, «yes«, или «yes-and-dedicated«).

 

Чтобы получить соединение (obtain a connection), учитывая ключ раздела сети «key», URL-адрес «url», логический тип учетных данных «credentials», необязательную настройку нового соединения «new» (по умолчанию «no») и необязательное логическое значение http3Only (по умолчанию false), выполните следующие действия:

1. Если new является «no», то:
   1. Пусть connections будут набором соединений в пуле соединений пользовательского агента, ключ которого является key, источник является источником url, а учетные данные являются credentials.
   2. Если connections не пустые и http3Only имеет значение false, вернуть одно из connections.
   3. Если в connections есть соединение HTTP/3, верните это соединение.
2. Пусть proxies будут результатом поиска прокси для url способом, определяемым реализацией. Если прокси нет, пусть proxies будут «"DIRECT"».
Примечание

Именно здесь вступают в игру нестандартные технологии, такие как протокол автоматического обнаружения веб-прокси (WPAD) и автоконфигурация прокси (PAC). Значение «DIRECT» означает, что прокси-сервер для этого конкретного url не используется.

3. Пусть timingInfo будет новой информацией о времени соединения.
4. Для каждого proxy из proxies:
   1. Установите времени начала поиска домена timingInfo на время начала небезопасного общего доступа.
   2. Пусть hosts будут «хостом origin».
   3. Если proxy является «DIRECT», то установите для hosts результат выполнения разрешения источника с заданным key и источником url.
   4. Если hosts вышли из строя, продолжайте.
   5. Установите время окончания поиска домена timingInfo на небезопасное общее текущее время.
   6. Пусть connection будет результатом выполнения этого шага: запустить создание соединения с заданным key, источником url, credentials, proxy, хостом, определяемым реализацией из hosts, timingInfo и http3Only определенное реализацией количество раз, параллельно друг другу, и дождитесь хотя бы 1, чтобы вернуть значение. В зависимости от реализации выберите значение для возврата из возвращаемых значений и верните его. Любые другие возвращаемые значения, являющиеся соединениями, могут быть закрыты.
Примечание

По сути, это позволяет реализации выбирать один или несколько IP-адресов из возвращаемого значения для разрешения домена (при условии, что прокси-сервер «DIRECT») и гонять их друг против друга, отдавать предпочтение IPv6-адресам, повторять попытки в случае тайм-аута и т. д.

   7. Если connection не удалось, продолжайте.
   8. Если new не является "yes-and-dedicated", тогда добавьте connection в пул соединений пользовательского агента.
   9. Вернуть connection.
5. Вернуть неудачу.
Примечание

Это намеренно немного расплывчато, поскольку есть много нюансов в управлении подключением, которые лучше оставить на усмотрение разработчиков. Описание этого помогает объяснить функцию <link rel = preconnect> и четко указывает, что соединения устанавливаются с использованием учетных данных. В последнем уточняется, что, например, идентификаторы сеанса TLS не используются повторно в соединениях, учетные данные которых ложны, с соединениями, учетные данные которых верны.

 

Чтобы создать соединение (create a connection), учитывая ключ раздела сети key, источник происхождения origin, логические учетные данные credentials, строковый proxy, хост host, информацию о времени подключения timingInfo и логическое значение http3Only, выполните следующие действия:

1. Установите времени начала соединения timingInfo на небезопасное общее текущее время.
2. Пусть connection будет новым соединением, ключ которого является key, источник - origin, учетные данные - credentials, а информация о времени - timingInfo. Запишите информацию о времени соединения для данного connection и используйте connection для установки HTTP-соединения с host с учетом proxy и origin. [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH] [TLS]
Если http3Only истинно (является true), установите соединение HTTP/3. [HTTP3]
При установке соединения HTTP/3 включите SETTINGS_ENABLE_WEBTRANSPORT со значением 1 и H3_DATAGRAM со значением 1 в начальный кадр SETTINGS. [WEBTRANSPORT-HTTP3] [HTTP3-DATAGRAM]
Если credentials ложны (являются false), не отправляйте сертификат клиента TLS.
Если установить соединение не удалось (например, ошибка TCP или TLS), вернуть ошибку.
3. Установите согласованный протокол ALPN для timingInfo в соответствии с идентификатором протокола ALPN connection со следующими оговорками: [RFC7301]
   Если при настройке прокси-сервера установлено туннельное соединение, то это должен быть идентификатор протокола ALPN туннелируемого протокола, в противном случае это должен быть идентификатор протокола ALPN первого перехода к прокси.
   В случае, если пользовательский агент использует экспериментальный, незарегистрированный протокол, пользовательский агент должен использовать используемый идентификатор протокола ALPN, если таковой имеется. Если ALPN не использовался для согласования протокола, пользовательский агент может использовать другую описательную строку.
Примечание

Согласованный протокол ALPN от timingInfo предназначен для идентификации используемого сетевого протокола независимо от того, как он был фактически согласован; то есть, даже если ALPN не используется для согласования сетевого протокола, это идентификаторы протокола ALPN, которые указывают на используемый протокол.

4. Вернуть connection.

 

Чтобы записывать информацию о времени соединения (record connection timing info) для данного соединения connection, пусть timingInfo будет информацией о времени connection, и соблюдайте следующие требования:

Время окончания соединения timingInfo должно быть небезопасным общим текущим временем сразу после установления соединения с сервером или прокси, как показано ниже:
   Возвращаемое время должно включать временной интервал для установления транспортного соединения, а также другие временные интервалы, такие как аутентификация SOCKS. Он должен включать временной интервал, достаточный для завершения подтверждения TLS для запроса ресурса.
   Если пользовательский агент использовал TLS False Start для этого соединения, этот интервал не должен включать время, необходимое для получения сообщения Finished сервера. [RFC7918]
   Если пользовательский агент отправляет запрос с ранними данными, не дожидаясь завершения полного установления связи, этот интервал не должен включать время, необходимое для получения сообщения ServerHello от сервера. [RFC8470]
   Если пользовательский агент ожидает завершения полного рукопожатия для отправки запроса, этот интервал включает полное рукопожатие TLS, даже если другие запросы были отправлены с использованием ранних данных при connection.
Пример

Предположим, пользовательский агент устанавливает соединение HTTP/2 через TLS 1.3 для отправки запроса GET и запроса POST. Он отправляет ClientHello в момент t1, а затем отправляет запрос GET с ранними данными. Запрос POST небезопасен ([HTTP-SEMANTICS], раздел 4.2.1), поэтому пользовательский агент ожидает завершения подтверждения в момент времени t2 перед его отправкой. Хотя оба запроса использовали одно и то же соединение, запрос GET сообщает время окончания соединения t1, а запрос POST сообщает t2.

Если используется безопасный транспорт, время начала безопасного соединения timerInfo должно быть результатом вызова небезопасного общего текущего времени непосредственно перед запуском процесса подтверждения для безопасного соединения. [TLS]
Примечание

Алгоритм фиксации и грубой информации о времени соединения гарантирует, что детали повторно используемых соединений не будут раскрыты, а значения времени будут огрублены.

 

 

2.7. Ключи сетевых разделов

Ключ раздела сети (network partition key) — это кортеж, состоящий из сайта и нулевого или определяемого реализацией значения.

Чтобы определить ключ раздела сети по запросу (determine the network partition key), с учетом параметров объекта среды settings, выполните следующие действия:

1. Пусть topLevelOrigin будет источником верхнего уровня settings.
2. Если topLevelOrigin имеет значение null, установите для topLevelOrigin значение источника URL создания верхнего уровня в настройках settings.
3. Утверждено: topLevelOrigin - это источник.
4. Пусть topLevelSite будет результатом получения сайта с учетом topLevelOrigin.
5. Пусть secondKey имеет значение null или значение, определяемое реализацией.
   Второй ключ намеренно немного расплывчатый, поскольку более тонкие моменты все еще развиваются. Смотри Issue #1035.
6. Вернуть (topLevelSite, secondKey).

 

Чтобы определить ключ раздела сети (determine the network partition key) по запросу request, выполните следующие действия:

1. Если зарезервированный клиент запроса request не равен нулю, вернуть результат определения ключа раздела сети для данного зарезервированного клиента запроса request.
2. Если клиент запроса request не равен нулю, вернуть результат определения ключа раздела сети для данного клиента запроса request.
3. Вернуть null.

 

2.8 Разделы кеша HTTP

Чтобы определить раздел HTTP-кеша (determine the HTTP cache partition) по данному запросу request, выполните следующие действия:

1. Пусть «key» будет результатом определения ключа раздела сети по «request».
2. Если «key» равен null, вернуть null.
3. Вернуть уникальный HTTP-кеш, связанный с «key». [HTTP-CACHING]

 

2.9 Блокировка портов

Чтобы определить, следует ли блокировать получение запроса request из-за плохого порта, выполните следующие действия:

1. Пусть url будет текущим URL запроса.

2. Пусть scheme будет схемой url.

3. Пусть port будет портом адреса url.

4. Если scheme — «ftp», а порт — 20 или 21, то возврат разрешен.

5. В противном случае, если scheme является сетевой схемой, а port — плохим портом, возврат будет заблокирован.

6. Возврат разрешен.

 

Порт считается плохим портом (bad port), если он указан в первом столбце следующей таблицы.

Порт Типичный сервис
Port Typical service
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
77 priv-rjs
79 finger
87 ttylink
95 supdup
101 hostriame
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 loc-srv / epmap
139 netbios
143 imap2
179 bgp
389 ldap
427 afp (alternate)
465 smtp (alternate)
512 print / exec
513 login
514 shell
515 printer
526 tempo
530 courier
531 chat
532 netnews
540 uucp
548 afp
556 remotefs
563 nntp+ssl
587 smtp (outgoing)
601 syslog-conn
636 ldap+ssl
993 ldap+ssl
995 pop3+ssl
2049 nfs
3659 apple-sasl
4045 lockd
6000 x11
6665 irc (alternate)
6666 irc (alternate)
6667 irc (default)
6668 irc (alternate)
6669 irc (alternate)
6697 irc+tls

 

2.9 Должен ли ответ response на запрос request быть заблокирован из-за его MIME-типа?

Выполните следующие шаги:

1. Пусть «mimeType» будет результатом извлечения типа MIME из списка заголовков ответа response.

2. Если «mimeType» даёт сбой, возврат разрешен.

3. Пусть destination будет пунктом назначения запроса request.

4. Если destination похож на сценарий и выполняется одно из следующих условий, возврат заблокирован:

Сущность «mimeType» начинается с «audio/», «image/» или «video/».

Сущность «mimeType» — это «text/csv».

5. Вернуть разрешен.

 

3. Расширения HTTP

3.1 Заголовок «Origin«

Заголовок запроса `Origin` указывает, откуда происходит выборка.

Заголовок `Origin` — это версия заголовка`Referer` [sic], которая не показывает путь. Он используется для всех HTTP-выборок, чей ответ на запрос поврежден «cors», а также для тех, у которых метод запроса не является ни GET, ни HEAD. Из-за ограничений совместимости он не входит во все выборки.

Его значение ABNF:

Origin = origin-or-null

origin-or-null = origin / %s»null» ; case-sensitive
origin = scheme «://» host [ «:» port ]

Он заменяет заголовок `Origin`.

 

Чтобы добавить заголовок запроса `Origin`, учитывая запрос request, выполните следующие действия:

1. Пусть «serializedOrigin» будет результатом побайтной сериализации источника запроса с помощью «request«.

2. Если повреждение ответа на «request» — «cors» или режим «request» — «websocket», добавьте в список заголовков «request» — `Origin`/serializedOrigin.

3. В противном случае, если метод запроса не является ни GET, ни HEAD, тогда:

3.1 Переключите политику реферера запроса «request«:

«no-referrer«

Установите serializedOrigin в `null`.

«no-referrer-when-downgrade«

«strict-origin«

«strict-origin-when-cross-origin«

Если источником запроса «request» является источник кортежа, его схема «scheme» — «https», а схема «scheme» текущего URL-адреса запроса «request» — не «https», тогда установите для «serializedOrigin» значение «null».

«same-origin«

Если источник запроса «request» не совпадает с источником текущего URL-адреса запроса «request«, то установите для «serializedOrigin» значение `null`.

В противном случае

Ничего не делать.

3.2 Добавьте `Origin`/serializedOrigin в список заголовков запроса «request«.

Политика реферера запроса учитывается для всех выборок, в которых сборщик явно не согласился поделиться своим источником с сервером, например, с использованием протокола CORS.

 

3.2 Протокол CORS

Протокол CORS существует, чтобы разрешить обмен ответами из разных источников и более гибкую выборку, чем это возможно с помощью элемента формы HTML <form>. Он расположен поверх HTTP и позволяет в ответах объявлять, что они могут быть переданы другим источникам.

Это должен быть механизм согласия, чтобы предотвратить утечку данных из ответов за брандмауэром (интрасети). Кроме того, для запросов, включающих учетные данные, необходимо дать согласие, чтобы предотвратить утечку потенциально конфиденциальных данных.

В этом разделе поясняется протокол CORS для разработчиков серверов. Требования к пользовательским агентам являются частью алгоритма выборки, за исключением нового синтаксиса заголовка HTTP.

 

3.2.1 Общие положения

Протокол CORS состоит из набора заголовков, которые указывают, может ли ответ быть общим для разных источников.

Для запросов, которые более сложны, чем это возможно с помощью элемента формы HTML <form>, выполняется предварительный запрос CORS, чтобы гарантировать, что текущий URL-адрес запроса поддерживает протокол CORS.

 

3.2.2 HTTP-запросы

Запрос CORS (CORS request) — это HTTP-запрос, который включает заголовок `Origin`. Он не может быть надежно идентифицирован как участвующий в протоколе CORS, поскольку заголовок `Origin` также включается во все запросы, метод которых не является ни GET, ни HEAD.

Запрос CORS-preflight (CORS-preflight request) — это запрос CORS, который проверяет, понятен ли протокол CORS. Он использует `OPTIONS` в качестве метода и включает следующие заголовки:

`Access-Control-Request-Method`

Указывает, какой метод может использовать будущий запрос CORS к тому же ресурсу.

`Access-Control-Request-Headers`

Указывает, какие заголовки может использовать будущий запрос CORS к тому же ресурсу.

 

3.2.3 HTTP-ответы

HTTP-ответ на запрос CORS может включать следующие заголовки:

`Access-Control-Allow-Origin`

Указывает, можно ли поделиться ответом, возвращая буквальное значение заголовка запроса `Origin` (которое может быть null) или `*` в ответе.

`Access-Control-Allow-Credentials`

Указывает, можно ли предоставить общий доступ к ответу, если режим учетных данных запроса — «include».

Для запроса CORS-preflight режим учетных данных всегда «omit», но для любых последующих запросов CORS он может отсутствовать. Следовательно, поддержка также должна быть указана как часть HTTP-ответа на запрос CORS-preflight.

 

HTTP-ответ на запрос CORS-preflight может включать следующие заголовки:

`Access-Control-Allow-Methods`

Указывает, какие методы поддерживаются URL-адресом ответа для целей протокола CORS.

Заголовок `Allow` не имеет отношения к протоколу CORS.

`Access-Control-Allow-Headers`

Указывает, какие заголовки поддерживаются URL-адресом ответа для целей протокола CORS.

`Access-Control-Max-Age`

Указывает количество секунд (по умолчанию 5), в течение которых может быть кэширована информация, предоставленная заголовками `Access-Control-Allow-Methods` и `Access-Control-Allow-Headers`.

 

HTTP-ответ на запрос CORS, который не является запросом CORS-preflight, также может включать следующий заголовок:

`Access-Control-Expose-Headers`

Указывает, какие заголовки могут быть показаны как часть ответа, перечисляя их имена.

 

В случае, если сервер не желает участвовать в протоколе CORS, его HTTP-ответ на запрос CORS или запрос CORS-preflight не должен включать какие-либо из вышеуказанных заголовков. Серверу рекомендуется использовать статус 403 в таких HTTP-ответах.

 

3.2.4 Синтаксис нового заголовка HTTP

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` значение `*` считается подстановочным знаком для запросов без учетных данных. Для таких запросов нет способа сопоставить только имя заголовка или метод, который равен `*`.

 

3.2.5 Протокол CORS и учетные данные

Когда режим учетных данных запроса установлен на «include«, он влияет на работу протокола CORS, кроме включения учетных данных в выборку.

 

Пример

Раньше XMLHttpRequest можно было использовать для установки режима учетных данных запроса на «include»:

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

В настоящее время достаточно

fetch("./", { credentials:"include" }).then(/* … */)

.

 

Режим учетных данных запроса не обязательно доступен на сервере; только при наличии учетных данных для запроса его можно наблюдать на основании включенных учетных данных. Обратите внимание, что даже в этом случае запрос CORS-preflight никогда не включает учетные данные.

Поэтому разработчику сервера необходимо решить, можно ли совместно использовать ответы, «испорченные» учетными данными. А также необходимо решить, могут ли запросы, требующие предварительного запроса CORS, включать учетные данные. Вообще говоря, как совместное использование ответов, так и разрешение запросов с учетными данными довольно небезопасно, и нужно проявлять особую осторожность, чтобы избежать запутанной проблемы заместителя.

Для обмена ответами с учетными данными важны заголовки `Access-Control-Allow-Origin` и `Access-Control-Allow-Credentials`. Следующая таблица служит для иллюстрации различных допустимых и незаконных комбинаций для запроса на https://rabbit.invalid/:

Режим учетных данных запроса `Access-Control-Allow-Origin` `Access-Control-Allow-Credentials` Общий? Примечания
«omit» `*` Omitted Да
«omit» `*` `true` Да Если режим учетных данных не включен, то `Access-Control-Allow-Credentials` игнорируется.
«omit» `https://rabbit.invalid/` Omitted Нет У сериализованного источника нет завершающей косой черты.
«omit» `https://rabbit.invalid/` Omitted Да
«include» `*` `true` Нет Если режим учетных данных — «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 могут использовать только `*` в качестве значения, если режим учетных данных запроса не «include».

 

3.2.6 Примеры

Пример

Сценарий на «https://foo.invalid/» хочет получить некоторые данные с «https://bar.invalid/». (Ни учетные данные, ни доступ к заголовку ответа не имеют значения.)

var url = "https://bar.invalid/api?key=730d67a37d7f3d802e96396d00280768773813fbe726d116944d814422fc1a45&data=about:unicorn";
fetch(url).then(success, failure)

Это будет использовать протокол CORS, хотя он полностью прозрачен для разработчика из «foo.invalid». В рамках протокола CORS пользовательский агент будет включать в запрос заголовок `Origin`:

Origin: https://foo.invalid

После получения ответа от «bar.invalid» пользовательский агент проверит заголовок ответа Access-Control-Allow-Origin. Если его значение равно «https://foo.invalid» или *, пользовательский агент вызовет успешный обратный вызов «success». Если он имеет любое другое значение или отсутствует, пользовательский агент вызовет обратный вызов ошибки «failure».

 

Пример

Разработчик «foo.invalid» вернулся и теперь хочет получить некоторые данные из «bar.invalid», а также получить доступ к заголовку ответа.

fetch(url).then(response => {
var hsts = response.headers.get("strict-transport-security"),
csp = response.headers.get("content-security-policy")
log(hsts, csp)
})

«bar.invalid» предоставляет правильный заголовок ответа Access-Control-Allow-Origin в соответствии с предыдущим примером. Значения hsts и csp будут зависеть от заголовка ответа Access-Control-Expose-Headers. Например, если ответ содержал следующие заголовки

Content-Security-Policy: default-src 'self'
Strict-Transport-Security: max-age=31536000; includeSubdomains; preload
Access-Control-Expose-Headers: Content-Security-Policy

тогда «hsts» будет иметь значение null, а «csp» — «default-src ‘self’», даже если ответ включал оба заголовка. Это связано с тем, что «bar.invalid» необходимо явно предоставить общий доступ к каждому заголовку, указав их имена в заголовке ответа Access-Control-Expose-Headers.

В качестве альтернативы, если «bar.invalid» хочет поделиться всеми своими заголовками ответов, для запросов, не содержащих учетные данные, он может использовать `*` в качестве значения для заголовка ответа `Access-Control-Expose-Headers`. Если бы запрос включал учетные данные, имена заголовков ответа должны были бы быть указаны явно и `*` нельзя было использовать.

 

Пример

Разработчик «foo.invalid» возвращается, теперь извлекая некоторые данные из «bar.invalid», включая учетные данные. На этот раз протокол CORS больше не прозрачен для разработчика, поскольку учетные данные требуют явного согласия:

fetch(url, { credentials:"include" }).then(success, failure)

Это также делает любые заголовки ответов `Set-Cookie` «bar.invalid» полностью функциональными (в противном случае они игнорируются).

Пользовательский агент обязательно включит в запрос все соответствующие учетные данные. Это также установит более строгие требования к ответу. Мало того, что «bar.invalid» необходимо указать «https://foo.invalid» в качестве значения для заголовка `Access-Control-Allow-Origin` (`*` не допускается, когда задействованы учетные данные), заголовок`Access-Control-Allow-Credentials` также должен присутствовать:

Access-Control-Allow-Origin: https://foo.invalid
Access-Control-Allow-Credentials: true

Если ответ не включает эти два заголовка с этими значениями, будет вызван обратный вызов ошибки «failure«. Однако любые заголовки ответа `Set-Cookie` будут соблюдаться.

 

3.2.7 Исключения протокола CORS

Спецификации допускают ограниченные исключения из списка надежных отправителей CORS для значений заголовка `Content-Type`, не включенных в список надежных отправителей. Эти исключения сделаны для запросов, которые могут быть инициированы веб-контентом, но чьи заголовки и тела могут лишь минимально контролироваться веб-контентом. Следовательно, серверы должны ожидать, что веб-контент из разных источников будет разрешен запускать запросы без предварительной проверки со следующими значениями заголовка `Content-Type`, не включенными в безопасный список:

  • `application/csp-report` [CSP]
  • `application/expect-ct-report+json` [EXPECT-CT]
  • `application/xss-auditor-report`
  • `application/ocsp-request` [OCSP]

Спецификации не должны вводить новые исключения и должны делать это только с тщательным учетом последствий для безопасности. Новые исключения могут быть предложены путем подачи заявки.

 

3.3 Заголовок «Content-Length«

Заголовок `Content-Length` в значительной степени определен в HTTP. Его модель обработки определяется здесь, поскольку модель, определенная в HTTP, несовместима с веб-контентом. [HTTP]

Чтобы извлечь длину (extract a length) из списка заголовков headers, выполните следующие действия:

1. Пусть значения values будут результатом получения, декодирования и разделения `Content-Length` из заголовков headers.
2. Если значения values являются null, вернуть null.
3. Допустим, что candidateValue равно null.
4. Для каждого значения value из значений values:
   4.1 Если keywordValue имеет значение null, установите для candidateValue значение value.
   4.2 В противном случае, если value не является candidateValue, вернуть ошибку.
5. Если candidateValue является пустой строкой или имеет кодовую точку, которая не является цифрой ASCII, тогда верните null.
6. Вернуть candidateValue, интерпретируемое как десятичное число.

 

3.4 Заголовок «Content-Type«

Заголовок `Content-Type` в значительной степени определен в HTTP. Его модель обработки определяется здесь, поскольку ABNF, определенный в HTTP, несовместим с веб-контентом. [HTTP]

Чтобы извлечь тип MIME из списка заголовков «headers» , выполните следующие действия:

1. Пусть кодировка charset будет null.

2. Пусть сущность essence будет null.

3. Пусть mimeType будет null.

4. Пусть значения values будут результатом получения, декодирования и разделения Content-Type из заголовков.

5. Если значение values равно null, вернуть ошибку.

6. Для каждого value из values:

6.1 Пусть temporaryMimeType будет результатом синтаксического анализа значения value.

6.2 Если temporaryMimeType является ошибкой или его сущность «*/*», продолжайте.

6.3 Задайте для mimeType значение temporaryMimeType.

6.4 Если сущность mimeType не является сущностью essence, тогда:

6.4.1 Установите charset значение null.

6.4.2 Если параметры mimeType [«charset»] существуют, установите для charset значение mimeType параметры [«charset»].

6.4.3 Установите сущность essence на сущность mimeTypes.

6.5 В противном случае, если параметры mimeType [«charset»] не существуют, а charset не равен null, установите для параметров mimeType [«charset»] значение charset.

7. Если mimeType имеет значение null, вернуть ошибку.

8. Вернуть mimeType

 

ПРЕДУПРЕЖДЕНИЕ! 

Когда извлечение типа MIME возвращает ошибку или тип MIME, сущность которого неверна для данного формата, рассматривайте это как фатальную ошибку. Существующие функции веб-платформы не всегда следовали этой схеме, которая на протяжении многих лет была основным источником уязвимостей в этих функциях. Напротив, параметры типа MIME обычно можно игнорировать.

 

Пример

Вот как на практике извлечь функции типа MIME:

Заголовки (как в сети) Вывод (сериализованный)
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
text/html;x=y;charset=gbk
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: */*
text/html
Content-Type: text/html
Content-Type:
text/html

 

 

3.4 Заголовок «X-Content-Type-Options«

Заголовок ответа `X-Content-Type-Options` может использоваться для того, чтобы требовать проверки заголовка ответа `Content-Type` относительно адресата запроса.

Чтобы определить nosniff по заданному списку заголовков «list», выполните следующие действия:

1. Пусть «values» будут результатом получения, декодирования и разделения `X-Content-Type-Options` из «list».

2. Если «values» равно null, вернуть false.

3. Если values[0] не учитывает регистр ASCII для «nosniff», вернуть true.

4. Вернуть false.

 

Веб-разработчики и средства проверки соответствия должны использовать следующее значение ABNF для `X-Content-Type-Options`:

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

 

3.4.1 Должен ли ответ response на запрос request быть заблокирован из-за nosniff?

Выполните следующие шаги:

1. Если определение nosniff в списке заголовков ответа response ложно, возврат разрешен.

2. Пусть mimeType будет результатом извлечения типа MIME из списка заголовков ответа response.

3. Пусть пункт назначения destination будет пунктом назначения запроса request.

4. Если пункт назначения destination подобен сценарию, а mimeType является ошибкой или не является типом MIME JavaScript, то возврат заблокирован.

5. Если пункт назначения destination — «style«, а mimeType — сбой или его суть не «text/css«, то возврат заблокирован.

6. Возврат разрешен.

Только те места назначения запросов, которые похожи на скрипты или являются «style«, рассматриваются как любые относящиеся к ним эксплойты. Кроме того, «image» несовместим с развернутым контентом.

 

3.5 CORB — Cross-origin read blocking

Блокировка чтения из разных источников (Cross-origin read blocking), более известная как CORB, представляет собой алгоритм, который выявляет сомнительные выборки ресурсов из разных источников (например, выборки, которые в любом случае не удались бы, как попытки отрисовки JSON внутри элемента img) и блокирует их до того, как они достигнут веб-страницы. CORB снижает риск утечки конфиденциальных данных, удерживая их подальше от веб-страниц с разными источниками.

Тип MIME с защитой CORB (CORB-protected MIME type) — это тип MIME HTML, тип MIME JSON или тип MIME XML, за исключением «image/svg+xml».

Даже без CORB доступ к содержимому ресурсов с перекрестным источником с типами MIME, защищенными CORB, либо управляется протоколом CORS (например, в случае XMLHttpRequest), либо не наблюдается (например, в случае эхо-запросов или отчетов CSP, которые игнорируют ответ ) или приведет к ошибке (например, при неудачной попытке декодирования HTML-документа, встроенного в элемент img как изображение). Это означает, что CORB может блокировать ресурсы MIME-типов, защищенные CORB, без нарушения работы веб-страниц.

 

Чтобы выполнить проверку CORB (CORB check), учитывая запрос request и ответ response, выполните следующие действия:

1. Если инициатором запроса request является»download«, возврат разрешен.

Если мы переделаем загрузку как навигацию, этот шаг можно удалить.

2. Если схема текущего URL-адреса запроса request не является схемой HTTP (S), возврат разрешен.

3. Пусть mimeType будет результатом извлечения типа MIME из списка заголовков ответа response.

4. Если mimeType получил сбой, возврат разрешен.

5. Если статус ответа response — 206 и mimeType — это MIME-тип, защищенный CORB, то возврат заблокирован.

6. Если определение nosniff с помощью списка заголовков ответа response истинно, а mimeType является типом MIME, защищенным CORB, или его сущность — «text/plain», то возврат заблокирован.

CORB защищает только ответы «text/plain» с заголовком `»X-Content-Type-Options: nosniff»`. К сожалению, защита таких ответов без этого заголовка, когда их статус 206, приведет к поломке слишком многих существующих видеоответов, имеющих «text/plain» тип MIME.

7. Возврат разрешен.

 

3.6 Заголовок «Cross-Origin-Resource-Policy«

Заголовок ответа `Cross-Origin-Resource-Policy` может использоваться для того, чтобы требовать проверки источника текущего URL-адреса запроса относительно источника запроса, когда режим запроса — «no-cors«.

Его значение ABNF:

Cross-Origin-Resource-Policy = %s"same-origin" / %s"same-site" / %s"cross-origin" ; case-sensitive

Чтобы выполнить проверку политики ресурсов для разных источников (cross-origin resource policy check), учитывая источник «origin», объект настроек среды «settingsObject», ответ «response» и необязательное логическое значение «forNavigation», выполните следующие действия:

1. Установите для «forNavigation» значение false, если оно не задано.

2. Пусть embedderPolicy будет политикой внедрения settingsObject.

3. Если внутренняя проверка политики ресурсов с разными источниками с помощью «origin», «unsafe-none», «response» и «forNavigation» возвращает значение «заблокировано», тогда возврат будет заблокирован.

Этот шаг необходим, потому что мы не хотим сообщать о нарушениях, не связанных с Политикой встраивания Cross-Origin, ниже.

4. Если внутренняя проверка политики ресурсов для разных источников с помощью «origin», значение отчета embedderPolicy, «response» и «forNavigation» возвращает значение «заблокировано» (blocked), то поставьте в очередь отчет о нарушении CORP политики внедрения cross-origin с «response», «settingsObject», и true.

5. Если внутренняя проверка политики ресурсов с разными источниками с помощью origin, значения embedderPolicy, ответа и forNavigation возвращает разрешено (allowed), то возврат разрешен.

6. Поставить в очередь отчет о нарушении CORP политики внедрения кросс-происхождения с «response», «settingsObject» и false.

7. Возврат заблокирован.

Только алгоритм навигации HTML использует эту проверку, когда для forNavigation установлено значение true, и это всегда для вложенных переходов. В противном случае ответ является либо внутренним ответом непрозрачного отфильтрованного ответа, либо ответом, который будет внутренним ответом непрозрачного отфильтрованного ответа. [HTML]

Чтобы выполнить внутреннюю проверку политики ресурсов между источниками, учитывая источник «origin», значение политики внедрения «embedderPolicyValue», ответ «response» и логическое значение «forNavigation», выполните следующие действия:

1. Если forNavigation истинно, а embedderPolicyValue — «unsafe-none«, то возврат разрешен.

2. Пусть «policy» будет результатом получения «Cross-Origin-Resource-Policy» из списка заголовков ответа response.

Это означает, что `»Cross-Origin-Resource-Policy: same-site, same-origin»` заканчивается так, как разрешено ниже, так как никогда не будет соответствовать чему-либо, пока embedderPolicyValue имеет значение «unsafe-none». Два или более заголовка «Cross-Origin-Resource-Policy» будут иметь одинаковый эффект.

3. Если «policy» не является ни «same-origin», «same-site», ни «cross-origin», тогда установите для «policy» значение null.

4. Если «policy» имеет значение «null», а «embedderPolicyValue» равно «require-corp», тогда установите для «policy» значение «same-origin».

5. Переключите политику «policy»:

null

`cross-origin`

Возврат разрешен.

`same-origin`

Если «origin» совпадает с источником URL-адреса ответа response, возврат разрешен.

В противном случае возврат заблокирован.

`same-site`

Если верно следующее

origin — это тот же сайт без схемы, что и исходный URL-адрес ответа

Схема origin — https или схема URL ответа — не https

тогда возврат разрешен.

В противном случае возврат заблокирован.

`»Cross-Origin-Resource-Policy: same-site»` не считает, что ответ, доставленный через безопасный транспорт, соответствует незащищенному источнику запроса, даже если их хосты в остальном являются одним и тем же сайтом. Ответы с безопасной передачей будут соответствовать только инициатору с безопасной передачей.

 

Чтобы поставить в очередь отчет о нарушении CORP политики внедрения кросс-происхождения, учитывая ответ «response», объект настроек среды «settingsObject» и логическое значение «reportOnly», выполните следующие действия:

1. Пусть «endpoint» будет конечная точка для отчетов политики встраивания settingsObject, если «reportOnly» имеет значение true, а в противном случае — конечная точка отчетов политики встраивания «settingsObject«.

2. Пусть serialized url будет результатом сериализации URL-адреса ответа для отчета с response.

3. Пусть «body» будет новым объектом, содержащим следующие свойства:

Ключ «type», значение «corp»

Ключ «blocked-url», значение serialized url

4. Очередь «body» как тип отчета «coep» для «endpoint» на «settingsObject«. [REPORTING]

 

4. Выборка («Выбирание»)

Алгоритм ниже определяет выборку. В общих чертах, он принимает запрос и выдает ответ.

То есть он либо возвращает ответ, если установлен флаг синхронности запроса, либо ставит в очередь задачи аннотированный ответ процесса, конец тела ответа процесса и ответ процесса, сделанный для ответа.

Для захвата загрузок, если флаг синхронности запроса не установлен, задачи, аннотированные телом запроса процесса и концом тела запроса процесса для запроса, могут быть поставлены в очередь.

Чтобы выполнить выборку (fetch) с помощью запроса «request», выполните следующие действия. Текущая выборка может быть прекращена (terminated) с помощью флага «aborted», который не установлен, если не указано иное.

Пользовательского агента могут попросить приостановить (suspend) текущую выборку. Пользовательский агент может принять или проигнорировать запрос на приостановку. Приостановленная загрузка может быть возобновлена. Пользовательский агент должен игнорировать запрос приостановки, если текущая выборка обновляет ответ в HTTP-кеше для запроса.

Пользовательский агент не обновляет запись в кэше HTTP для запроса, если режим кеширования запроса установлен на «no-store» или в ответе появляется заголовок «Cache-Control: no-store». [HTTP-CACHING]

1. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

1.1 Если окно запроса request является «client», установите окно request как клиент request, если глобальный объект клиента request является объектом Window, и в противном случае установите значение «no-window».

1.2 Если источником запроса request является «client», установите источник request как источник request клиента.

1.3 Если в списке заголовков запроса request нет «Accept», то:

1.3.1 Пусть значение value будет `* / *`.

1.3.2 Агент пользователя должен установить значение value для первого совпадающего оператора, если таковой имеется, переключаясь на адресата запроса request:

«document«

«frame«

«iframe«

`text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8`

«image«

`image/png,image/svg+xml,image/*;q=0.8,*/*;q=0.5`

«style«

`text/css,*/*;q=0.1`

1.3.3 Добавьте `Accept`/value в список заголовков запроса request.

1.4 Если список заголовков запроса request не содержит `Accept-Language`, пользовательские агенты должны добавить `Accept-Language`/ соответствующее значение в список заголовков запроса request.

1.5 Если приоритет запроса request равен нулю (является null), тогда используйте инициатор и место назначения запроса request соответствующим образом при установке приоритета запроса для объекта, определенного пользователем.

Объект, определяемый пользовательским агентом, может включать вес потока и зависимость для HTTP/2, а также эквивалентную информацию, используемую для определения приоритетов отправки и обработки выборок HTTP/1.

1.6 Если запрос request является запросом субресурса, то:

1.6.1 Пусть запись record будет новой записью выборки, состоящей из запроса request и этого экземпляра алгоритма выборки.

1.6.2 Добавить запись record в список групп выборки клиента запроса request из записей выборки.

2. В случае прерывания:

2.1 Пусть aborted будет флагом отмены завершения.

2.2 Если установлено прерывание aborted, возвращается прерванная сетевая ошибка.

2.3 Вернуть сетевую ошибку.

3.Вернуть результат выполнения основной выборки с помощью запроса request.

 

4.1 Основная выборка

Чтобы выполнить основную выборку (main fetch) с использованием запроса request, необязательно с рекурсивным флагом recursive flag, выполните следующие действия:

При рекурсивном вызове основной выборки устанавливается «recursive flag».

1. Пусть ответ response будет null.

2. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

2.1 Если в запросе request установлен флаг «local-URLs-only» и текущий URL запроса request не является локальным, тогда установите ответ response на сетевую ошибку.

2.2 Выполнить отчет о нарушениях политики безопасности контента для запроса request. [CSP]

2.3 Если необходимо, запрос request отправить на обновление до потенциально безопасного URL-адреса. [UPGRADE]

2.4 Если выборка запроса request будет заблокирована из-за плохого порта, если выборка запроса request будет заблокирована как смешанное содержимое, или если выборка запроса request будет заблокирована политикой безопасности контента, возврат заблокирован, установите ответ response на сетевую ошибку. [MIX] [CSP]

2.5 Если политика реферера запроса request представляет собой пустую строку, а клиент запроса request не имеет значения NULL, тогда установите политику реферера запроса request на политику реферера запроса  request клиента. [Referrer]

2.6 Если политика реферера запроса request представляет собой пустую строку, установите для политики реферера запроса request значение «no-referrer-when-downgrade«.

Мы используем «no-referrer-when-downgrade», потому что это историческое значение по умолчанию.

2.7 Если реферер запроса request не является «no-referrer», установите реферер запроса request на результат вызова определения реферера запроса request. [Referrer]

Как указано в Политике Реферера, пользовательские агенты могут предоставить конечному пользователю параметры, позволяющие переопределить реферер запроса на «no-referrer» или предоставить ему менее конфиденциальную информацию.

2.8 Если схема текущего URL-адреса запроса — «ftp», схема URL-адреса создания клиента запроса не является «ftp», а зарезервированный клиент запроса — либо null, либо среда, целевой контекст просмотра которой является вложенным контекстом просмотра, затем установите ответ response на сетевую ошибку.

2.9 Установите для схемы текущего URL запроса request значение https, если выполняются все следующие условия:

текущая схема URL запроса — http

текущий URL-адрес запроса хоста является доменом

Сопоставление хоста текущего URL-адреса запроса с известным доменным именем хоста HSTS. Сопоставление приводит либо к совпадению супердомена с заявленной директивой includeSubDomains, либо к конгруэнтному совпадению (с заявленной директивой includeSubDomains или без нее). [HSTS]

3. В случае прерывания:

3.1 Пусть aborted будет флагом отмены завершения.

3.2 Если установлено прерывание aborted, возвращается прерванная сетевая ошибка.

3.3 Вернуть сетевую ошибку.

4. Если флаг синхронности запроса не установлен и флаг рекурсии не установлен, выполните оставшиеся шаги параллельно.

5. Если ответ response равен нулю, установите ответ response на результат выполнения шагов, соответствующих первому совпадающему оператору:

— источник текущего URL запроса совпадает с источником запроса, а повреждение ответа запроса является «basic«

— текущая схема URL запроса — «data«

— режим запроса — «navigate» (навигация) или «websocket» (веб-сокет)

1. Установите для ответа на запрос значение «basic«.

2. Вернуть результат выполнения выборки схемы с помощью запроса request.

HTML присваивает всем документам и рабочим процессам, созданным из URL-адресов, схема которых является «данными», уникальное непрозрачное происхождение. Сервис-воркеры могут быть созданы только из URL-адресов, схема которых является схемой HTTP (S). [HTML] [SW]

— режим запроса — «same-origin» (то же происхождение)

Вернуть сетевую ошибку.

— режим запроса — «no-cors«

1. Если режим перенаправления запроса request не является «follow» (отслеживаемым), возвращается сетевая ошибка.

2. Установите для ответа на запрос request значение «opaque» (непрозрачный).

3. Пусть noCorsResponse будет результатом выполнения выборки схемы с использованием запроса request.

4. Если noCorsResponse — это отфильтрованный ответ или проверка CORB с запросом request, и noCorsResponse возвращает разрешенный результат, тогда возвращается noCorsResponse.

5. Возвращает новый ответ, статус которого — статус noCorsResponse, а список CSP — это список CSP noCorsResponse.

ОПАСНО!!! Это эффективная защита от атак по побочным каналам, только если noCorsResponse изолирован от процесса, инициировавшего запрос.

— схема текущего URL запроса не является схемой HTTP (S)

Вернуть сетевую ошибку.

— в запросе установлен флаг «use-CORS-preflight«

— установлен флаг «unsafe-request» небезопасного запроса для request, и либо метод запроса request не входит в список безопасных CORS, либо имена заголовков запроса «CORS-unsafe» со списком заголовков запроса не пусты

1. Установить заражение ответа на запрос «cors«.

2. Пусть corsWithPreflightResponse будет результатом выполнения HTTP-выборки с использованием запроса с установленным флагом «CORS-preflight».

3. Если corsWithPreflightResponse — сетевая ошибка, очистите записи кеша с помощью request.

4. Возврат corsWithPreflightResponse.

— В противном случае

1. Установить заражение ответа на запрос «cors«.

2. Вернуть результат выполнения HTTP-выборки с использованием запроса.

6. Если установлен рекурсивный флаг, вернуть ответ.

7. Если ответ не является сетевой ошибкой и ответ не является отфильтрованным ответом, тогда:

7.1 Если повреждение ответа на запрос — «cors», то:

7.1.1 Пусть headerNames будет результатом извлечения значений списка заголовков, заданных `Access-Control-Expose-Headers`, и списка заголовков ответа.

7.1.2 Если режим учетных данных запроса отличается от «include» и headerNames содержит `*`, тогда установите для CORS-открытого списка имен заголовков ответа все уникальные имена заголовков в списке заголовков ответа.

7.1.3 В противном случае, если headerNames не равно null или не имеет значения, задайте для списка заголовков ответа, представленного CORS, значение headerNames.

Одно из headerNames все еще может быть `*` на этом этапе, но будет соответствовать только заголовку с именем `*`.

7.2 Установите ответ response на следующий отфильтрованный ответ с response в качестве внутреннего ответа, в зависимости от заражения ответа на запрос request:

«basic«

основной отфильтрованный ответ

«cors«

CORS отфильтрованный ответ

«opaque«

непрозрачный фильтрованный ответ

8. Пусть internalResponse будет ответом response, если ответом response является сетевая ошибка, и внутренним ответом response в противном случае.

9. Если список URL-адресов internalResponse пуст, установите его как копию списка URL-адресов запроса.

Список URL-адресов ответа может быть пустым (например, если ответ представляет собой URL-адрес «about«).

10. Если флаг разрешения ошибки времени запроса не установлен, установите флаг разрешения времени internalResponse.

11. Установите список CSP для internalResponse. [CSP]

12. Если ответ не является сетевой ошибкой, и любой из следующих алгоритмов возвращает блокировку, установите response и internalResponse на сетевую ошибку:

— должен быть заблокирован internalResponse на запрос как смешанное содержимое [MIX]

— должен быть заблокирован internalResponse на запрос Политикой Безопасности Контента [CSP]

— должен быть заблокирован internalResponse на запрос из-за его типа MIME

— должен быть заблокирован internalResponse на запрос из-за nosniff

13. Если тип ответа «opaque», статус internalResponse — 206, установлен флаг запрошенного диапазона internalResponse и список заголовков запроса не содержит «Range», тогда установите response и internalResponse на сетевую ошибку.

Традиционно API принимают ответ с диапазоном, даже если диапазон не запрашивался. Это предотвращает предоставление частичного ответа от более раннего запроса диапазона к API, который не сделал запрос диапазона.

Вышеупомянутые шаги предотвращают следующую атаку:

Медиа-элемент используется для запроса диапазона HTML-ресурса из разных источников. Хотя это недопустимый носитель, ссылка на клон ответа может быть сохранена в сервис-воркере. Позже это можно будет использовать в качестве ответа на выборку элемента скрипта. Если частичный ответ является допустимым JavaScript (даже если не весь ресурс), его выполнение приведет к утечке личных данных.

14. Если ответ не является сетевой ошибкой и либо метод запроса — HEAD, либо CONNECT, либо статус internalResponse имеет нулевой статус тела, установите для тела internalResponse значение null и не обращайте внимания на любые постановки в очередь к нему (если они есть).

Это стандартизирует обработку ошибок для серверов, нарушающих HTTP.

15. Если ответ не является сетевой ошибкой и метаданные целостности запроса не являются пустой строкой, тогда:

15.1 Ждите тело ответа.

15.2 Если в потоке тела ответа response нет ошибок и ответ response не соответствует метаданным целостности запроса, установите response и internalResponse на сетевую ошибку. [SRI]

Это работает с ответом, поскольку этот алгоритм не должен соблюдать internalResponse. Это позволит злоумышленнику использовать хеши в качестве оракула.

16. Если установлен флаг синхронности запроса, дождитесь тела internalResponse, а затем верните ответ.

На этом выборка прекращается.

17. Если текущая схема URL запроса является схемой HTTP (S), то:

17.1 Если тело запроса выполнено, поставьте в очередь задачу «fetch-request-done» для запроса.

17.2 В противном случае, параллельно дождитесь тела запроса, а затем поставьте в очередь задачу «fetch-request-done» для запроса.

18. Поставить в очередь задачу выборки по request для обработки ответа для response.

19. Дождитесь internalResponse тела ответа.

20. Поставить в очередь задачу выборки по запросу request, чтобы обработать конец тела ответа для response.

21. Установить флаг выполнения запроса.

22. Поставить в очередь задачу выборки по запросу request, чтобы обработать ответ, сделанный для response.

 

4.2 Выборка Схемы

Чтобы выполнить выборку схемы  с помощью запроса request, включите текущую схему URL-адреса запроса и выполните соответствующие шаги:

«about«

Если в текущем URL-адресе запроса установлен флаг «cannot-be-a-base-URL», а путь содержит одну строку «blank», тогда возвращается новый ответ, сообщение о состоянии которого — `OK`, список заголовков состоит из одного заголовка с именем `Content-Type`, а значение — `text/html;charset=utf-8`, а body — это пустая последовательность байтов.

В противном случае вернуть ошибку сети.

URL-адреса, такие как «about:config«, обрабатываются во время навигации и приводят к сетевой ошибке в контексте выборки.

«blob«

1. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

1.1 Пусть blob будет объектом записи URL-адреса большого двоичного объекта текущего URL-адреса запроса.

1.2 Если метод запроса не является GET или blob не является объектом Blob, возвращается сетевая ошибка. [FileAPI]

1.3 Пусть ответ response будет новым ответом, статусное сообщение которого — «ОК».

1.4 Добавьте значение `Content-Length`/ blob-атрибут size в список заголовков ответа response.

1.5 Добавьте значение `Content-Type`/ blob-атрибут type в список заголовков ответа response.

1.6 Задайте в теле ответа результат выполнения операции чтения для большого двоичного объекта blob.

1.7 Верните response

2. В случае прерывания:

2.1 Пусть aborted будет флагом отмены завершения.

2.2. Если установлено прерывание aborted, возвращается прерванная сетевая ошибка.

2.3 Вернуть сетевую ошибку.

«data«

1. Пусть dataURLStruct будет результатом выполнения data: URL-обработчика для текущего URL-адреса запроса.

2. Если dataURLStruct является ошибкой, возвращается сетевая ошибка.

3. Возвращает ответ, сообщение о состоянии которого — `OK`, список заголовков состоит из одного заголовка с именем `Content-Type`, а значение — это тип MIME dataURLStruct, сериализованный, а тело — это тело dataURLStruct.

«file«

Пока, к сожалению, URL-адреса файлов оставлены читателям в качестве упражнения.

В случае сомнений вернуть ошибку сети.

«ftp«

На данный момент, как это ни прискорбно, URL-адреса ftp в основном оставлены в качестве упражнения для читателя.

1. Пусть body будет результатом того, что пользовательский агент получит контент из запроса текущего URL-адреса из сети через FTP. [RFC 959]

2. Пусть mime будет `application/octet-stream`.

3. Если тело body является результатом того, что пользовательский агент создает страницу со списком каталогов для результата команды FTP LIST, тогда установите для mime значение `text/ftp-dir`.

4. Возвращает ответ, статусное сообщение которого — `OK`, список заголовков состоит из одного заголовка с именем`Content-Type` и значением mime, а тело — body.

В случае сомнений вернуть ошибку сети.

«HTTP(S) схема«

Вернуть результат выполнения HTTP-выборки с использованием запроса.

«В противном случае«

Вернуть сетевую ошибку.

 

4.3 Выборка HTTP (HTTP fetch)

Чтобы выполнить HTTP-выборку (HTTP fetch) с использованием запроса с необязательным флагом «CORS-preflight«, выполните следующие действия:

Детализация учета флага CORS-preflight указывает, что требуется запрос CORS-preflight.

1. Пусть ответ response будет null.

2. Пусть actualResponse будет null.

3. Если режим сервис-воркеров запроса request — «all«, то:

3.1 Установить ответ response на результат вызова дескриптора для запроса request. [HTML] [SW]

3.2 Если ответ response не null, то:

3.2.1 Передать тело для запроса request.

3.2.2  Установите actualResponse для ответа response, если ответ response не является отфильтрованным, и для внутреннего ответа в противном случае.

3.2.3 Если верно одно из следующих утверждений

— тип ответа — «error«

— режим запроса — «same-origin«, а тип ответа — «cors«.

— режим запроса не является «no-cors«, а тип ответа — «opaque«

— режим перенаправления запроса не является «manual«, а тип ответа — «opaqueredirect«.

— режим переадресации запроса не является «follow«, а список URL-адресов ответа содержит более одного элемента.

затем вернуть ошибку сети.

4. Если ответ null, то:

4.1 Если установлен флаг «CORS-preflight» и выполняется одно из этих условий:

— Нет совпадения записи в кэше метода для метода, использующего запрос, и либо метод запроса не входит в список безопасных CORS, либо установлен флаг запроса «use-CORS-preflight».

— В именах заголовков запроса «CORS-unsafe» со списком заголовков запроса есть по крайней мере один элемент, для которого нет совпадения записи в кэше имени заголовка с использованием запроса.

Затем:

1. Пусть preflightResponse будет результатом выполнения предварительной проверки CORS с использованием запроса.

2. Если preflightResponse — сетевая ошибка, верните preflightResponse.

На этом шаге проверяется кэш предварительной проверки CORS, и если подходящей записи нет, выполняется предварительная выборка CORS, которая в случае успеха заполняет кеш. Цель предварительной выборки CORS — убедиться, что извлекаемый ресурс знаком с протоколом CORS. Кэш предназначен для минимизации количества предварительных проверок CORS.

4.2 Если режим перенаправления запроса — «follow», установите для режима рабочих служб запроса значение «none».

Перенаправления, поступающие из сети (в отличие от сервис-воркера), не должны быть доступны сервис-воркеру.

4.3 Установите response и actualResponse на результат выполнения выборки «HTTP-network-or-cache» с использованием запроса.

4.4 Если повреждение ответа на запрос — «cors» и проверка CORS для запроса и ответа возвращает ошибку, возвращается ошибка сети.

Поскольку проверка CORS не должна применяться к ответам со статусом 304 или 407, или к ответам сервис-воркера, если на то пошло, она применяется здесь.

4.5 Если проверка TAO на запрос и ответ возвращает ошибку, тогда установите флаг разрешения сбоя синхронизации запроса.

5. Если либо повреждение ответа запроса, либо тип ответа «opaque» и проверка политики ресурсов с разными источниками с указанием источника запроса, клиента запроса и фактического ответа возвращает блокировку, то возвращается сетевая ошибка.

Проверка политики ресурсов между источниками выполняется для ответов, поступающих из сети, и ответов, поступающих от работника службы. Это отличается от проверки CORS, поскольку клиент запроса и работник службы могут иметь разные политики внедрения.

6. Если статус actualResponse — статус перенаправления, то:

6.1 Если статус actualResponse не равен 303, тело запроса не равно нулю и соединение использует HTTP/2, тогда пользовательские агенты могут передавать кадр RST_STREAM, и даже поощряются к этому.

303 исключен, поскольку определенные сообщества придают ему особый статус.

6.2 Пусть location будет результатом извлечения значений списка заголовков из `Location` и списка заголовков actualResponse.

6.3 Если местоположение location является значением, тогда установите местоположение как результат анализа location с URL-адресом фактического ответа.

6.4 В качестве URL-адреса местоположения actualResponse укажите location.

6.5 Включите режим перенаправления запроса:

«error«

Установите ответ response на сетевую ошибку.

«manual«

Установите ответ response на отфильтрованный ответ с непрозрачным перенаправлением, внутренний ответ которого — actualResponse.

«follow«

Установить ответ на результат выполнения выборки «HTTP-redirect» с использованием запроса request и ответа response.

7. Вернуть  response

Обычно поток тела actualResponse по-прежнему ставится в очередь после возврата.

 

4.4 Выборка HTTP-перенаправление (HTTP-redirect fetch)

Этот алгоритм используется алгоритмом навигации HTML в дополнение к HTTP-выборке, описанной выше. [HTML]

Чтобы выполнить выборку с перенаправлением HTTP (HTTP-redirect fetch) с использованием запроса и ответа, выполните следующие действия:

1. Пусть actualResponse будет ответом response, если ответ response не является отфильтрованным ответом, и внутренним ответом response в противном случае.

2. Если URL-адрес местоположения actualResponse равен нулю, вернуть ответ response.

3. Если URL-адрес местоположения actualResponse является ошибочным, возвращается ошибка сети.

4. Если схема URL-адреса местоположения actualResponse НЕ является схемой HTTP (S), возвращается сетевая ошибка.

5. Если количество перенаправлений запроса request равно двадцати, возвращается сетевая ошибка.

6. Увеличьте количество перенаправлений запросов request на единицу.

7. Если режим запроса request — «cors«, URL-адрес местоположения actualResponse включает учетные данные, а источник запроса не совпадает с источником URL-адреса местоположения actualResponse, тогда возвращается сетевая ошибка.

8. Если повреждение ответа на запрос request — «cors«, а URL-адрес местоположения actualResponse включает учетные данные, возвращается сетевая ошибка.

Это улавливает переадресацию ресурса с перекрестным происхождением на URL-адрес того же источника.

9. Если статус фактического ответа actualResponse не равен 303, тело запроса request не равно нулю, а источник тела запроса request равен нулю, возвращается сетевая ошибка.

10. Если источник текущего URL-адреса фактического ответа не совпадает с источником текущего URL-адреса запроса, а источник запроса не совпадает с источником текущего URL-адреса запроса, то установите флаг испорченного источника запроса (tainted origin flag).

11. Если верно одно из следующих утверждений

Статус фактического ответа — 301 или 302, а метод запроса — POST.

Статус фактического ответа — 303, а метод запроса — не GET или HEAD.

тогда:

1. Установите для метода запроса значение GET, а для тела запроса значение null.

2. Для каждого headerName имени «request-body-header» удалите headerName из списка заголовков запроса.

12. Если тело запроса не равно NULL, установите в теле запроса первое возвращаемое значение безопасного извлечения источника тела запроса.

недействительность источника тела запроса уже проверена.

13. Добавьте фактический URL-адрес местоположения ответа в список URL-адресов запроса.

14. Вызвать политику реферера набора запросов при перенаправлении на запрос request и фактический ответ actualResponse. [Referrer]

15. Вернуть результат выполнения основной выборки с использованием запроса request с установленным рекурсивным флагом (recursive flag), если режим перенаправления запроса не является «manual».

Здесь он может быть только «manual«, когда этот алгоритм вызывается непосредственно из алгоритма навигации HTML.

Это должно вызвать основную выборку, чтобы получить правильный ответ.

 

4.5 Выборка HTTP-сеть или кэш (HTTP-network-or-cache fetch)

Чтобы выполнить выборку HTTP-сети или кеша (HTTP-network-or-cache fetch) с использованием запроса с необязательным флагом «аутентификации-выборки»(authentication-fetch flag), выполните следующие действия:

Флаг «аутентификация-выборка» (authentication-fetch flag) — это бухгалтерская деталь.

Некоторые реализации могут поддерживать кеширование частичного содержимого в соответствии с запросами диапазона HTTP. [HTTP-RANGE] Однако это не широко поддерживается кешами браузера.

1. Пусть httpRequest будет NULL.

2. Пусть ответ response будет NULL.

3. Пусть storedResponse будет NULL.

4. Пусть httpCache будет NULL.

5. Пусть revalidatingFlag не установлен.

6. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

6.1 Если окно запроса request — «no-window», а режим перенаправления запроса request — «error», тогда установите httpRequest на request.

6.2 В противном случае:

1. Установите httpRequest на копию запроса, кроме его тела.

2. Пусть body будет телом запроса request.

3. Установите тело HTTP-запроса httpRequest в body.

4. Если body не равно нулю, тогда установите тело запроса request на новое тело, поток которого равен NULL и чей источник является источником тела body.

здесь запрос request копируется как httpRequest, так как нам нужно иметь возможность добавлять заголовки в httpRequest и читать его тело, не затрагивая запрос. А именно, запрос можно повторно использовать с «перенаправлениями», «аутентификацией» и «аутентификацией прокси». Мы копируем, а не клонируем, чтобы уменьшить потребление памяти. Если источник тела запроса равен нулю, перенаправления и аутентификация завершатся ошибкой выборки.

6.3 Установить флаг учетных данных — credentials flag, если один из

режим учетных данных запроса — «include»
режим учетных данных запроса — «same-origin«, а повреждение ответа запроса — «basic«

верно, и не установлено иначе.

6.4 Пусть contentLengthValue будет NULL.

6.5 Если тело httpRequest имеет значение NULL, а метод httpRequest — `POST` или `PUT`, установите для contentLengthValue значение `0`.

6.6 Если тело httpRequest НЕ NULL, а источник тела httpRequest НЕ NULL, тогда установите contentLengthValue равным общему количеству байтов тела httpRequest, сериализованных и изоморфно закодированных.

6.7 Если contentLengthValue НЕ NULL, добавьте `Content-Length`/contentLengthValue в список заголовков httpRequest.

6.8 Если contentLengthValue не равно NULL и установлен флаг «keepalive» httpRequest, то:

1. Пусть inflightKeepaliveBytes будут равны нулю.

2. Пусть group будет группой выборки клиента httpRequest.

3. Пусть inflightRecords будет набором записей выборки в группе, в запросе которой установлен флаг «keepalive» и не установлен флаг готовности.

4. Для каждого fetchRecord в inflightRecords:

1. Пусть inflightRequest будет запросом fetchRecord.

2. Увеличьте «inflightKeepaliveBytes» на общее количество байтов тела inflightRequest.

5. Если сумма contentLengthValue и inflightKeepaliveBytes больше 64 килобайт, возвращается сетевая ошибка.

Вышеупомянутый предел гарантирует, что запросы, которым разрешено переживать объект настроек среды и содержать тело, имеют ограниченный размер и не могут оставаться в живых бесконечно.

6.9 Если реферер httpRequest является URL-адресом, добавьте `Referer`/ httpRequest, сериализованный и изоморфно закодированный, в список заголовков httpRequest.

6.10 Добавьте заголовок запроса `Origin` для httpRequest.

6.11 Если список заголовков httpRequest не содержит `User-Agent`, тогда пользовательские агенты должны добавить значение `User-Agent` / дефолтное значение `User-Agent` (по умолчанию) в список заголовков httpRequest.

6.12 Если режим кеширования httpRequest установлен по умолчанию, а список заголовков httpRequest содержит `If-Modified-Since`, `If-None-Match`, `If-Unmodified-Since`, `If-Match` или `If-Range`, затем установите для режима кеширования httpRequest значение «no-store».

6.13 Если режим кеширования httpRequest — «no-cache», httpRequest не установлен флаг изменения заголовка управления кешем без кеширования (prevent no-cache cache-control header modification flag), а список заголовков httpRequest не содержит `Cache-Control`, затем добавьте`Cache-Control` / `max-age = 0` в список заголовков httpRequest.

6.14 Если режим кеширования httpRequest — «no-store» или «reload», то:

1. Если список заголовков httpRequest не содержит `Pragma`, добавьте`Pragma` / `no-cache` в список заголовков httpRequest.

2. Если список заголовков httpRequest не содержит `Cache-Control`, добавьте`Cache-Control` / `no-cache` в список заголовков httpRequest.

6.15 Если список заголовков httpRequest содержит `Range`, добавьте`Accept-Encoding` / `identity` в список заголовков httpRequest.

Это позволяет избежать сбоя при обработке кодирования контента с частью закодированного ответа.

Кроме того, многие серверы по ошибке игнорируют заголовки «Range», если принято кодирование, отличное от идентификатора.

6.16 Измените список заголовков httpRequest для HTTP. Не добавляйте данный заголовок, если список заголовков httpRequest содержит имя этого заголовка.

Было бы здорово, если бы мы могли как-то сделать это более нормативным. На этом этапе при необходимости должны быть добавлены такие заголовки, как «Accept-Encoding«, «Connection«, «DNT» и «Host«.

`Accept`, `Accept-Charset` и `Accept-Language` не должны быть включены в этот момент.

«Accept» и «Accept-Language» уже включены (если не используется fetch(), который не включает последний по умолчанию), а `Accept-Charset` является пустой тратой байтов. Подробнее см. Разделение уровня заголовка HTTP.

6.17 Если установлен флаг учетных данных — credentials flag, то:

1. Если пользовательский агент не настроен на блокировку файлов cookie для httpRequest (см. Раздел 7 [COOKIES]), то:

1. Пусть cookies будут результатом выполнения алгоритма «cookie-string» (см. Раздел 5.4 [COOKIES]) с хранилищем файлов cookie пользовательского агента и текущим URL httpRequest.

2. Если cookies не является пустой строкой, добавьте `Cookie`/cookies в список заголовков HTTP-запроса.

2. Если список заголовков httpRequest не содержит `Authorization`, то:

1. Пусть authorizationValue будет NULL.

2. Если есть запись аутентификации для httpRequest и либо флаг «use-URL-credentials» httpRequest  не установлен, либо текущий URL httpRequest не включает учетные данные, тогда установите authorizationValue на запись аутентификации.

3. В противном случае, если текущий URL-адрес httpRequest действительно включает учетные данные и установлен флаг аутентификации-выборки (authentication-fetch flag), установите для authorizationValue текущий URL-адрес httpRequest, преобразованный в значение `Authorization`.

4. Если authorizationValue НЕ NULL, добавьте `Authorization` / authorizationValue в список заголовков httpRequest.

6.18 Если есть запись прокси-аутентификации, используйте ее соответствующим образом.

Это намеренно не зависит от режима учетных данных httpRequest.

6.19 Задайте для httpCache результат определения раздела HTTP-кеша с учетом httpRequest.

6.20 Если httpCache имеет значение NULL, установите для режима кеширования httpRequest значение «no-store».

6.21 Если режим кеширования httpRequest не является ни «no-store», ни «reload», тогда:

1. В качестве параметра storedResponse укажите результат выбора ответа из httpCache, возможно, требующего проверки, в соответствии с главой «Создание ответов из кешей» руководства HTTP-кеширование [HTTP-CACHING], если таковое имеется.

В соответствии с требованиями HTTP при этом по-прежнему учитывается заголовок «Vary«.

2. Если сохраненный ответ не является нулевым, тогда:

1. Если режим кеширования установлен на «default«, storedResponse является устаревшим ответом на время повторной проверки, а клиент httpRequest не имеет значения NULL, тогда:

1. Установите ответ response на storedResponse.

2. Установите состояние кеша ответа response как «local«.

3. Пусть revalidateRequest будет клоном запроса request.

4. Установите для режима кеширования revalidateRequest значение «no-cache«.

5. Установите флаг изменения заголовка revalidateRequest, чтобы предотвратить изменение заголовка управления кешем без кеширования.

6. Установите для режима рабочих служб revalidateRequest значение «none«.

7. Параллельно выполните основную выборку с помощью revalidateRequest.

Эта выборка предназначена только для обновления состояния httpCache, и ответ не будет использоваться до следующего обращения к кешу. Устаревший ответ будет использоваться как ответ на текущий запрос. Эта выборка выполняется в контексте клиента, поэтому, если она уходит, запрос будет прекращен.

2. В противном случае

1. Если storedResponse является устаревшим ответом, установите revalidatingFlag.

2. Если установлен revalidatingFlag и режим кеширования httpRequest не является ни «force-cache» (принудительным кешированием), ни «only-if-cached» (только при кэшировании), то:

1. Если список заголовков storedResponse содержит `ETag`, добавьте`If-None-Match` с его значением в список заголовков httpRequest.

2. Если сохраненный список заголовков Response содержит `Last-Modified`, добавьте`If-Modified-Since` с его значением в список заголовков HTTP-запроса.

См. Также главу «Отправка запроса проверки» в документе HTTP-кеширование [HTTP-CACHING].

3. В противном случае установите для ответа значение storedResponse и установите состояние кеша ответа на «local».

7. В случае прерывания:

1. Пусть aborted будет флагом отмены завершения.

2. Если установлено «aborted», возвращается прерванная сетевая ошибка.

3. Вернуть сетевую ошибку.

8. Если ответ нулевой, то:

1. Если режим кеширования httpRequest — «only-if-cached», возвращается сетевая ошибка.

2. Пусть forwardResponse будет результатом выполнения выборки из HTTP-сети с использованием httpRequest с флагом учетных данных credentials flag, если он установлен.

3. Если метод httpRequest небезопасен и статус forwardResponse находится в диапазоне от 200 до 399 включительно, сделайте недействительными соответствующие сохраненные ответы в httpCache, как указано в главе «Недействительность» кеширования HTTP, и установите для параметра storedResponse значение null. [HTTP-CACHING]

4. Если установлен revalidatingFlag и статус forwardResponse равен 304, тогда:

1. Обновите список заголовков сохраненных ответов storedResponse, используя список заголовков переадресованных ответов forwardResponse, как описано в главе «Обновление сохраненных ответов после проверки» кэширования HTTP. [HTTP-CACHING]

Это также обновляет сохраненный ответ в кеше.

2. Установите ответ response на storedResponse.

5. Если ответ response является NULL, то:

1. Установите ответ response на forwardResponse.

2. Сохраните httpRequest и переадресуйте ответ в httpCache, как описано в главе «Хранение ответов в кешах» кеширования HTTP. [HTTP-CACHING]

Если forwardResponse является сетевой ошибкой, это эффективно кэширует сетевую ошибку, которую иногда называют «отрицательным кэшированием» (negative caching).

9. Задайте в качестве списка URL ответа response копию списка URL httpRequest.

10. Если список заголовков httpRequest содержит `Range`, тогда установите флаг запроса диапазона ответа (range-requested flag).

11. Если статус ответа response 401, повреждение ответа httpRequest не является «cors«, установлен флаг учетных данных, а окно запроса является объектом настроек среды, тогда:

1. Требуется тестирование: несколько заголовков `WWW-Authenticate`, отсутствуют, проблемы с анализом.

2. Если тело запроса request не равно NULL, то:

1. Если источник тела запроса request — NULL, возвращается сетевая ошибка.

2. Установите в теле request первое возвращаемое значение безопасного извлечения источника тела request.

3. Если в запросе не установлен use-URL-credentials flag или установлен authentication-fetch flag, то:

1. Если текущая выборка прервана, то:

1. Пусть aborted будет флагом отмены завершения.

2. Если установлено «aborted», возвращается прерванная сетевая ошибка.

3. Вернуть сетевую ошибку.

2. Пусть имя пользователя username и пароль password будут результатом запроса у конечного пользователя имени пользователя и пароля, соответственно, в окне запроса request.

3. Задайте для имени пользователя текущий URL-адрес запроса request и username.

4. Задайте для пароля текущий URL-адрес запроса request и password.

4. Задайте ответ response на результат выполнения «выборки из сети или кэша HTTP» (HTTP-network-or-cache fetch) с помощью запроса с установленным флагом выборки аутентификации (authentication-fetch flag).

12. Если статус ответа 407, то:

1. Если окно запроса «no-window«, возвращается сетевая ошибка.

2. Требуется тестирование: несколько заголовков `Proxy-Authenticate`, отсутствуют, проблемы с анализом.

3. Если текущая выборка прервана, то:

1. Пусть aborted будет флагом отмены завершения.

2. Если установлено «aborted», возвращается прерванная сетевая ошибка.

3. Вернуть сетевую ошибку.

4. Предложите конечному пользователю в соответствующем окне запроса и сохраните результат как запись прокси-аутентификации. [HTTP-AUTH]

Остальные детали аутентификации прокси определяются протоколом HTTP.

5. Установите ответ на результат выполнения выборки из HTTP-сети или кеша с помощью запроса request.

13. Если установлен флаг аутентификации-выборки (authentication-fetch flag), тогда создайте запись аутентификации для запроса request и данной области.

14. Верните response

Обычно поток тела ответа после возврата все еще находится в очереди.

 

4.6 Выборка HTTP-сеть (HTTP-network fetch)

Чтобы выполнить выборку из HTTP-сети (HTTP-network fetch) с использованием запроса request с необязательным флагом учетных данных credentials flag, выполните следующие действия:

1. Пусть учетные данные credentials будут истинными (true), если установлен флаг credentials flag, и ложью (false) в противном случае.

2. Пусть ответ response будет NULL.

3. Пусть httpCache будет результатом определения раздела HTTP-кеша с учетом httpRequest.

4. Если httpCache имеет значение NULL, установите для режима кеширования запроса request значение «no-store».

5. Пусть networkPartitionKey будет результатом определения ключа раздела сети по запросу request.

6. Включить режим запроса request:

«websocket«

Пусть соединение connection будет результатом получения соединения WebSocket с учетом текущего URL-адреса запроса request.

В противном случае

Пусть соединение connection будет результатом получения соединения с заданным ключом networkPartitionKey, источником текущего URL-адреса запроса request и учетными данными credentials.

7. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

1. Если соединение connection не удалось (потерпело неудачу), вернуть ошибку сети.

2. Если соединение connection не является соединением HTTP/2, тело запроса не равно нулю, а источник тела запроса равен нулю, тогда добавьте «Transfer-Encoding»/«chunked» к списку заголовков запроса.

3. Установите ответ на результат выполнения HTTP-запроса через соединение, используя запрос со следующими оговорками:

-Следуйте соответствующим требованиям HTTP. [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH]

-Подождите, пока не будут переданы все заголовки.

-Любые ответы, статус которых находится в диапазоне от 100 до 199 включительно, а не 101, следует игнорировать.

За такими ответами в конечном итоге следует «окончательный» ответ.

Точное распределение уровней между Fetch и HTTP все еще необходимо отсортировать, поэтому ответ response здесь представляет собой как ответ, так и HTTP-ответ.

Если список заголовков запроса содержит `Transfer-Encoding`/`chunked`, а ответ передается через HTTP/1.0 или старше, возвращается сетевая ошибка.

Если HTTP-запрос приводит к появлению диалогового окна сертификата клиента TLS, то:

1. Если окно запроса request является «объектом настроек среды» (environment settings object), сделайте диалог доступным в окне запроса request.

2. В противном случае вернуть ошибку сети.

Передать тело запроса request.

8. В случае прерывания:

1. Пусть aborted будет флагом отмены завершения.

2. Если соединение connection использует HTTP/2, то передайте кадр RST_STREAM.

3. Если установлено «прервано», возвращается прерванная сетевая ошибка.

4. Вернуть сетевую ошибку.

9. Пусть highWaterMark будет неотрицательным числом, отличным от NaN, выбранным пользовательским агентом.

10. Пусть sizeAlgorithm будет алгоритмом, который принимает объект фрагмента (chunk) и возвращает неотрицательное, отличное от NaN, не бесконечное число, выбранное пользовательским агентом.

11. Пусть pull будет действием, которое возобновляет текущую выборку, если она приостановлена.

12. Пусть отмена cancel будет действием, которое завершает текущую выборку с установленным флагом прерывания.

13. Пусть stream будет результатом создания объекта ReadableStream с highWaterMark, sizeAlgorithm, pull и cancel.

Эта строительная операция не вызовет исключения.

14. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

1. Установите тело ответа response на новое тело, поток которого является потоком stream.

2. Если ответ response имеет длину тела полезной нагрузки, то установите общие байты тела ответа response на эту длину тела полезной нагрузки.

3. Если ответ response не является сетевой ошибкой и режим кеширования запроса не является «no-store«, то обновите response в httpCache для request.

4. Если установлен флаг учетных данных (credentials flag) и пользовательский агент не настроен на блокировку файлов cookie для запроса (см. Раздел 7 [COOKIES]), запустите алгоритм синтаксического анализа «set-cookie-string» (см. Раздел 5.2 в [COOKIES]) на значение каждого заголовка, имя которого является нечувствительным к регистру байтом совпадением для `Set-Cookie` в списке заголовков ответа, если таковой имеется, и текущего URL-адреса запроса.

Это вектор отпечатков пальцев.

15. В случае прерывания:

1. Пусть aborted будет флагом отмены завершения.

2. Если установлено прерывание aborted, то устанавливается флаг прерывания ответа.

3. Верните response

16. Выполните эти шаги параллельно:

1. Выполните эти шаги, но прервите, когда текущая выборка будет прекращена:

1. Пока ИСТИНА

1. Если один или несколько байтов были переданы из тела сообщения ответа, то:

1. Пусть bytes будут переданными байтами.

2. Увеличьте переданные байты тела ответа response с длиной bytes.

3. Пусть кодирование codings будет результатом извлечения значений списка заголовков, заданных Content-Encoding, и списка заголовков ответа.

4. Устанавливает bytes в результат обработки кодировок содержимого с учетом codings и bytes.

Это делает заголовок «Content-Length» ненадежным в той степени, в которой он был надежным с самого начала.

5. Если «bytes» выдают ошибку, то прекратите текущую выборку.

6. Поставьте в очередь объект Uint8Array, обертывающий ArrayBuffer, содержащий байты bytes для потоковой передачи stream. Если это вызвало исключение, прекратите текущую выборку и ошибочный stream с этим исключением.

7. Если потоку stream не нужны дополнительные данные, а флаг синхронности запроса request не установлен, попросите пользовательский агент приостановить текущую выборку.

2. В противном случае, если передача байтов для тела сообщения ответа response выполняется нормально и поток stream доступен для чтения, закройте поток stream и прервите эти параллельные шаги.

2. В случае прерывания:

1. Пусть aborted будет флагом отмены завершения.

2. Если установлено «aborted», то:

1. Установить флаг прерывания ответа response.

2. Если поток stream доступен для чтения, ошибочный stream с DOMException «AbortError».

3. В противном случае, если поток stream доступен для чтения, ошибочный stream с TypeError.

4. Если соединение connection использует HTTP/2, то передайте кадр RST_STREAM.

5. В противном случае пользовательский агент должен закрыть соединение connectio, если это не ухудшит производительность.

Например, пользовательский агент может поддерживать соединение открытым, если он знает, что в повторно используемом соединении осталось всего несколько байтов передачи. В этом случае может быть хуже закрыть соединение и снова пройти процесс подтверждения для следующей выборки.

Они выполняются параллельно, поскольку на данный момент неясно, релевантен ли текст ответа (ответ может быть перенаправлением).

17. Вернуть response

Обычно поток тела ответа по-прежнему помещается в очередь после возврата

 

4.7 Выборка CORS-предполетная (CORS-preflight fetch)

По сути, это реализация пользовательского агента проверки того, понятен ли протокол CORS. Так называемый запрос CORS-preflight. В случае успеха он заполняет кеш CORS-preflight, чтобы минимизировать количество этих выборок.

Чтобы выполнить предварительную загрузку CORS (CORS-preflight fetch) с помощью запроса request, выполните следующие действия:

1. Пусть:

Предварительная проверка preflight будет новым запросом, метод которого — `OPTIONS`,

URL — текущий URL запроса request,

Инициатор — инициатор запроса request,

Пункт назначения — место назначения запроса request,

Источник — источник запроса request,

Реферер — это реферер запроса request,

Политика реферера — это политика реферера запроса request,

Режим -» cors «

Испорченный флаг происхождения (tainted origin flag) — это испорченный флаг происхождения запроса request,

Испорченный ответ — «cors«.

 

Режим предварительной проверки сервис-воркеров не имеет значения, поскольку этот алгоритм использует выборку из сети или кеша HTTP (HTTP-network-or-cache fetch), а не из выборки HTTP (HTTP fetch).

2. Добавьте `Accept`/`*/*` в список заголовков preflight.

3. Добавьте `Access-Control-Request-Method`/метод request в список заголовков preflight.

4. Пусть headers будут именами заголовков запроса CORS-unsafe со списком заголовков запроса request.

5. Если заголовки headers не пустые, то:

1. Пусть значение value будет элементами в заголовках, разделенных друг от друга символом `,`

2. Добавьте `Access-Control-Request-Headers`/value в список заголовков preflight.

Это намеренно не использует комбинирование, поскольку 0x20 после 0x2C — это не тот способ, которым это было реализовано, к лучшему или худшему.

6. Пусть ответ response будет результатом выполнения выборки из HTTP-сети или кеша с использованием preflight.

7. Если проверка CORS (CORS check) для запроса request и ответа response возвращает успех, а статус ответа — ОК, тогда:

Проверка CORS выполняется по запросу request, а не перед preflight, чтобы убедиться, что используется правильный режим учетных данных.

1. Пусть методы methods будут результатом извлечения значений списка заголовков, заданных `Access-Control-Allow-Methods` и списка заголовков ответа response.

2. Пусть headerNames будет результатом извлечения значений списка заголовков, заданных `Access-Control-Allow-Headers`, и списка заголовков ответа response.

3. Если один из методов methods или headerNames является ошибкой, вернуть сетевую ошибку.

4. Если methods имеет значение NULL и установлен флаг «use-CORS-preflight» запроса, установите для методов methods новый список, содержащий метод запроса request.

Это гарантирует, что выборка CORS-preflight, которая произошла из-за установленного в запросе флага «use-CORS-preflight», кэшируется.

5. Если метод запроса отсутствует в methods, метод запроса не входит в список надежных CORS, а режим учетных данных запроса — «include» или methods не содержат «*«, то возвращается сетевая ошибка.

6. Если одно из имен списка заголовков запроса request является именем заголовка запроса CORS без подстановочных знаков и не является нечувствительным к регистру байтом совпадением для элемента в headerNames, возвращается сетевая ошибка.

7. Для каждого unsafeName в именах заголовков запроса CORS-unsafe со списком заголовков запроса, если unsafeName не является совпадением без учета регистра байтов для элемента в headerNames, а режим учетных данных запроса — «include» или headerNames не содержит `*`, вернуть сетевую ошибку.

8. Пусть max-age будет результатом извлечения значений списка заголовков, заданных `Access-Control-Max-Age`, и списка заголовков ответа response.

9. Если max-age является ошибкой или NULL, установите max-age равным 5.

10. Если max-age больше, чем установленный предел max-age, установите max-age равным наложенному пределу.

11. Если пользовательский агент не предоставляет кеш, вернуть ответ response.

12. Для каждого method в methods, для которых существует сопоставление записи кэша метода с использованием запроса request, установите для параметра max-age соответствующей записи значение max-age.

13. Для каждого method в methods, для которых нет соответствия записи кэша метода с использованием запроса request, создайте новую запись кэша с request, max-age, method и null.

14. Для каждого «headerName» в «headerNames», для которого есть совпадение записи в кэше имени заголовка с помощью «request», установите для параметра max-age соответствующей записи значение «max-age».

15. Для каждого «headerName» в «headerNames», для которого нет совпадения записи кэша имени заголовка с использованием запроса, создайте новую запись кеша с request, max-age, null, и headerName.

16. Верните response

8. В противном случае вернуть ошибку сети.

 

4.8 Кеш CORS-предполетный (CORS-preflight cache)

У пользовательского агента есть связанный кеш CORS-preflight (CORS-preflight cache). Кэш предварительной проверки CORS — это список записей кеша.

Запись кеша (cache entry) состоит из:

  • byte-serialized origin (последовательность байтов)
  • URL (URL-адрес)
  • max-age (количество секунд)
  • credentials (логическое значение)
  • method (null, `*`, или метод)
  • header name (null, `*` или название заголовка)

Записи кэша должны быть удалены по прошествии секунд, указанных в их поле максимального возраста, с момента сохранения записи. Записи кеша могут быть удалены до наступления этого момента.

Чтобы создать новую запись кэша (create a new cache entry), учитывая запрос, максимальный возраст, метод и имя заголовка, выполните следующие действия:

1. Пусть entry будет записью кеша, инициализированной следующим образом:

byte-serialized origin

Результат побайтной сериализации источника запроса с request

URL

текущий URL запроса request

max-age

max-age

credentials

Истина, если режим учетных данных запроса — «include«, и ложь в противном случае.

method

method

header name

headerName

2. Добавить запись entry в кеш CORS-preflight пользовательского агента.

 

Чтобы очистить записи кэша (clear cache entries), для данного запроса request удалите все записи кеша в кэше предварительной проверки CORS пользовательского агента, чье байтово-сериализованное происхождение является результатом байтовой сериализации источника запроса с request, а URL-адрес является текущим URL-адресом request.

Запись кэша совпадает с записью кеша entry с запросом request, если байтово-сериализованное происхождение записи entry является результатом побайтовой сериализации источника запроса с request, URL-адрес записи является текущим URL-адресом запроса request, а один из

  • учетные данные записи entry верны
  • учетные данные записи entry являются ложными, а режим учетных данных запроса не является «include«.

это Истина (TRUE)

 

Соответствие записи кэша метода для method, использующего запрос request, происходит, когда в «кэше предварительной проверки CORS» (CORS-preflight cache) пользовательского агента есть запись в кэше, для которой есть совпадение записи кэша с запросом request, а его метод — method или `*`.

 

Если в кэше CORS-предварительной проверки пользовательского агента есть запись кэша заголовка, для которой есть совпадение записи кэша с запросом и одно из

  • его имя заголовка является совпадением для headerName без учета регистра байтов
  • его имя заголовка — `*`, а headerName не является именем заголовка запроса CORS без подстановочных знаков

это Истина (TRUE)

 

4.9 Проверка CORS

Чтобы выполнить проверку CORS для запроса request и ответа response, выполните следующие действия:

1. Пусть origin будет результатом получения `Access-Control-Allow-Origin` из списка заголовков ответа response.
2. Если origin является null, вернуть ошибку.
   Null не является `null`.
3. Если режим учетных данных запроса request не "include", а источник - `*`, вернуть успех.
4. Если результатом побайтной сериализации источника запроса с request не является origin, возвращается ошибка.
5. Если режим учетных данных запроса request не "include", вернуть успех.
6. Пусть учетные данные credentials будут результатом получения `Access-Control-Allow-Credentials` из списка заголовков ответа response.
7. Если учетные данные credentials равны `true`, вернуть успех.
8. Вернуть неудачу.

 

4.10 Проверка TAO

Чтобы выполнить проверку TAO (TAO check) для запроса request и ответа response, выполните следующие действия:

1. Если установлен флаг разрешения времени запроса request на сбой, вернуть ошибку.
2. Если повреждение ответа на запрос request является "basic", вернуть успех.
3. Пусть values будут результатом получения, декодирования и разделения `Timing-Allow-Origin` из списка заголовков ответа response.
4. Если значения values содержат "*", вернуть успех.
5. Если значения values содержат результат сериализации источника запроса с request, вернуть успех.
6. Вернуть неудачу.

 

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("consumed the entire body without keeping the whole thing in memory!"))
   .catch(e => log("something went wrong: " + e))

 

5.1 Класс Headers

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);
boolean has(ByteString name);
undefined set(ByteString name, ByteString value);
iterable<ByteString, ByteString>;
};

В отличие от списка заголовков, объект Headers не может представлять более одного заголовка Set-Cookie. В некотором смысле это проблематично, поскольку, в отличие от всех других заголовков, заголовки Set-Cookie нельзя комбинировать, но поскольку заголовки Set-Cookie не доступны для клиентского JavaScript, это считается приемлемым компромиссом. Реализации могут выбрать более эффективное представление объекта Headers даже для списка заголовков, если они также поддерживают связанную структуру данных для заголовков Set-Cookie.

Пример

Объект Headers можно инициализировать с помощью различных структур данных JavaScript:

var meta = { "Content-Type" : "text/xml", "Breaking-Bad": "<3" }
new Headers(meta)
// Вышеупомянутое эквивалентно
var meta = [
   [ "Content-Type", "text/xml" ],
   [ "Breaking-Bad", "<3" ]
]
new Headers(meta)

Объект Headers имеет связанный список заголовков (header list), который изначально пуст.

Примечание. Это может быть указатель на список заголовков чего-то еще, например, запроса, демонстрируемого объектами Request.

 

У объекта Headers также есть связанная защита (guard), которая является «immutable», «request», «request-no-cors», «response» или «none».

 

Чтобы добавить пару имя/значение name/value к объекту Headers (headers), выполните следующие действия:

1. Нормализовать значение value.
2. Если name не является именем или value не является значением, выбросить TypeError.
3. Если защита заголовков headers "immutable"(неизменяема), бросить TypeError.
4. В противном случае, если защита заголовков headers - "request", а name - запрещенное имя заголовка, вернитесь.
5. В противном случае, если защита заголовков headers - "request-no-cors":
   1. Пусть временное значение temporaryValue будет результатом получения имени name из списка заголовков.
   2. Если temporaryValue равно null, установите temporaryValue в value.
   3. В противном случае установите для параметра «temporaryValue» значение «temporaryValue», за которым следует 0x2C 0x20, за которым следует value.
   4. Если name/temporaryValue не является заголовком запроса, не включенным в список надежных CORS, то вернитесь.
6. В противном случае, если защита заголовков headers - «response», а name - запрещенное имя заголовка ответа, возврат.
7. Добавить name/temporaryValue в список заголовков headers.
8. Если защита заголовков headers - "request-no-cors", удалите из headers привилегированные заголовки без CORS.

 

Чтобы заполнить заголовки headers объекта Headers заданным объектом object, выполните следующие действия:

1. Если object представляет собой последовательность, то для каждого заголовка header в object:
   1. Если заголовок header не содержит ровно два элемента, то выдает ошибку TypeError.
   2. Добавить первый элемент header / второй элемент заголовка header к заголовкам headers.
2. В противном случае object является записью, тогда для каждого keyvalue в object добавьте ключ key/ значение value в заголовки headers.

 

Чтобы удалить привилегированные заголовки запросов без CORS из объекта Headers (headers), выполните следующие действия:

1. Для каждого headerName привилегированных имен заголовков без CORS:
   1. Удалите headerName из списка заголовков headers.

Это вызывается, когда заголовки изменяются непривилегированным кодом.

 

Шаги конструктора новых заголовков new Headers( init ):

1. Установите для этого (this) охранника значение "none".
2. Если указан "init", заполните его this с "init".

 

Шаги метода append (name, value) состоят в том, чтобы добавить к thisname/value.

 

Шаги метода удаления (имени) — delete(name):

1. Если name не является именем, выбросить TypeError.
2. Если охранник (этого this) - "immutable", то выдает ошибку TypeError.
3. В противном случае, если охранник (этого this) - "request", а name - запрещенное имя заголовка, вернитесь.
4. В противном случае, если охранник (этого this) - "request-no-cors", name не является именем заголовка запроса, не включенным в список безопасности CORS, и name не является именем привилегированного заголовка запроса без CORS, вернитесь.
5. В противном случае, если охранник (этого this) - "response", а name - запрещенное имя заголовка ответа, вернитесь.
6. Если список заголовков (этого this) не содержит name, вернитесь.
7. Удалить name из списка заголовков (этого this).
8. Если охранник (этого this) - "request-no-cors", удалите из this заголовки привилегированных запросов без CORS.

 

Шаги метода получения get (name):

1. Если name не является именем, выбросить TypeError.
2. Вернуть результат получения имени name из списка заголовков (этого this).

 

Шаги метода обладания has (name):

1. Если name НЕ является именем, выбросить TypeError.
2. Верните true, если этот список заголовков содержит name; в противном случае - false.

 

Шаги метода установки set (name, value):

1. Нормализовать значение value.
2. Если name не является именем или value не является значением, выбросить TypeError.
3. Если охранник (этого this) - "immutable", бросить TypeError.
4. В противном случае, если охранник (этого this) - "request", а name - запрещенное имя заголовка, вернитесь.
5. В противном случае, если охранник (этого this) - "request-no-cors" и name/value не является заголовком запроса без CORS-safelisted, вернитесь.
6. В противном случае, если охранник (этого this) - "response", а name - запрещенное имя заголовка ответа, вернитесь.
7. Задайте name/value в этом списке заголовков (этого this).
8. Если охранник (этого this) - "request-no-cors", удалите из заголовки привилегированных запросов без CORS из (этого this).

Пары значений для перебора являются возвращаемым значением текущей сортировки и комбинируются с списком заголовков (этого this).

 

5.2 Союзы BodyInit

IDL

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

Чтобы безопасно извлечь из объекта object тело и значение «Content-Type«, выполните следующие действия:

1. Если object является объектом ReadableStream, то:
   1. Утверждение: object не заблокирован и не нарушен.
2. Вернуть результаты извлечения объекта object.

Операция безопасного извлечения (safely extract operation) — это подмножество операции извлечения, которая гарантированно не вызовет исключения.

 

Чтобы извлечь (extract) тело и значение «Content-Type» из объекта object с необязательным флагом keepalive (по умолчанию ложно), выполните следующие действия:

1. Пусть поток stream будет объектом object, если object является объектом ReadableStream; в противном случае результат создания объекта ReadableStream.
2. Пусть Content-Type будет null.
3. Пусть действие action будет null.
4. Пусть источник source будет null, если object является объектом ReadableStream; в противном случае object.
5. Переключите object на:
   Blob
      Установите action для действия, которое читает object.
      Если атрибут type объекта object не является пустой последовательностью байтов, установите Content-Type равным его значению.
   byte sequence (последовательность байтов)
      Установите action для действия, которое возвращает объект object.
   BufferSource
      Установить action для действия, которое возвращает копию байтов, удерживаемых объектом object.
      Поставьте в очередь объект Uint8Array, обертывающий ArrayBuffer, содержащий копию байтов, удерживаемых объектом object, для потоковой передачи stream и закрытия потока stream. Если это вызвало исключение, поток ошибок stream с этим исключением.
   FormData
      Задайте action для действия, которое запускает алгоритм кодирования multipart/form-data, с объектом object в качестве набора данных формы(form data set) и с UTF-8 в качестве явной кодировки символов.
      Установите Content-Type на `multipart/form-data; boundary=`, за которым следует граничная строка multipart/form-data, сгенерированная алгоритмом кодирования multipart/form-data.
   URLSearchParams
      Установите action для действия, которое запускает сериализатор application/x-www-form-urlencoded со списком object.
      Установите Content-Type на `application/x-www-form-urlencoded; charset = UTF-8`.
   scalar value string (строка скалярного значения)
      Установите action для действия, которое запускает кодировку UTF-8 для object.
      Установите Content-Type на `text/plain;charset=UTF-8`.
   ReadableStream
      Если установлен флаг keepalive, бросить TypeError.
      Если object нарушен или заблокирован, выдается ошибка TypeError.
6. Если action НЕ NULL, запустить action параллельно:
   1. Когда один или несколько байтов доступны и поток stream не содержит ошибок, ставьте байты в очередь с учетом доступных байтов и потока stream.
   2. Когда запущенное действие action выполнено, закройте поток stream.
7. Пусть body будет телом, поток которого является stream, а источник - source.
8. Вернуть тело body и Content-Type.

 

5.3 Миксин Body

IDL

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

Форматы, от которых вы не хотели бы, чтобы сетевой уровень зависел, такие как HTML, скорее всего, здесь не будут отображаться. Скорее, API парсера HTML может со временем принять поток.

Объекты, реализующие миксин Body, получают связанное тело (null или тело) и тип MIME (сбой или тип MIME).

Объект, реализующий миксин Body, считается нарушенным, если его тело не NULL и поток его тела нарушен.

Говорят, что объект, реализующий миксин Body, заблокирован, если его тело не NULL и поток его тела заблокирован.

Шаги получателя тела body должны возвращать NULL, если это тело пустое; в противном случае это поток тела.

Шаги получателя bodyUsed должны возвращать «true«, если это (this) нарушено; в противном случае — «false«.

 

Алгоритм данных пакета (package data), заданный байтами bytes, типом type и mimeType, включает тип и выполняет соответствующие шаги:

ArrayBuffer
   Верните новый ArrayBuffer, содержимое которого - bytes.
      Примечание: Выделение ArrayBuffer может вызвать ошибку RangeError.
Blob
   Вернуть Blob-объект, содержимое которого - bytes, а атрибут type - mimeType.
FormData
   Если сущность mimeType - "multipart/form-data", то:
      1. Анализируйте байты bytes, используя значение параметра `boundary` из mimeType, в соответствии с правилами, изложенными в разделе «Возврат значений из форм: multipart/form-data». [RFC7578 #]
      Каждая часть, заголовок которой "Content-Disposition" содержит параметр "filename", должна быть преобразована в запись, значением которой является объект File, содержимое которого является содержимым части. Атрибут "name" объекта File должен иметь значение параметра `filename` части. Атрибут "type" объекта File должен иметь значение заголовка Content-Type части, если у части есть такой заголовок, и значение `text/plain` (значение по умолчанию, определенное [RFC7578] раздел 4.4) в противном случае.
      Каждая часть, чей заголовок "Content-Disposition" не содержит параметра "filename", должна быть проанализирована в запись, значение которой представляет собой кодировку UTF-8 без содержимого спецификации части.
         Это делается независимо от наличия или значения заголовка Content-Type и независимо от наличия или значения параметра charset.
         Часть, заголовок которой Content-Disposition содержит параметр "name" со значением "_charset_", анализируется как любая другая часть. Это не меняет кодировку.
      2. Если по какой-то причине это не удается, бросьте TypeError.
      3. Вернуть новый объект FormData, добавив к записям каждую запись, полученную в результате операции синтаксического анализа.
   Вышеупомянутое является грубым приближением того, что необходимо для `multipart/form-data`, более подробная спецификация синтаксического анализа должна быть написана. Добровольцы приветствуются.
   В противном случае, если сущность mimeType - "application/x-www-form-urlencoded", тогда:
      1. Пусть записи entries будут результатом разбора байтов bytes.
      2. Если записи entries являются ошибкой, то выдает ошибку TypeError.
      3. Вернуть новый объект FormData, записи которого являются entries.
   В противном случае выбросить TypeError.
JSON
   Вернуть результат выполнения синтаксического анализа JSON из байтов в bytes.
text
   Вернуть результат выполнения декодирования UTF-8 по bytes.

 

Алгоритм потребляющего тела (consume body), учитывая объект object и тип type, выполняет следующие шаги:

1. Если объект object нарушен или заблокирован, тогда вернуть обещание, отклоненное с помощью TypeError.
2. Пусть promise будет обещанием, разрешенным с пустой последовательностью байтов.
3. Если тело объекта object не null, то:
   1. Пусть stream будет потоком тела объекта object
   2. Пусть reader будет результатом получения читателя из потока stream. Если это вызвало исключение, верните обещание, отклоненное с этим исключением.
   3. Установите обещание promise на результат чтения всех байтов из потока stream с помощью читателя reader.
4. Пусть шаги steps будут состоять в том, чтобы вернуть результат данных пакета с первым заданным аргументом, типом type и объекта MIME-типом object.
6. Вернуть результат выполнения обещанных шагов steps из promise.

 

Шаги метода arrayBuffer() должны вернуть результат выполнения тела потребления с this и ArrayBuffer.

Шаги метода blob() должны вернуть результат выполнения тела с this и Blob.

Шаги метода formData() должны вернуть результат выполнения тела потребления с this и FormData.

Шаги метода json() должны вернуть результат выполнения тела потребления с this и JSON.

Шаги метода text() должны вернуть результат выполнения тела с this и text.

 

5.4 Класс Request

IDL

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;
   [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;
   any window; // можно установить только на null
};
enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "frame", "iframe", "image", "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" };

«serviceworker» опускается в RequestDestination, так как его нельзя наблюдать из JavaScript. Реализации все равно должны будут поддерживать его как место назначения. «websocket» опускается в RequestMode, поскольку его нельзя использовать или наблюдать из JavaScript.

Объект Request имеет связанный запрос (запрос).

У объекта Request также есть связанные заголовки (null или объект Headers), изначально null.

У объекта Request есть связанный сигнал (объект AbortSignal), первоначально новый объект AbortSignal.

У объекта Request есть тело — это тело его запроса.

 

Для веб-разработчиков

request = new Request( input [, init ])

Возвращает новый запрос request, свойство url которого является input, если input является строкой, и input url, если input является объектом Request.

Аргумент init — это объект, свойства которого могут быть установлены следующим образом:

method

Строка для установки метода method запроса request.

headers

Объект Headers, литерал объекта или массив массивов из двух элементов для установки заголовков headers запроса request.

body

Объект BodyInit или значение null для установки тела запроса request.

referrer

Строка, значение которой является URL-адресом того же происхождения, «about:client» или пустой строкой, для установки реферера запроса request.

referrerPolicy

Политика реферера для установки параметра referrerPolicy запроса request.

mode

Строка, указывающая, будет ли запрос использовать CORS или будет ограничен URL-адресами того же происхождения. Устанавливает режим запроса request — mode.

credentials

Строка, указывающая, будут ли учетные данные отправляться с запросом всегда, никогда или только при отправке на URL-адрес того же происхождения. Устанавливает учетные данные запроса request — credentials.

cache

Строка, указывающая, как запрос будет взаимодействовать с кешем браузера для настройки кеша cache запроса request.

redirect

Строка, указывающая, следует ли запрос за перенаправлениями, приводит ли к ошибке при обнаружении перенаправления или возвращает перенаправление (непрозрачно). Устанавливает перенаправление redirect запроса request.

integrity

Криптографический хэш ресурса, который должен быть получен по запросу. Устанавливает целостность integrity запроса request.

keepalive

Логическое значение для установки активности запроса request — keepalive.

signal

AbortSignal для установки сигнала signal запроса request.

window

Может быть только null. Используется для отделения запроса request от любого окна Window.

 

request . method

Возвращает HTTP-метод запроса, по умолчанию — GET.

request . url

Возвращает URL-адрес запроса в виде строки.

request . headers

Возвращает объект Headers, состоящий из заголовков, связанных с запросом. Обратите внимание, что заголовки, добавленные на сетевом уровне пользовательским агентом, не будут учитываться в этом объекте, например, заголовок «Host«.

request . destination

Возвращает тип ресурса, запрошенного запросом, например, «document» или «script».

request . referrer

Возвращает реферер запроса. Его значением может быть URL-адрес того же происхождения, если он явно задан в init, пустая строка, указывающая на отсутствие реферера, и «about: client», если по умолчанию используется глобальное значение по умолчанию. Это используется во время выборки для определения значения заголовка «Referer» выполняемого запроса.

request . referrerPolicy

Возвращает политику реферера, связанную с запросом. Это используется во время выборки для вычисления значения реферера запроса.

request . mode

Возвращает режим, связанный с запросом, который представляет собой строку, указывающую, будет ли запрос использовать CORS или будет ограничен URL-адресами того же происхождения.

request . credentials

Возвращает режим учетных данных, связанный с запросом, который представляет собой строку, указывающую, будут ли учетные данные отправляться с запросом всегда, никогда или только при отправке на URL-адрес того же источника.

request . cache

Возвращает режим кеширования, связанный с запросом, который представляет собой строку, указывающую, как запрос будет взаимодействовать с кешем браузера при выборке.

request . redirect

Возвращает режим перенаправления, связанный с запросом, который представляет собой строку, указывающую, как перенаправления для запроса будут обрабатываться во время выборки. По умолчанию запрос будет следовать за перенаправлениями.

request . integrity

Возвращает метаданные целостности подресурсов запроса, которые являются криптографическим хешем извлекаемого ресурса. Его значение состоит из нескольких хешей, разделенных пробелом. [SRI]

request . keepalive

Возвращает логическое значение, указывающее, может ли запрос пережить глобал, в котором он был создан.

request . isReloadNavigation

Возвращает логическое значение, указывающее, предназначен ли запрос для перезагрузки навигации.

request . isHistoryNavigation

Возвращает логическое значение, указывающее, предназначен ли запрос для навигации по истории (также известной как обратная навигация).

request . signal

Возвращает сигнал, связанный с запросом, который является объектом AbortSignal, указывающим, был ли запрос прерван, и его обработчиком события прерывания.


 

Шаги конструктора нового запроса new Request (input, init):

1. Пусть запрос request будет null.
2. Пусть fallbackMode будет null.
3. Пусть fallbackCredentials будет null.
4. Пусть baseURL будет (this) базовым URL API соответствующего объекта настроек.
5. Пусть сигнал signal будет null.
6. Если ввод input - это строка, то:
   1. Пусть parsedURL будет результатом синтаксического анализа ввода input с помощью baseURL.
   2. Если parsedURL завершился ошибкой, выбросить TypeError.
   3. Если parsedURL включает учетные данные, выдает ошибку TypeError.
   4. Установите запрос request на новый запрос, URL-адрес которого parsedURL.
   5. Установите для fallbackMode значение "cors".
   6. Установите для fallbackCredentials значение "same-origin".
7. В противном случае:
   1. Утверждение: ввод input - это объект Request.
   2. Установите запрос request на запрос ввода input.
   3. Установите сигнал signal на сигнал ввода input.
8. Пусть origin будет источником этого релевантного объекта настроек.
9. Пусть окно window будет "client".
10. Если окно запроса request является объектом настроек среды и его источник совпадает с origin, тогда установите window как окно запроса request.
11. Если init["window"] существует и не имеет значения null, выбросить TypeError.
12. Если init["window"] существует, то установите для окна window значение "no-window".
13. Установите request на новый запрос со следующими свойствами:
   URL
      текущий URL запроса request.
   method
      метод запроса request.
   header list
      Копия списка заголовков запроса request.
   unsafe-request flag
      Установлен.
   client
      Соответствующий объект настроек этого THIS.
   window
      окно window
   priority
      приоритет запроса request.
   origin
      "client".
   referrer
      реферер запроса request.
   referrer policy
      политика реферера запроса request.
   mode
      режим запроса request.
   credentials mode
      режим учетных данных запроса request.
   cache mode
      режим кеширования запроса request.
   redirect mode
      режим перенаправления запроса request.
   integrity metadata
      метаданные целостности запроса request.
   keepalive flag
      флаг проверки активности запроса request.
   reload-navigation flag
      флаг перезагрузки-навигации запроса request.
   history-navigation flag
      флаг навигации по истории запроса request.
14. Если init не пуст, то:
   1. Если режим запроса request - "navigate", установите его на "same-origin".
   2. Снимите флаг перезагрузки-навигации запроса request.
   3. Снять флаг навигации по истории запроса request.
   4. В качестве реферера запроса request укажите "client"
   5. Задайте для политики реферера запроса request пустую строку.
   Это делается для того, чтобы гарантировать, что когда сервис-воркер «перенаправляет» запрос, например, из изображения в таблице стилей с перекрестным источником, и вносит изменения, он больше не будет исходить из исходного источника (т. е. из перекрестного источника таблицы стилей), но вместо этого от сервис-воркера, который «перенаправил» запрос. Это важно, поскольку исходный источник может даже не генерировать запросы того же типа, что и сервис-воркер. Следовательно, сервисы, которые доверяют первоисточнику, могут быть использованы, если это не сделано, хотя это несколько надумано.
15. Если init["referrer"] существует, то:
   1. Пусть referrer будет init["referrer"].
   2. Если referrer - это пустая строка, установите реферер запроса request как "no-referrer".
   3. В противном случае:
      1. Пусть parsedReferrer будет результатом синтаксического анализа referrer с baseURL.
      2. Если parsedReferrer завершился ошибкой, выбросить TypeError.
      3. Если верно одно из следующих утверждений
            -Флаг parsedReferrer не может быть базовым URL-адресом, схема имеет значение "about", а путь содержит одну строку "client"
            -Источник parsedReferrer не совпадает с источником origin
         затем установите реферер запроса request на "client".
      4. В противном случае установите referer запроса request на проанализированный реферер - parsedReferrer.
16. Если существует init["referrerPolicy"], установите для него политику реферера запроса request.
17. Пусть mode будет init["mode"], если он существует, и fallbackMode в противном случае.
18. Если режим mode является "navigate", то выдает ошибку TypeError.
19. Если mode не null, установите режим запроса в mode.
20. Пусть учетные данные credentials будут init["credentials"], если они существуют, и fallbackCredentials в противном случае.
21. Если учетные данные credentials не null, установите режим учетных данных запроса request на credentials.
22. Если существует init["cache"], установите для него режим кеширования запроса request.
23. Если режим кеширования запроса request - "only-if-cached", а режим запроса request - НЕ "same-origin", то выдается ошибка TypeError.
24. Если существует init["redirect"], установите для него режим перенаправления запроса request.
25. Если существует init["integrity"], установите для него метаданные целостности запроса request.
26. Если init["keepalive"] существует, тогда установите флаг "keepalive" запроса, если init["keepalive"] истинно, и снимите его в противном случае.
27. Если init["method"] существует, то:
   1. Пусть method будет init["method"].
   2. Если method не является методом или method является запрещенным, то выдает ошибку TypeError.
   3. Нормализовать method
   4. Установите для метода запроса request значение method.
28. Если существует init["signal"], установите для него signal.
29. Установите запрос (этого this) на request.
30. Если сигнал signal не null, сделайте так, чтобы сигнал (этого this) следовал за сигналом signal.
31. Задайте для (этого this) заголовки как новый объект Headers, список заголовков которого является списком заголовков запроса request, а защита - "request".
32. Если режим запроса - "no-cors", то:
   1. Если метод (этого this) запроса не входит в список надежных отправителей CORS, то выдает ошибку TypeError.
   2. Установите для (этого this) защиты заголовков значение "request-no-cors".
33. Если init не пуст, то:
      Заголовки очищаются, так как они могут содержать заголовки, недопустимые в этом режиме. В противном случае они были ранее очищены или не изменились с момента создания с помощью привилегированного API.
   1. Пусть заголовки headers будут копией заголовка (этого this) и связанного с ним списка заголовков.
   2. Если существует init["headers"], установите заголовки headers в значение init["headers"].
   3. Очистите заголовки этого this из списка заголовков.
   4. Если заголовки headers являются объектом Headers, то для каждого заголовка header в его списке заголовков добавьте "имя header/значение header" к заголовкам (этого this).    5. В противном случае заполните заголовки (этого this) с headers.
34. Пусть inputBody будет телом запроса input, если input является объектом Request, ... и null в противном случае.
35. Если либо init["body"] существует и не имеет значения null, либо inputBody не равно null, а метод запроса - `GET` или`HEAD`, то выдает ошибку TypeError.
36. Пусть body будет inputBody.
37. Если init["body"] существует и не имеет значения null, то:
   1. Пусть Content-Type будет null.
   2. Если init["keepalive"] существует и имеет значение true, тогда установите body и Content-Type равными результату извлечения init["body"] с установленным флагом "keepalive".
   3. В противном случае установите body и Content-Type равными результату извлечения init["body"].
   4. Если Content-Type не равно null и список заголовков (этого this) не содержит "Content-Type", добавьте к заголовкам (этого this) `Content-Type`/Content-Type.
38. Если тело body не равно null и источник тела body равен null, то:
   1. Если режим запроса (этого this) не совпадает ни с "same-origin", ни с "cors", то выдает ошибку TypeError.
   2. Установите для запроса (этого this) флаг "use-CORS-preflight".
39. Если inputBody - это тело body, а ввод нарушен или заблокирован, то бросить TypeError.
40. Если inputBody - это тело body и inputBody не null, то:
   1. Пусть ws и rs будут записываемой стороной и читаемой стороной потока преобразования идентичности соответственно.
   2. Пусть обещание promise будет результатом вызова:  ReadableStreamPipeTo(inputBody, ws, false, false, false, undefined).
      Это делает поток inputBody заблокированным и немедленно прерывается.
   3. Установите promise.[[PromiseIsHandled]] на значение true.
   4. Установите body в новое тело, поток которого равен rs, источник которого - источник inputBody, а общее количество байтов - это общее количество байтов inputBody.
41. Установите тело запроса (этого this) в тело body.
42. Задайте для типа MIME (этого this) результат извлечения типа MIME из списка заголовков этого запроса.

 

Шаги получателя method должны вернуть этот this метод запроса.

Этапы получения url должны вернуть URL-адрес этого this запроса, сериализованный.

Шаги получателя headers должны возвращать эти this заголовки.

Получатель destination должен вернуть место назначения этого this запроса.

Шаги получения реферера referrer:

1. Если реферер этого this запроса - "no-referrer", вернуть пустую строку.
2. Если реферер этого this запроса - "client", верните "about: client".
3. Верните сериализованный реферер этого this запроса.

Шаги получателя referrerPolicy должны вернуть политику реферера этого this запроса.

Шаги получателя mode должны вернуть режим этого this запроса.

Шаги получателя credentials должны вернуть режим учетных данных этого this запроса.

Действия получателя cache должны вернуть режим кеширования этого this запроса.

Шаги получателя redirect должны вернуть режим перенаправления этого this запроса.

Этапы получения данных integrity должны вернуть метаданные целостности этого this запроса.

Шаги получателя keepalive должны возвращать true, если установлен флаг keepalive этого this запроса; в противном случае — ложь false.

Шаги получателя isReloadNavigation должны вернуть значение true, если установлен флаг reload-navigation этого this запроса; в противном случае — ложь false.

Шаги получателя isHistoryNavigation должны вернуть значение true, если установлен флаг навигации по истории этого this запроса; в противном случае — ложь false.

Шаги получателя signal должны вернуть этот this сигнал.

 

Шаги метода клонирования clone():

1. Если это this нарушено или заблокировано, выбросить TypeError.
2. Пусть clonedRequestObject будет новым объектом Request.
3. Пусть clonedRequest будет результатом клонирования этого this запроса.
4. Установите для запроса clonedRequestObject значение clonedRequest.
5. Задайте заголовки clonedRequestObject для нового объекта Headers со следующими свойствами:
   header list
      список заголовков clonedRequest
   guard
      защита заголовков этого this.
6. Сделайте так, чтобы сигнал clonedRequestObject следовал за сигналом этого this .
7. Верните 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);
   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 также есть связанные заголовки headers (null или объект Headers), изначально null.

Тело объекта Response — это его тело ответа.

 

Шаги конструктора нового ответа new Response (body, init):

1. Если init["status"] не находится в диапазоне от 200 до 599 включительно, то бросить RangeError.
2. Если init["statusText"] не соответствует созданию токена фразы-причины, то выдает ошибку TypeError.
3. Установите этот this ответ на новый ответ.
4. Задайте для заголовков этого this новый объект Headers, список заголовков которого является списком заголовков ответа r, а защита - "response".
5. Установите для статуса ответа этого this init["status"].
6. Установите для сообщения статуса ответа этого this init["statusText"].
7. Если существует init["headers"], заполните заголовки этого this - init["headers"].
8. Если body не null, то:
   1. Если init["status"] является null статусом тела, то выбросить TypeError.
      (101 включен в статус нулевого тела из-за его использования в другом месте. Это не влияет на этот шаг.)
   2. Пусть Content-Type будет null.
   3. Задайте для тела ответа этого this и Content-Type результат извлечения тела body.
   4. Если Content-Type не null и список заголовков этого this ответа не содержит `Content-Type`, тогда добавьте `Content-Type`/ Content-Type к списку заголовков ответа этого this.
9. Задайте для типа MIME этого this результат извлечения типа MIME из списка заголовков ответа этого this.

 

Шаги статического метода ошибки error():

1. Пусть ответ r будет новым объектом Response, ответом которого является новая сетевая ошибка.
2. Установите заголовки r в новый объект Headers, защита которого "immutable".
3. Верните ответ r

 

Шаги метода статического перенаправления redirect(url, status):

1. Пусть parsedURL будет результатом синтаксического анализа url с базовым URL API текущего объекта настроек.
2. Если parsedURL завершился ошибкой, выбросить TypeError.
3. Если status не является статусом перенаправления, бросить RangeError.
4. Пусть ответ r будет новым объектом Response, ответ которого является новым ответом.
5. Установите заголовки r в новый объект Headers, защита которого "immutable".
6. Установите статус ответа r на status.
7. Пусть значение value будет parsedURL, сериализовано и изоморфно закодировано.
8. Добавьте `Location` / value в список заголовков ответа r.
9. Вернуть r

 

Шаги получателя type должны вернуть этот this тип ответа.

Этапы получения url должны вернуть пустую строку, если URL-адрес этот this ответа равен нулю; в противном случае URL-адрес этот this ответа, сериализованный с установленным флагом «exclude-fragment». [URL]

Шаги получателя redirected должны вернуть значение true, если в списке URL-адресов ответа этого this более одного элемента; в противном случае — false.

Чтобы отфильтровать ответы, являющиеся результатом перенаправления, сделайте это напрямую через API, например, fetch (url, {redirect: «error»}). Таким образом, потенциально опасный ответ не может случайно просочиться.

Этапы получения status должны вернуть статус ответа этого this.

Шаги получателя ok должны вернуть true, если статус ответа этого thisok; в противном случае — false.

Шаги получателя statusText должны вернуть статусное сообщение ответа этого this.

Шаги получателя headers должны возвращать заголовки этого this.

 

Шаги метода клонирования clone():

1. Если это this нарушено или заблокировано, выбросить TypeError.
2. Пусть clonedResponseObject будет новым объектом Response.
3. Пусть clonedResponse будет результатом клонирования этого this ответа.
4. Установите для ответа clonedResponseObject значение clonedResponse.
5. Установите заголовки clonedResponseObject на новый объект Headers, чей список заголовков установлен на список заголовков clonedResponse, а guard - этого this защита заголовков.
6. Верните clonedResponseObject.
7. Вернуть clonedResponse.

 

5.6 Метод Fetch

IDL

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

Шаги метода выборки fetch (input, init):

1. Пусть p будет новым обещанием (Promise).
2. Пусть объект запроса requestObject будет результатом вызова начального значения объекта Request в качестве конструктора с аргументами input и init. Если это вызывает исключение, отклоните (reject) p с ним и верните p.
3. Пусть request будет requestObject запроса.
4. Если установлен флаг прерывания сигнала requestObject, то:
   1. Отменить выборку с  p, request и null.
   2. Вернуть обещание p.
5. Если глобальный объект клиента запроса request является объектом ServiceWorkerGlobalScope, то установите для режима рабочих служб запроса request значение "none".
6. Пусть responseObject будет новым объектом Response и новым связанным объектом Headers, защита которого "immutable".
7. Пусть locallyAborted будет ложным (false).
Это позволяет нам отклонять обещания с предсказуемым временем, когда запрос на прерывание исходит из того же потока, что и вызов выборки.
8. Добавьте следующие шаги прерывания в сигнал requestObject:
   1. Установите для locallyAborted значение true.
   2. Прервать выборку с  p, request и responseObject.
   3. Завершите текущую выборку с установленным флагом прерывания.
9. Параллельно выполните следующее:
   Fetch request
   Чтобы обработать ответ для response, выполните следующие подэтапы:
      1. Если localAborted истинно true, прекратите эти подшаги.
      2. Если установлен флаг прерывания ответа response, прервите выборку с p, request и responseObject и завершите эти подшаги.
      3. Если ответом response является сетевая ошибка, отклоните p с помощью TypeError и завершите эти подшаги.
      4. Свяжите responseObject с ответом response.
      5. Разрешите (Resolve) обещание p с responseObject.
10. Верните обещание p.

 

Чтобы прервать выборку (abort fetch) с помощью обещания promise, запроса request и объекта ответа responseObject, выполните следующие действия:

1. Пусть ошибка error будет исключением DOMException "AbortError".
2. Отклонить (Reject) обещание promise с ошибкой error.
   Это невозможно, если обещание уже выполнено (статус fulfilled).
3. Если тело запроса request не null и доступно для чтения, тогда необходимо отменить тело request с error.
4. Если объект ответа responseObject имеет значение null, тогда вернуть.
5. Пусть response будет ответом responseObject.
6. Если тело ответа response не null и доступно для чтения, тогда ошибочное тело ответа response с error.

 

5.7 Сборка мусора

Пользовательский агент может прекратить текущую выборку, если это завершение не наблюдается с помощью сценария.

«Наблюдаемый через скрипт» (Observable through script) означает наблюдаемый через аргументы и возвращаемое значение fetch(). Другие способы, такие как связь с сервером через побочный канал, не включены.

Сервер, способный наблюдать за сборкой мусора, имеет прецедент, например, с объектами WebSocket и XMLHttpRequest.

 

Примеры

Пользовательский агент может прекратить выборку, потому что прекращение не может быть соблюдено.

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

Пользовательский агент не может прекратить выборку, потому что прекращение можно наблюдать через обещание.

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

Пользовательский агент может прекратить выборку, потому что связанное тело не наблюдается.

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

Пользовательский агент может прекратить выборку, потому что прекращение не может быть соблюдено.

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

Пользовательский агент не может завершить выборку, потому что можно наблюдать завершение, зарегистрировав обработчик для объекта обещания.

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

Пользовательский агент не может завершить выборку, так как завершение будет наблюдаться через зарегистрированный обработчик.

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

(Приведенные выше примеры ненаблюдаемости предполагают, что встроенные свойства и функции, такие как body.getReader(), не были перезаписаны.)

 

6. Изменения протокола WebSocket

Этот раздел заменяет часть требования клиента к открытию рукопожатия протокола WebSocket, чтобы интегрировать его с алгоритмами, определенными в Fetch. Таким образом, CSP, файлы cookie, HSTS и другие протоколы, связанные с Fetch, обрабатываются в одном месте. В идеале RFC следует обновить с использованием этого языка, но это никогда не бывает так просто. API WebSocket, определенный в стандарте HTML, был обновлен для использования этого языка. [WSP] [HTML]

Это работает путем замены алгоритма «установить соединение WebSocket» в протоколе WebSocket на новый, который интегрируется с Fetch. «Установить соединение WebSocket» состоит из трех алгоритмов:

  1. установка соединения,
  2. создание и передача запроса на установление связи и
  3. проверка ответа на установление связи.

Это расслоение отличается от Fetch, который сначала создает рукопожатие, затем устанавливает соединение и передает рукопожатие и, наконец, проверяет ответ. Имейте это в виду, читая эти изменения.

 

6.1 Соединения

Чтобы получить соединение WebSocket по URL-адресу, выполните следующие действия:

1. Пусть host будет хостом url.
2. Пусть port будет портом url.
3. Пусть secure имеет значение false, если схема url - "http", и true в противном случае.
4. Следуйте требованиям, изложенным в шагах 2–5 включительно, первого набора шагов в разделе 4.1 протокола WebSocket, чтобы установить соединение WebSocket. [WSP]
5. Если это установило соединение, верните его, в противном случае верните ошибку.

Хотя соединение WebSocket немного отличается по своей структуре, имеет разные свойства и, следовательно, не может использоваться совместно, оно очень близко к «обычному» соединению.

6.2 Открытие рукопожатия

Чтобы установить соединение WebSocket с учетом url, протоколов protocols и клиента client, выполните следующие действия:

1. Пусть requestURL будет копией url со схемой "http", если схема url - "ws", и "https" в противном случае.
   Это изменение схемы необходимо для хорошей интеграции с выборкой. Например, HSTS не работал бы без него. У WebSocket нет реальной причины иметь отдельные схемы, это устаревший артефакт. [HSTS]
2. Пусть request будет новым запросом, URL которого - requestURL, клиент - client, режим сервисных рабочих - "none", реферер - "no-referrer", установлен синхронный флаг, режим - "websocket", режим учетных данных - "include" , режим кеширования - "no-store", а режим перенаправления - "error".
3. Добавьте `Upgrade` / ` websocket` в список заголовков запроса request.
4. Добавьте `Connection` / ` Upgrade` в список заголовков запроса request.
5. Пусть keyValue будет одноразовым идентификатором, состоящим из случайно выбранного 16-байтового значения, которое было закодировано с прощающей базой64 и изоморфно закодировано.
   Пример:
      Если бы случайно выбранным значением была последовательность байтов 0x01 0x02 0x03 0x04 0x05 0x06 0x07 0x08 0x09 0x0a 0x0b 0x0c 0x0d 0x0e 0x0f 0x10, keyValue будет закодирован в формате прощающего base64 как "AQIDBAUGBwgJCgsMDQ4PEC==" и изоморфно закодирован как `AQIDBAUGBwgJCgsMDQ4PEC==`.
6. Добавьте `Sec-WebSocket-Key`/ keyValue в список заголовков запроса request.
7. Добавьте `Sec-WebSocket-Version`/ `13` к списку заголовков запроса request.
8. Для каждого протокола protocol в протоколах protocols объедините `Sec-WebSocket-Protocol`/ protocol в списке заголовков запроса request.
9. Пусть permessageDeflate будет значением заголовка расширения "permessage-deflate", определяемым пользовательским агентом. [WSP]
   Пример: 
      `permessage-deflate; client_max_window_bits`
10. Добавьте `Sec-WebSocket-Extensions` / permessageDeflate в список заголовков запроса request.
11. Пусть ответ response будет результатом получения выборки запроса request.
12. Если response является сетевой ошибкой или его статус не равен 101, не удаётся установить соединение WebSocket.
13. Если протоколы protocols не являются пустым списком и извлечение значений списка заголовков с заданным `Sec-WebSocket-Protocol` и списком заголовков ответа приводит к null, ошибке или пустой последовательности байтов, тогда соединение WebSocket не устанавливается.
   Это отличается от проверки этого заголовка, определенной протоколом WebSocket. Это касается только подпротокола, не запрошенного клиентом. Это касается подпротокола, запрошенного клиентом, но не подтвержденного сервером.
14. Выполните требования, указанные с шагов 2 по 6 включительно, из последнего набора шагов в разделе 4.1 протокола WebSocket для проверки ответа response. Это либо приводит к сбою соединения WebSocket, либо соединение WebSocket установлено.

 

Ошибка соединения WebSocket и установка соединения WebSocket определяются протоколом WebSocket. [WSP]

 

ОПАСНОСТЬ!!!

Причина, по которой перенаправления не соблюдаются, и это рукопожатие, как правило, ограничено, заключается в том, что это может привести к серьезным проблемам безопасности в контексте веб-браузера. Например, рассмотрим хост с сервером WebSocket на одном пути и открытым HTTP-перенаправителем на другом. Внезапно любой сценарий, которому может быть присвоен конкретный URL-адрес WebSocket, может быть обманут для связи (и, возможно, обмена секретами) с любым хостом в Интернете, даже если сценарий проверяет, что URL-адрес имеет правильное имя хоста.

 

7. data: URL-адреса

Информативное описание data: URL-адреса см. В RFC 2397. Этот раздел заменяет нормативные требования RFC к обработке для обеспечения совместимости с развернутым контентом. [RFC2397]

Структура URL-адреса «data:» — это структура, состоящая из типа MIME (тип MIME) и тела (байтовой последовательности).

Обработчик URL «data:» принимает URL-адрес dataURL и затем выполняет следующие действия:

1. Утверждение: схема dataURL является "data".
2. Пусть input будет результатом запуска сериализатора URL-адресов на dataURL с установленным флагом исключения фрагмента (exclude fragment flag).
3. Удалите из ввода input начальную строку "data:".
4. Пусть позиция position указывает на начало ввода input.
5. Пусть mimeType будет результатом сбора последовательности кодовых точек, которые не равны U+002C (,), для данной позиции position.
6. Удалите начальные и конечные пробелы ASCII из mimeType.
   Это удалит только кодовые точки U+0020 SPACE, если таковые имеются.
7. Если позиция position превышает конец ввода input, вернуть ошибку.
8. Продвинуть позицию position на 1.
9. Пусть encdedBody будет остатком ввода input.
10. Пусть body будет процентом декодирования encodedBody.
11. Если mimeType заканчивается на U+003B (;), за которым следует ноль или более U+0020 SPACE, за которым следует соответствие ASCII без учета регистра для "base64", то:
   1. Пусть stringBody будет изоморфным декодированием тела.
   2. Устанавливает тело body на декодирование прощающего base64 для stringBody.
   3. Если тело body повреждено, вернуть отказ.
   4. Удалите последние 6 кодовых точек из mimeType.
   5. Удалите завершающие кодовые точки U+0020 SPACE из mimeType, если таковые имеются.
   6. Удалите последнюю кодовую точку U+003B (;) из mimeType.
12. Если mimeType начинается с U+003B (;), тогда добавьте "text/plain" к mimeType.
13. Пусть mimeTypeRecord будет результатом синтаксического анализа mimeType.
14. Если mimeTypeRecord завершился ошибкой, установите для mimeTypeRecord значение: "text/plain;charset=US-ASCII"
15. Вернуть новые структуру URL data: , MIME-тип которой - mimeTypeRecord, а тело - body.

 

Фоновое чтение

Этот раздел и его подразделы носят информативный характер.

 

Разделение слоя заголовка HTTP

Для целей выборки существует уровень API (img HTML, background-image CSS), уровень ранней выборки, уровень сервис-воркера, а также уровень сети и кеша. `Accept` и `Accept-Language` устанавливаются на уровне ранней выборки (обычно пользовательским агентом). Большинство других заголовков, управляемых пользовательским агентом, таких как `Accept-Encoding`, `Host` и `Referer`, устанавливаются на уровне сети и кеша. Разработчики могут устанавливать заголовки либо на уровне API, либо на уровне работника службы (обычно через объект Request). Разработчики почти не контролируют запрещенные заголовки, но могут управлять `Accept` и иметь средства, например, для ограничения и пропуска `Referer`.

 

Атомарная обработка перенаправления HTTP

Перенаправления (ответ, статус или статус внутреннего ответа (если есть) является статусом перенаправления) не предоставляются API. Раскрытие переадресации может привести к утечке информации, недоступной другим способом в результате атаки межсайтового сценария.

Пример

Выборка на «https://example.org/auth«, которая включает Cookie с пометкой HttpOnly, может привести к перенаправлению на «https://other-origin.invalid/4af955781ea1c84a3b11«. Этот новый URL-адрес содержит секрет. Если мы раскроем перенаправления, этот секрет будет доступен через атаку межсайтового скриптинга.

 

Базовая безопасная настройка протокола CORS

Для ресурсов, где данные защищены с помощью IP-аутентификации или брандмауэра (к сожалению, все еще довольно часто), использование протокола CORS небезопасно. (Это причина, по которой пришлось изобрести протокол CORS.)

Однако в противном случае безопасно использовать следующий заголовок:

Access-Control-Allow-Origin: *

Даже если ресурс предоставляет дополнительную информацию на основе файлов cookie или HTTP-аутентификации, использование вышеуказанного заголовка не покажет ее. Он будет делиться ресурсом с такими API, как XMLHttpRequest, так же, как он уже используется curl и wget.

Таким образом, другими словами, если к ресурсу невозможно получить доступ с случайного устройства, подключенного к сети с помощью curl и wget, вышеупомянутый заголовок не должен быть включен. Однако, если к нему можно получить доступ, это нормально.

 

CORS протокол и HTTP кеши

Если требования протокола CORS более сложны, чем установка `Access-Control-Allow-Origin` на * или статическое происхождение, следует использовать `Vary`. [HTML] [HTTP] [HTTP-SEMANTICS] [HTTP-COND] [HTTP-CACHING] [HTTP-AUTH]

Vary: Origin

В частности, подумайте, что произойдет, если Vary не используется и сервер настроен на отправку Access-Control-Allow-Origin для определенного ресурса только в ответ на запрос CORS. Когда пользовательский агент получает ответ на запрос, не связанный с CORS, для этого ресурса (например, в результате запроса навигации), в ответе не будет `Access-Control-Allow-Origin`, и пользовательский агент будет кэшировать этот ответ. . Затем, если пользовательский агент впоследствии встречает запрос CORS для ресурса, он будет использовать этот кэшированный ответ из предыдущего запроса, отличного от CORS, без `Access-Control-Allow-Origin`.

Но если `Vary: Origin` используется в том же сценарии, который описан выше, это заставит пользовательский агент получить ответ, который включает`Access-Control-Allow-Origin`, вместо того, чтобы использовать кешированный ответ от предыдущего не-CORS запрос, в котором отсутствует `Access-Control-Allow-Origin`.

Однако, если для параметра Access-Control-Allow-Origin установлено значение * или статическое происхождение для определенного ресурса, настройте сервер так, чтобы он всегда отправлял Access-Control-Allow-Origin в ответах для ресурса — для не-CORS запросов, а также запросы CORS — и не используйте Vary.

 

Благодарности

Спасибо Adam Barth, Adam Lavin, Alan Jeffrey, Alexey Proskuryakov, Andrés Gutiérrez, Andrew Sutherland, Ángel González, Anssi Kostiainen, Arkadiusz Michalski, Arne Johannessen, Artem Skoretskiy, Arthur Barstow, Asanka Herath, Axel Rauschmayer, Ben Kelly, Benjamin Gruenbaum, Benjamin Hawkes-Lewis, Bert Bos, Björn Höhrmann, Boris Zbarsky, Brad Hill, Brad Porter, Bryan Smith, Caitlin Potter, Cameron McCormack, 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, François Marier, Frank Ellerman, Frederick Hirsch, Gary Blackwood, Gavin Carothers, Glenn Maynard, Graham Klyne, Gregory Terzian, 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, Janusz Majnert, Jeena Lee, Jeff Carpenter, Jeff Hodges, Jeffrey Yasskin, Jesse M. Heines, Jianjun Chen, Jinho Bang, Jochen Eisinger, John Wilander, Jonas Sicking, Jonathan Kingston, Jonathan Watt, 최종찬 (Jongchan Choi), Jörn Zaefferer, Joseph Pecoraro, Josh Matthews, Julian Krispel-Samsel, Julian Reschke, 송정기 (Jungkee Song), Jussi Kalliokoski, Jxck, Kagami Sascha Rosylight, Keith Yeung, Kenji Baheux, Lachlan Hunt, Larry Masinter, Liam Brummitt, Louis Ryan, 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 Thomson, Matt Andrews, Matt Falkenhagen, 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, Nikhil Marathe, Nikki Bee, Nikunj Mehta, Odin Hørthe Omdal, Ondřej Žára, O. Opsec, Perry Jiang, Philip Jägenstedt, R. Auburn, Raphael Kubo da Costa, Rondinelly, Rory Hewitt, Ryan Sleevi, Sébastien Cevey, Sendil Kumar N, Shao-xuan Kang, Sharath Udupa, Shivakumar Jagalur Matt, Shivani Sharma, Sigbjørn Finne, Simon Pieters, Simon Sapin, Srirama Chandra Sekhar Mogali, Stephan Paul, Steven Salat, Sunava Dutta, Surya Ismail, Takashi Toyoshima, 吉野剛史 (Takeshi Yoshino), Thomas Roessler, Thomas Steiner, Thomas Wisniewski, Tiancheng «Timothy» Gu, Tobie Langel, Tom Schuster, Tomás Aparicio, 保呂毅 (Tsuyoshi Horo), Tyler Close, Ujjwal Sharma, Vignesh Shanmugam, Vladimir Dzhuvinov, Wayne Carr, Xabier Rodríguez, Yehuda Katz, Yoav Weiss, Youenn Fablet, 平野裕 (Yutaka Hirano) и Zhenbin Xu за то, что они классные.

Этот стандарт написан Анн ван Кестерен (Mozilla, annevk@annevk.nl).

Авторские права © WHATWG (Apple, Google, Mozilla, Microsoft). Эта работа находится под международной лицензией Creative Commons Attribution 4.0.

 

Индекс

Термины, определенные в этой спецификации

Термины, определенные ссылкой

Ссылки

Нормативные ссылки

[ABNF]
D. Crocker, Ed.; P. Overell. Augmented BNF for Syntax Specifications: ABNF. January 2008. Internet Standard. URL: https://tools.ietf.org/html/rfc5234

[COOKIES]
A. Barth. HTTP State Management Mechanism. April 2011. Proposed Standard. URL: https://httpwg.org/specs/rfc6265.html

[CSP]
Mike West. Content Security Policy Level 3. URL: https://w3c.github.io/webappsec-csp/

[DOM]
Anne van Kesteren. DOM Standard. Living Standard. URL: https://dom.spec.whatwg.org/

[ENCODING]
Anne van Kesteren. Encoding Standard. Living Standard. URL: https://encoding.spec.whatwg.org/

[FILEAPI]
Marijn Kruisselbrink; Arun Ranganathan. File API. URL: https://w3c.github.io/FileAPI/

[HEADER-STRUCTURE]
Mark Nottingham; Poul-Henning Kamp. Structured Field Values for HTTP. URL: https://tools.ietf.org/html/draft-ietf-httpbis-header-structure

[HSTS]
J. Hodges; C. Jackson; A. Barth. HTTP Strict Transport Security (HSTS). November 2012. Proposed Standard. URL: https://tools.ietf.org/html/rfc6797

[HTML]
Anne van Kesteren; et al. HTML Standard. Living Standard. URL: https://html.spec.whatwg.org/multipage/

[HTTP]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Message Syntax and Routing. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7230.html

[HTTP-AUTH]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Authentication. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7235.html

[HTTP-CACHING]
R. Fielding, Ed.; M. Nottingham, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Caching. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7234.html

[HTTP-COND]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Conditional Requests. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7232.html

[HTTP-SEMANTICS]
R. Fielding, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Semantics and Content. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7231.html

[INFRA]
Anne van Kesteren; Domenic Denicola. Infra Standard. Living Standard. URL: https://infra.spec.whatwg.org/

[MIMESNIFF]
Gordon P. Hemsley. MIME Sniffing Standard. Living Standard. URL: https://mimesniff.spec.whatwg.org/

[MIX]
Mike West. Mixed Content. URL: https://w3c.github.io/webappsec-mixed-content/

[REFERRER]
Jochen Eisinger; Emily Stark. Referrer Policy. URL: https://w3c.github.io/webappsec-referrer-policy/

[REPORTING]
Douglas Creager; et al. Reporting API. URL: https://w3c.github.io/reporting/

[RFC7405]
P. Kyzivat. Case-Sensitive String Support in ABNF. December 2014. Proposed Standard. URL: https://tools.ietf.org/html/rfc7405

[RFC7578]
L. Masinter. Returning Values from Forms: multipart/form-data. July 2015. Proposed Standard. URL: https://tools.ietf.org/html/rfc7578

[RFC959]
J. Postel; J. Reynolds. File Transfer Protocol. October 1985. Internet Standard. URL: https://tools.ietf.org/html/rfc959

[SRI]
Devdatta Akhawe; et al. Subresource Integrity. URL: https://w3c.github.io/webappsec-subresource-integrity/

[STALE-WHILE-REVALIDATE]
M. Nottingham. HTTP Cache-Control Extensions for Stale Content. May 2010. Informational. URL: https://httpwg.org/specs/rfc5861.html

[STREAMS]
Adam Rice; Domenic Denicola; 吉野剛史 (Takeshi Yoshino). Streams Standard. Living Standard. URL: https://streams.spec.whatwg.org/

[SW]
Alex Russell; et al. Service Workers 1. URL: https://w3c.github.io/ServiceWorker/

[TLS]
E. Rescorla. The Transport Layer Security (TLS) Protocol Version 1.3. August 2018. Proposed Standard. URL: https://tools.ietf.org/html/rfc8446

[UPGRADE]
Mike West. Upgrade Insecure Requests. URL: https://w3c.github.io/webappsec-upgrade-insecure-requests/

[URL]
Anne van Kesteren. URL Standard. Living Standard. URL: https://url.spec.whatwg.org/

[WEBIDL]
Boris Zbarsky. Web IDL. URL: https://heycam.github.io/webidl/

[WSP]
I. Fette; A. Melnikov. The WebSocket Protocol. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6455

[XHR]
Anne van Kesteren. XMLHttpRequest Standard. Living Standard. URL: https://xhr.spec.whatwg.org/

Информационные ссылки

[EXPECT-CT]
Emily Stark. Expect-CT Extension for HTTP. URL: https://tools.ietf.org/html/draft-ietf-httpbis-expect-ct-02

[HTTP-RANGE]
R. Fielding, Ed.; Y. Lafon, Ed.; J. Reschke, Ed.. Hypertext Transfer Protocol (HTTP/1.1): Range Requests. June 2014. Proposed Standard. URL: https://httpwg.org/specs/rfc7233.html

[HTTPVERBSEC1]
Multiple vendors’ web servers enable HTTP TRACE method by default.. URL: https://www.kb.cert.org/vuls/id/867593

[HTTPVERBSEC2]
Microsoft Internet Information Server (IIS) vulnerable to cross-site scripting via HTTP TRACK method.. URL: https://www.kb.cert.org/vuls/id/288308

[HTTPVERBSEC3]
HTTP proxy default configurations allow arbitrary TCP connections.. URL: https://www.kb.cert.org/vuls/id/150227

[OCSP]
S. Santesson; et al. X.509 Internet Public Key Infrastructure Online Certificate Status Protocol — OCSP. June 2013. Proposed Standard. URL: https://tools.ietf.org/html/rfc6960

[ORIGIN]
A. Barth. The Web Origin Concept. December 2011. Proposed Standard. URL: https://tools.ietf.org/html/rfc6454

[RFC2397]
L. Masinter. The «data» URL scheme. August 1998. Proposed Standard. URL: https://tools.ietf.org/html/rfc2397

 

Индекс 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);
   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<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;
[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;
any window; // can only be set to null
};
enum RequestDestination { "", "audio", "audioworklet", "document", "embed", "font", "frame", "iframe", "image", "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" };
[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);
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 = {});
};