Краткий обзор

Данная спецификация определяет API для открытия HTTP-соединения с целью получения push-уведомлений от сервера в форме DOM-событий. API спроектировано так, чтобы его можно было бы расширить для работы с другими схемами push-уведомлений, такими как Push SMS.

Статус этого документа

Этот раздел описывает статус этого документа в момент его публикации. Другие документы могут заменить этот документ. Список текущих публикаций W3C и самая последняя, официально опубликованная ревизия этого технического документа могут быть найдены в каталоге технических документов W3C на http://www.w3.org/TR/.

Если вы хотите добавить комментарии относительно этого документа, то вы можете ввести отзыв, используя эту форму:

Feedback Comments

Please don't use section numbers as these tend to change rapidly and make your feedback harder to understand.

(Note: Your IP address and user agent will be publicly recorded for spam prevention purposes.)

Вы также можете послать отзыв по почте на public-webapps@w3.org (подписаться, архивы) или на whatwg@whatwg.org (подписаться, архивы). Приветствуется любые замечания.

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

Последняя стабильная версия авторского черновика данной спецификации всегда доступна на CVS-сервере W3C и в Subversion-репозитории WHATWG. Последняя рабочая копия от автора (которая может содержать незаконченный текст в процессе подготовки) содержит последний черновой вариант данной спецификации (помимо прочего). Для более подробной информации, пожалуйста, см. WHATWG FAQ.

Уведомления об изменениях данной спецификации, вместе с уведомлениями об изменениях родственных спецификаций, публикуются посредством следующих механизмов:

Уведомления об изменениях по e-mail
Лист рассылки Commit-Watchers (полные diff-ы исходников): http://lists.whatwg.org/listinfo.cgi/commit-watchers-whatwg.org
Браузерный вариант всех изменений VCS:
CVSWeb-интерфейс с diff-ами бок-о-бок: http://dev.w3.org/cvsweb/html5/
Аннотированное резюме с unified diff-ами: http://html5.org/tools/web-apps-tracker
Непосредственный Subversion-интерфейс: svn checkout http://svn.whatwg.org/webapps/

Рабочая группа по Web-приложениям от W3C является рабочей группой от W3C, ответственной за продвижение данной спецификации в соответствии с W3C Recommendation track. Данная спецификация является Авторским черновиком от 29 марта 2013.

Этот документ был выпущен группой людей, действующей согласно 5 February 2004 W3C Patent Policy. W3C держит публичный список of всех открытых патентов, сделанных в связи с результатами работы этой группы; эта страница также включает инструкции по раскрытию возможных патентов. Лицо, владеющее актульной информацией о каком-либо патенте, который, как он считает, содержит Essential Claim(s), должно раскрыть эту информацию согласно section 6 of the W3C Patent Policy.

Содержание

  1. 1 Вступление
  2. 2 Cоответствие требованиям
    1. 2.1 Зависимости
  3. 3 Терминология
  4. 4 Интерфейс EventSource
  5. 5 Модель обработки
  6. 6 Разбор потока событий
  7. 7 Интерпретация потока событий
  8. 8 Замечания
  9. 9 Connectionless push и другие возможности
  10. 10 Сборка мусора
  11. 11 Согласование с IANA
    1. 11.1 text/event-stream
    2. 11.2 Last-Event-ID
  12. Ссылки
  13. Благодарности

1 Вступление

Этот раздел — неофициальный.

Чтобы позволить серверам проталкивать данные к Web-страницам или использовать специально разработанные с этой целью протоколы "server-push", данная спецификация вводит интерфейс EventSource.

Использование этого API состоит из создания объекта EventSource и регистрации слушателя событий.

var source = new EventSource('updates.cgi');
source.onmessage = function (event) {
  alert(event.data);
};

На серверной стороне скрипт ("updates.cgi" в данном случае) посылает сообщения в следующей форме, с MIME-типом text/event-stream:

data: This is the first message.

data: This is the second message, it
data: has two lines.

data: This is the third message.

Разработчики могут различать события, используя различные типы событий. Вот поток, в котором есть 2 типа событий, "add" и "remove":

event: add
data: 73857293

event: remove
data: 2153

event: add
data: 113411

Скрипт, предназначенный для обработки подобного потока, мог бы выглядеть так (где addHandler и removeHandler являются функциями, принимающими один аргумент, само событие):

var source = new EventSource('updates.cgi');
source.addEventListener('add', addHandler, false);
source.addEventListener('remove', removeHandler, false);

Тип события по умолчанию — "message".


Запросы потоковых событий могут перенаправляться с использованием редиректов 301 и 307, как и в случае обычных HTTP-запросов. Клиенты могут повторно подключиться, если соединение закрыто; клиенту можно сказать, чтобы он прекратил повторные подключения посредством HTTP-кода 204 No Content.

Использование этого API вместо эмуляции его посредством XMLHttpRequest или iframe позволяет агентам пользователя лучше использовать сетевые ресурсы в случаях, когда разработчик агента пользователя и оператор сети имеют возможность координировать свои действия заранее. Среди прочих преимуществ это может привести к значительной экономии батареи на портативных устройствах. Это обсуждается далее в разделе, посвященном connectionless push.

2 Cоответствие требованиям

Все диаграммы, примеры и замечания в этой спецификации не являются нормативными, как и все разделы, явно отмеченные ненормативными. Все остальное в этой спецификации является нормативным.

Ключевые слова "ДОЛЖЕН", "НЕ ДОЛЖЕН", "ТРЕБУЕТСЯ", "СЛЕДУЕТ", "НЕ СЛЕДУЕТ", "РЕКОМЕНДУЕТСЯ", "МОЖЕТ" и "НЕ ОБЯЗАТЕЛЬНЫЙ" в нормативной части этого документа должны интерпретироваться как описано в RFC2119. Для читаемости эти слова не представлены в верхнем регистре в данной спецификации. [RFC2119]

Требования, выраженные в повелительном наклонении как часть алгоритма (такие как "обрезать все ведущие пробельные символы" или "возвратить false и отменить действия") следует понимать в значении ключевого слова ("должен", "следует", "может" и т.д.), использованным при представлении алгоритма.

Некоторые соответствия требованиям выражаются как требования к атрибутам, методам и объектам. Подобные требования интерпретировать как требования к агентам пользователя.

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

Единственный класс соответствия, определенный данной спецификацией, есть агенты пользователя.

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

Когда поддержка некой возможности отключена (например, в качестве чрезвычайной меры для смягчения проблемы безопасности, или для содействия разработке, или из соображений производительности), агенты пользователя должны действовать, как если бы они не имели какой бы то ни было поддержки этой функции, и как если бы функция не была упомянута в этой спецификации. Например, если некая конкретная возможность доступна посредством атрибута в интерфейсе Web IDL, то сам атрибут следовало бы опустить из объектов, которые реализуют этот интерфейс,- оставление атрибута на объекте, при этом возвращать его как null или бросать исключение, — неудовлетворительно.

2.1 Зависимости

Данная спецификация полагается на несколько других, лежащих в основе, спецификаций.

HTML

Многие фундаментальные концепции из HTML использованы этой спецификацией. [HTML]

WebIDL

Блоки IDL в данной спецификации используют семантику спецификации WebIDL. [WEBIDL]

3 Терминология

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

Термин DOM используется для обозначения множества API, доступного скриптам Web-приложений, и это необязательно влечет существование наличие действительного объекта Document или любых других объектов Node, определенных в спецификации DOM. [DOM]

Говорят, что атрибут IDL берется (getting), когда извлекается его значение (например, разработчиком скрипта), и устанавливается (setting), когда новое значение присваивается ему.

4 Интерфейс EventSource

[Constructor(DOMString url, optional EventSourceInit eventSourceInitDict)]
interface EventSource : EventTarget {
  readonly attribute DOMString url;
  readonly attribute boolean withCredentials;

  // ready state
  const unsigned short CONNECTING = 0;
  const unsigned short OPEN = 1;
  const unsigned short CLOSED = 2;
  readonly attribute unsigned short readyState;

  // networking
           attribute EventHandler onopen;
           attribute EventHandler onmessage;
           attribute EventHandler onerror;
  void close();
};

dictionary EventSourceInit {
  boolean withCredentials = false;
};

Конструктор EventSource() принимает 1 или 2 аргумента. Первый задает URL, к которому нужно подключиться. Второй задает настройки, если таковые имеются, в форме словаря EventSourceInit. Когда конструктор EventSource() вызывается, ПА должен выполнить следующие действия:

  1. разрешить URL, указанный в первом аргументе, относительно базового URL входного скрипта. [HTML]

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

  3. Создать новый объект EventSource.

  4. Пусть CORS mode равен Anonymous.

  5. Если есть второй аргумент и элемент withCredentials словаря имеет значение true, тогда установить CORS mode в значение Use Credentials и инициализировать атрибут withCredentials нового объекта EventSource значением true.

  6. Вернуть новый объект EventSource, и продолжить действия в фоне (без блокировки скрипта).

  7. Выполнить potentially CORS-enabled fetch от полученного абсолютного URL, используя referrer source входного скрипта, с режимом CORS mode и источником, равным источнику входного скрипта, и обработать полученный ресурс, если таковой будет, как показано ниже.

    Определение алгоритма получения (используется CORS-ом) такого, что если браузер уже получает ресурс с заданным абсолютным URL, то соединение может быть использовано повторно вмето создания нового соединения. Все сообщения, полученные к этому моменту, диспетчеризуются сразу же в этом случае.

Конструктор должен быть виден, если глобальный объект скрипта есть либо объект Window, либо объект, реализующий интерфейс WorkerGlobalScope.


Атрибут url должен возвращать абсолютный URL, полученный из разрешения значения, которое было передано в конструктор.

Атрибут withCredentials должен быть установиться в последнее ему присвоенное значение. При создании объекта он инициализируется в false.

Атрибут readyState представляет собой состояние соединения. Он может иметь следующие значения:

CONNECTING (числовое значение 0)
Соединение еще не установлено, или оно было закрыто и ПА повторно подключается.
OPEN (числовое значение 1)
ПА держит открытое соединение и диспетчеризует события при их получении.
CLOSED (числовое значение 2)
Соединение не открыто, и ПА не пытается повторно подключиться. Либо была фатальная ошибка или метод close() был вызван.

При создании объекта его readyState должен быть установлен в значение CONNECTING (0). Правила, данные ниже для обработки соединения, определяют, когда это значение изменяется.

Метод close() должет прекратить все попытки алгоритма получения, стартовавшие для данного объекта EventSource, и должен установить readyState-атрибут в значение CLOSED.

Следующее есть обработчики событий (и соответствующие им типы события обработчика события), которые должны быть поддержаны, в качестве IDL-атрибутов, всеми объектами, реализующими интерфейс EventSource:

Обработчик событий Тип события обработчика события
onopen open
onmessage message
onerror error

В дополнении к сказанному, каждый объект EventSource обладает следующим, связанным с ним:

Значения этих переменных сейчас не раскрываются для пользователей.

5 Модель обработки

Ресурс, указанный аргументом в конструкторе EventSource доставляется, когда конструктор вызывается.

Для HTTP-соединений заголовок Accept может быть включен; если включен, то он должен содержать только форматы для записи событий, которые поддерживаются агентом пользователя (один из которых должен быть text/event-stream, как описано ниже).

Если ID-строка последнего события источника событий не равна пустой строке, то HTTP-заголовок Last-Event-ID должен быть включен в запрос со значением, равным ID-строка последнего события, в кодировке UTF-8.

Агентам пользователя следует использовать заголовок Cache-Control: no-cache в запросах, чтобы обойти любые кэширования запросов для источников событий. (Этот заголовок не является пользовательским заголовком запроса, поэтому агент пользователя все равно будет использовать CORS-механизм simple cross-origin request.) Агентам пользователя следует игнорировать кэширующие HTTP-заголовки в ответе, никогда не кэшируя источники событий.


Как только данные приходят, задания, добавленные источником сетевых заданий (networking task source) для обработки этих данных, должны действовать следующим образом.

Ответы HTTP 200 OK с заголовком Content-Type, равным типу text/event-stream, с игнорированием любых параметров MIME-типов должны быть обраработаны, линий за линией, как описано ниже.

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

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

Ответы HTTP 200 OK, которые содержат Content-Type с неподдерживаемым типом или не имеющим Content-Type вообще, должны служить причиной для того, чтобы агент пользователя провалил соединение.

HTTP 305 Use Proxy, 401 Unauthorized и 407 Proxy Authentication Required следует рассматривать прозрачно, как и для любого другого подресурса.

Ответы HTTP 301 Moved Permanently, 302 Found, 303 See Other и 307 Temporary Redirect обрабатываются доставляющим и CORS-алгоритмами. В случае редиректов 301 агент пользователя должен также запоминать новый URL, чтобы последующие запросы для данного ресурса данного объекта EventSource начинались с URL, полученным с последним 301 для данного объекта.

Ошибки сети, которые, в первую очередь, не дают создасться соединению (например, DNS-ошибки), должны служить причиной для того, чтобы агент пользователя асинхронно возобновлял соединение.

Любые другие коды HTTP-ответов, не перечисленные здесь, должны служить причиной для того, чтобы агент пользователя проваливал соединение.

Для не HTTP-протоколов ПА следует вести себя эквивалентным образом.


Когда агент пользователя объявляет о соединении, он должен добавить задание, которое, если атрибут readyState отличен от CLOSED, устанавливает атрибут readyState в значение OPEN и возбуждает простое событие с именем open на объекте EventSource.

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

  1. Добавить задание для выполнения следующих действий:

    1. Если атрибут readyState равен CLOSED, то прекратить задание.

    2. Установить атрибут readyState в значение CONNECTING.

    3. возбудить простое событие с именем error на объекте EventSource.

  2. Подождать в течение времени, равным времени переприсоединения для данного источника событий.

  3. По желанию подождать еще немного. В частности, если предыдущая попытка провалилась, то агенты пользователя могут ввести экспоненциальную "задержку на время откладывания передачи", чтобы избежать перегрузки потенциально уже перегруженного сервера. Или же, если операционная система сообщила, что нет сети, то агенты пользователя могут ждать момента, когда операционная система объявит, что сеть вернулась, перед тем как возобновить попытки.

  4. Подождать, пока вышеуказанное задание выполняется, если оно еще не выполнилось.

  5. Добавить задание для выполнения следующих действий:

    1. Если атрибут readyState не равен CONNECTING, то отменить действия.

    2. Выполнить potentially CORS-enabled fetch от абсолютного URL ресурса источника событий, используя тот же самый referrer source и с тем же самым режимоми источником, что были использованы в первом запросе, вызванным конструктором EventSource(), и обработать полученный таким образом ресурс, если таковой будет, как описано ранее в этом разделе.

Если агент пользователя собирается провалить соединение, то он должен добавить задание, которое, если атрибут readyState отличен от CLOSED, устанавливает атрибут readyState в значение CLOSED и возбуждает простое событие с именем error на объекте EventSource. Как только агент пользователя проваливает соединение, он не делает попыток повторно подключиться!


Источник заданий для любых заданий, которые были добавлены в очередь объектами EventSource есть remote event task source.

6 Разбор потока событий

MIME-тип формата потока событий равен text/event-stream.

Формат потока событий таков как описано правилом вывода stream следующего ABNF, набор символов для которого есть Юникод. [ABNF]

stream        = [ bom ] *event
event         = *( comment / field ) end-of-line
comment       = colon *any-char end-of-line
field         = 1*name-char [ colon [ space ] *any-char ] end-of-line
end-of-line   = ( cr lf / cr / lf )

; characters
lf            = %x000A ; U+000A LINE FEED (LF)
cr            = %x000D ; U+000D CARRIAGE RETURN (CR)
space         = %x0020 ; U+0020 SPACE
colon         = %x003A ; U+003A COLON (:)
bom           = %xFEFF ; U+FEFF BYTE ORDER MARK
name-char     = %x0000-0009 / %x000B-000C / %x000E-0039 / %x003B-10FFFF
                ; a Unicode character other than U+000A LINE FEED (LF), U+000D CARRIAGE RETURN (CR), or U+003A COLON (:)
any-char      = %x0000-0009 / %x000B-000C / %x000E-10FFFF
                ; a Unicode character other than U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)

Потоки событий в этом формате всегда нужно кодировать в UTF-8. [RFC3629]

Линии должны быть разделены либо парой U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF), одним символом U+000A LINE FEED (LF) или одним символом U+000D CARRIAGE RETURN (CR).

Так как соединения к удаленным серверам для таких ресурсов, как ожидается, будут долговечны, ПА должны обеспечить использование соответствующей буферизации. В частности, в то время как буферизация строк, определяемая окончанием строки по символу U+000A LINE FEED (LF) безопасна, блочная буферизация или строчная буферизация, ожидающая иных окончаний строк, могут вызывать задержки при диспетчеризации событий.

7 Интерпретация потока событий

Потоки должны декодироваться с использованием алгоритма UTF-8 decode.

Алгоритм UTF-8 decode отнимает один ведущий UTF-8 Byte Order Mark (BOM), если таковой имеется.

Поток должен быть разобран чтением всего строка за строкой, с окончанием строки на пару символов U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF), одним символом U+000A LINE FEED (LF) с предыдущим не равным U+000D CARRIAGE RETURN (CR) или одним U+000D CARRIAGE RETURN (CR) с последующим символом, не равным U+000A LINE FEED (LF).

При разборе потока буферы data, event type и last event ID должны быть связаны с ним. Они должны быть инициализированы пустой строкой.

Строки должны быть обработаны в порядке их получения следующим образом:

Если строка пустая

Диспетчеризовать событие, как показано ниже.

Если строка начинается с символа U+003A COLON (:)

Игнорировать строку.

Если строка содержит символ U+003A COLON (:)

Пусть field равно строке со всеми символами до первого символа U+003A COLON character (:).

Пусть value равно строке со всеми символами после первого символа U+003A COLON. Если value начинается с символа U+0020 SPACE, то удалить его из value.

Обработать поле, используя действия ниже, используя field как имя поля и value как значение поля.

Иначе строка непуста, но не содержит символ U+003A COLON (:)

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

Как только достигнут конец файла, все отложенные (pending) данные должны быть отброшены. (Если файл оканчивается в середине события, перед финальной пустой строкой, то незаконченное событие не диспетчеризуется.)


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

Если имя поля равно "event"

Установить буфер event type в значение поля.

Если имя поля равно "data"

Добавить значение поля к буферу data, затем добавить один символ U+000A LINE FEED (LF) к нему же.

Если имя поля равно "id"

Установить буфер last event ID в значение поля.

Если имя поля равно "retry"

Если значение поля состоит только из цифр ASCII, то интерпретировать значение поля как число по основанию 10 и установить время переприсоединения этим числом. Иначе игнорировать это поле.

Иначе

Поле игнорируется.

Когда агенту пользователя требуется диспетчеризовать событие, то он должен действовать следующим образом:

  1. Установить ID-строку последнего события источника событий в значение буфера last event ID. Буфер не сбрасывается, таким образом ID-строка последнего события источника событий остается равной этому значению до следующего раза ее установки сервером.

  2. Если буфер data равен пустой строке, то установить его буфер event type в значение пустой строки и отменить действия.

  3. Если последний символ буфера data равен U+000A LINE FEED (LF) , то удалить последний символ из буфера data.

  4. Создать событие с интерфейсом MessageEvent, с типом события message, которое "does not bubble", не отменяемое и не имеет действие по умолчанию. Атрибут data должен быть инициализирован значением буфера data, атрибут origin должен быть инициализирован результатом алгоритма Unicode serialization в отношении конечного URL origin'а источника событий (т.е. URL после редиректов) и атрибут lastEventId должен быть инициализирован ID-строкой последнего события источника событий. Это событие — не trusted.

  5. Если буфер event type равен значению, отличному от пустой строки, то изменить тип новосозданного события на значение буфера event type.

  6. Установить буферы data и event type равными пустой строке.

  7. Добавить задание, которое, если атрибут readyState отличен от CLOSED, диспетчеризует новосозданное событие на объекте EventSource.

Если событие не имеет поля "id", но событие ранее устанавливало ID-строку последнего события источника событий, то поле lastEventId события будет установлено в то последнее значение.

Следующий поток событий, как только за ним последует пустая строка:

data: YHOO
data: +2
data: 10

... вызвало бы событие message с интерфейсом MessageEvent, диспетчеризованным на объекте EventSource. Атрибут события data содержал бы строку YHOO\n+2\n10 (где \n представляет перевод строки).

Это могло бы быть использовано следующим образом:

var stocks = new EventSource("http://stocks.example.com/ticker.php");
stocks.onmessage = function (event) {
  var data = event.data.split('\n');
  updateStocks(data[0], data[1], data[2]);
};

... где updateStocks() есть функция, определенная как:

function updateStocks(symbol, delta, value) { ... }

... или что-то в этом роде.

Следующий поток содержит 4 блока. Первый блок содержит просто комментарий и не возбудит никаких событий. Второй блок имеет два поля с именами "data" и "id", соответственно; событие будет возбуждено для этого блока, с данными "first event", и также будет установлен ID последнего события в "1"; так что если соединение прервется между этим блоком и следующим, то серверу послали бы заголовок Last-Event-ID со значением "1". Третий блок возбуждает событие с данными "second event", а также с полем "id", на этот раз без значения, что обнуляет ID последнего события (что означает, что заголовок Last-Event-ID не будет теперь посылаться в случае попытки повторного соединения). Наконец последний блок просто возбуждает событие с данными " third event" (c одним ведущим пробельным символом). Отметим, что последний блок должен быть закончен пустой строкой, потому что конца потока недостаточно, чтобы вызвать диспетчеризацию последнего события.

: test stream

data: first event
id: 1

data:second event
id

data:  third event

Следующий поток возбуждает 2 события:

data

data
data

data:

Первый блок возбуждает событие с пустой строкой в качестве данных, также как и последний блок, если бы за ним следовала пустая строка. Средний блок возбуждает событие с данными, равными одному символу новой строки. Последний блок отметается, потому что за ним не следует пустая строка.

Следующий поток возбуждает 2 идентичных события:

data:test

data: test

Это происходит потому, что пробел после двоеточия игнорируется (при наличии).

8 Замечания

Устаревшие прокси-сервера известны тем, что в некоторых случаях обрывают HTTP-соединения после короткой паузы. Для защиты от таких прокси-серверов разработчики могут добавлять строку комментариев (начинающуюся с символа ':') каждые 15 секунд или около того.

Разработчики, желающие различать соединения к источникам событий между собой или устанавливать между ними и некими ранее загруженными документами могут обнаружить, что полагаться на IP-адреса не получиться, так как отдельные клиенты могут иметь множество IP-адресов (из-за наличия нескольких прокси-серверов) и отдельные IP-адреса могут иметь несколько клиентов (из-за использования одного прокси-сервера). Лучше включить уникальный идентификатор в документ в момент его выдачи и затем передавать этот идентификатор как часть URL при установке соединения.

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

Клиенты, имеющие ограничение на кол-во соединения для одного сервера могут столкнуться с проблемами при открытии нескольких страниц одного сайта, если каждая страница создает EventSource к одному и тому же домену. Разработчики могут избежать этого, используя относительно сложный механизм использования уникальных доменных имен для каждого соединения, либо разрешая пользователю включать/выключать функциональность EventSource на каждой странице, или с помощью задействования одного объекта EventSource с использованием shared worker. [WEBWORKERS]

9 Connectionless push и другие возможности

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

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

  1. Браузер соединяется с удаленным HTTP-сервером и запрашивает ресурс, указанный разработчиком в конструкторе EventSource.
  2. Сервер шлет редкие сообщения.
  3. Между сообщениями браузер обнаруживает, что он простаивает, за исключением сетевой активности по ведению TCP-соединения, и решает переключиться в спящий режим для экономии энергии.
  4. Браузер отключается от сервера.
  5. Браузер связывается с сервисом оператора и делает запрос, чтобы тот сервис, "проталкивающий прокси", держал соединение вместо него.
  6. "Проталкивающий прокси" связывается с удаленным HTTP-сервером и запрашивает ресурс, указанный разработчиком в конструкторе EventSource (возможно вместе с заголовком Last-Event-ID и т.д.).
  7. Браузер разрешает мобильному устройству перейти в спящий режим.
  8. Сервер шлет еще одно сообщение.
  9. "Проталкивающий прокси" использует технологию, такую как OMA push, чтобы передать событие мобильному устройству, последнее просыпается только для того, чтобы обработать событие и затем возвратится в спящий режим.

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

Также как реализация существующего API и протокола text/event-stream, как это определено в данной спецификации, как реализация более распределенным способом, как описано выше, так же и форматы передачи событий, определенные другими уместными спецификациями, могут поддерживаться. Данная спецификация не определяет, как делать разбор или обработку событий в таких случаях.

10 Сборка мусора

While an EventSource object's readyState is CONNECTING, and the object has one or more event listeners registered for open, message or error events, there must be a strong reference from the Window or WorkerGlobalScope object that the EventSource object's constructor was invoked from to the EventSource object itself.

While an EventSource object's readyState is OPEN, and the object has one or more event listeners registered for message or error events, there must be a strong reference from the Window or WorkerGlobalScope object that the EventSource object's constructor was invoked from to the EventSource object itself.

While there is a task queued by an EventSource object on the remote event task source, there must be a strong reference from the Window or WorkerGlobalScope object that the EventSource object's constructor was invoked from to that EventSource object.

If a user agent is to forcibly close an EventSource object (this happens when a Document object goes away permanently), the user agent must abort any instances of the fetch algorithm started for this EventSource object, and must set the readyState attribute to CLOSED.

If an EventSource object is garbage collected while its connection is still open, the user agent must abort any instance of the fetch algorithm opened by this EventSource.

It's possible for one active network connection to be shared by multiple EventSource objects and their fetch algorithms, which is why the above is phrased in terms of aborting the fetch algorithm and not the actual underlying download.

11 Согласование с IANA

11.1 text/event-stream

Эта информация предназначена для обзора сообществом и будет представлена на IESG для рассмотрения, утверждения и регистрации в IANA.

Имя типа:
text
Имя подтипа:
event-stream
Обязательные параметры:
Без параметров
Необязательные параметры
charset

Параметр charset может быть предоставлен. Значение параметра должно быть равно "utf-8". Этот параметр не служит никакой цели; он разрешен только для совместимости с устаревшими серверами.

Соображения по кодированию:
8-битное (всегда UTF-8)
Соображения безопасности:

Несовпадение источника (origin) потока событий с источником контента, потребляющего этот поток событий, может привести к утечке информации. Чтобы этого избежать агенты пользователя обязаны применять CORS-семантику. [CORS]

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

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

Соображения интероперабельности:
Правила обработки контента, и соответствующего требованиям, и не соответствующего, определены в данной спецификации.
Опубликованная спецификация:
Данный документ есть соответствующая спецификация.
Приложения, использующие данные медиа-тип:
Web-браузеры и инструменты, использующие Web-сервисы.
Дополнительная информация:
Магическое число(а):
Нет последовательности байт, могущей однозначно идентифицировать поток событий.
Расширение(я) файлов:
Нет особенных расширений файлов, рекомендуемых для данного типа.
Код типа файла для Macintosh:
Нет особенных кодов типа файла для Macintosh, рекомендуемых для данного типа.
Лицо и адрес электронной почты для получения дополнительной информации:
Ian Hickson <ian@hixie.ch>
Предполагаемое использование:
Обычное
Ограничения на употребление:
Ожидается, что данный формат будет использован только динамическими потоками через HTTP или через подобные протоколы. Не ожидается, что какие-нибудь конечные ресурсы будут помечены этим типом.
Автор:
Ian Hickson <ian@hixie.ch>
Контролирующий изменения:
W3C

Отдельные идентификаторы не имеют никакого отношения к ресурсам text/event-stream.

11.2 Last-Event-ID

Этот раздел описывает поле заголовка для регистрации в реесте Permanent Message Header Field Registry. [RFC3864]

Имя заголовка:
Last-Event-ID
Применимый протокол:
http
Статус:
стандарт
Автор/Контролирующий изменения:
W3C
Cпецификация документа(ов):
Данный документ есть соответствующая спецификация.
Сопутствующая информация:
Нет.

Ссылки

Все ссылки являются нормативными, если не помечены как "не нормативные".

[ABNF]
Augmented BNF for Syntax Specifications: ABNF, D. Crocker, P. Overell. IETF.
[CORS]
Cross-Origin Resource Sharing, A. van Kesteren. WHATWG.
[DOM]
DOM, A. van Kesteren, A. Gregor, Ms2ger. WHATWG.
[HTML]
HTML, I. Hickson. WHATWG.
[RFC2119]
Key words for use in RFCs to Indicate Requirement Levels, S. Bradner. IETF.
[RFC3629]
UTF-8, a transformation format of ISO 10646, F. Yergeau. IETF.
[RFC3864]
Registration Procedures for Message Header Fields, G. Klyne, M. Nottingham, J. Mogul. IETF.
[WEBIDL]
Web IDL, C. McCormack. W3C.
[WEBWORKERS]
Web Workers, I. Hickson. W3C.

Благодарности

Для получения полного списка благодарности см. спецификацию HTML. [HTML]