1. 9.2 サーバー送信イベント
      1. 9.2.1 導入
      2. 9.2.2 EventSourceインターフェイス
      3. 9.2.3 Processing model
      4. 9.2.4 `Last-Event-ID`ヘッダー
      5. 9.2.5 イベントストリームの解析
      6. 9.2.6 イベントストリームの解釈
      7. 9.2.7 オーサリングに関する注意事項
      8. 9.2.8 Connectionless push and other features
      9. 9.2.9 Garbage collection
      10. 9.2.10 Implementation advice

9.2 サーバー送信イベント

Server-sent_events

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera11+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+

9.2.1 導入

この節は非規範的である。

サーバーがHTTP経由で、または専用のサーバープッシュプロトコルを使用してウェブページにデータをプッシュできるようにするために、この仕様はEventSourceインターフェイスを導入する。

このAPIの使用は、EventSourceオブジェクトの作成とイベントリスナーの登録で構成される。

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

サーバー側では、スクリプト(この場合は"updates.cgi")は、text/event-streamのMIMEタイプで、次の形式でメッセージを送信する:

data: This is the first message.

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

data: This is the third message.

著者は、さまざまなイベントタイプを使用してイベントを分離できる。これは、"add"および"remove"の2つのイベントタイプを持つストリームである:

event: add
data: 73857293

event: remove
data: 2153

event: add
data: 113411

そのようなストリームを処理するためのスクリプトは次のようになる(ここでaddHandlerおよびremoveHandlerは、イベントという1つの引数を取る関数である):

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

デフォルトのイベントタイプは "message"である。

イベントストリームは常にUTF-8としてデコードされる。別の文字エンコーディングを指定する方法は存在しない。


イベントストリームリクエストは、通常のHTTPリクエストと同様に、HTTP 301および307リダイレクトを使用してリダイレクトできる。接続が閉じられる場合にクライアントは再接続する。クライアントは、HTTP 204 No Contentレスポンスコードを使用して再接続を停止するように指示できる。

XMLHttpRequestまたはiframeを使用してエミュレートするよりもむしろこのAPIを使用することは、ユーザーエージェントの実装者およびネットワークオペレーターが事前に調整できる場合に、ユーザーエージェントがネットワークリソースをより有効に活用可能になる。他の利点の中でも、これは、ポータブルデバイスのバッテリー寿命を大幅に節約するという結果をもたらす。これについては、下記のコネクションレスプッシュに関するセクションで詳しく説明される。

9.2.2 EventSourceインターフェイス

EventSource

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera11+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android11+
[Exposed=(Window,Worker)]
interface EventSource : EventTarget {
  constructor(USVString url, optional EventSourceInit eventSourceInitDict = {});

  readonly attribute USVString 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;
  undefined close();
};

dictionary EventSourceInit {
  boolean withCredentials = false;
};

Each EventSource object has the following associated with it:

Apart from url these are not currently exposed on the EventSource object.

source = new EventSource( url [, { withCredentials: true } ])

EventSource/EventSource

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera11+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+

新しいEventSourceオブジェクトを作成する。

urlは、イベントストリームを提供するURLを示す文字列である。

withCredentialsをtrueに設定すると、urlへの接続リクエストの資格情報モードが"include"に設定される。

source.close()

EventSource/close

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+

このEventSourceオブジェクトに対して開始されたフェッチアルゴリズムのインスタンスをすべて中止し、readyState属性をCLOSEDに設定する。

source.url

EventSource/url

Support in all current engines.

Firefox6+Safari6+Chrome18+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+

イベントストリームを提供するURLを返す。

source.withCredentials

EventSource/withCredentials

Support in all current engines.

Firefox6+Safari7+Chrome26+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS?Chrome Android?WebView Android?Samsung Internet?Opera Android12+

イベントストリームを提供するURLへの接続リクエストのクレデンシャルモードが"include"に設定される場合はtrueを返し、そうでなければfalseを返す。

source.readyState

EventSource/readyState

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+

このEventSourceオブジェクトの接続の状態を返す。以下に説明する値を持つことができる。

The EventSource(url, eventSourceInitDict) constructor, when invoked, must run these steps:

  1. Let ev be a new EventSource object.

  2. Let settings be ev's relevant settings object.

  3. Let urlRecord be the result of encoding-parsing a URL given url, relative to settings.

  4. If urlRecord is failure, then throw a "SyntaxError" DOMException.

  5. Set ev's url to urlRecord.

  6. Let corsAttributeState be Anonymous.

  7. If the value of eventSourceInitDict's withCredentials member is true, then set corsAttributeState to Use Credentials and set ev's withCredentials attribute to true.

  8. Let request be the result of creating a potential-CORS request given urlRecord, the empty string, and corsAttributeState.

  9. Set request's client to settings.

  10. User agents may set (`Accept`, `text/event-stream`) in request's header list.

  11. Set request's cache mode to "no-store".

  12. Set request's initiator type to "other".

  13. Set ev's request to request.

  14. Let processEventSourceEndOfBody given response res be the following step: if res is not a network error, then reestablish the connection.

  15. Fetch request, with processResponseEndOfBody set to processEventSourceEndOfBody and processResponse set to the following steps given response res:

    1. If res is an aborted network error, then fail the connection.

    2. Otherwise, if res is a network error, then reestablish the connection, unless the user agent knows that to be futile, in which case the user agent may fail the connection.

    3. Otherwise, if res's status is not 200, or if res's `Content-Type` is not `text/event-stream`, then fail the connection.

    4. Otherwise, announce the connection and interpret res's body line by line.

  16. Return ev.


The url attribute's getter must return the serialization of this EventSource object's url.

The withCredentials attribute must return the value to which it was last initialized. When the object is created, it must be initialized to false.

readyState属性は、接続の状態を表す。次の値を指定できる:

CONNECTING(数値0)
接続がまだ確立されていない、または接続が閉じられてユーザーエージェントが再接続している。
OPEN(数値1)
ユーザーエージェントは接続を開いており、イベントを受信するとイベントをディスパッチしている。
CLOSED(数値2)
接続が開いておらず、ユーザーエージェントが再接続を試みていない。致命的なエラーが発生したか、close()メソッドが呼び出されたかのいずれか。

When the object is created its readyState must be set to CONNECTING (0). The rules given below for handling the connection define when the value changes.

The close() method must abort any instances of the fetch algorithm started for this EventSource object, and must set the readyState attribute to CLOSED.

以下は、EventSourceインターフェイスを実装するすべてのオブジェクトによって、イベントハンドラーIDL属性として、サポートされるイベントハンドラー(および対応するイベントハンドラーイベント型)である:

イベントハンドラーイベントハンドラーイベント型
onopen

EventSource/open_event

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+
open
onmessage

EventSource/message_event

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+
message
onerror

EventSource/error_event

Support in all current engines.

Firefox6+Safari5+Chrome6+
Opera12+Edge79+
Edge (Legacy)?Internet ExplorerNo
Firefox Android45+Safari iOS5+Chrome Android?WebView Android?Samsung Internet?Opera Android12+
error

9.2.3 Processing model

When a user agent is to announce the connection, the user agent must queue a task which, if the readyState attribute is set to a value other than CLOSED, sets the readyState attribute to OPEN and fires an event named open at the EventSource object.

When a user agent is to reestablish the connection, the user agent must run the following steps. These steps are run in parallel, not as part of a task. (The tasks that it queues, of course, are run like normal tasks and not themselves in parallel.)

  1. Queue a task to run the following steps:

    1. If the readyState attribute is set to CLOSED, abort the task.

    2. Set the readyState attribute to CONNECTING.

    3. Fire an event named error at the EventSource object.

  2. Wait a delay equal to the reconnection time of the event source.

  3. Optionally, wait some more. In particular, if the previous attempt failed, then user agents might introduce an exponential backoff delay to avoid overloading a potentially already overloaded server. Alternatively, if the operating system has reported that there is no network connectivity, user agents might wait for the operating system to announce that the network connection has returned before retrying.

  4. Wait until the aforementioned task has run, if it has not yet run.

  5. Queue a task to run the following steps:

    1. If the EventSource object's readyState attribute is not set to CONNECTING, then return.

    2. Let request be the EventSource object's request.

    3. If the EventSource object's last event ID string is not the empty string, then:

      1. Let lastEventIDValue be the EventSource object's last event ID string, encoded as UTF-8.

      2. Set (`Last-Event-ID`, lastEventIDValue) in request's header list.

    4. Fetch request and process the response obtained in this fashion, if any, as described earlier in this section.

When a user agent is to fail the connection, the user agent must queue a task which, if the readyState attribute is set to a value other than CLOSED, sets the readyState attribute to CLOSED and fires an event named error at the EventSource object. Once the user agent has failed the connection, it does not attempt to reconnect.


The task source for any tasks that are queued by EventSource objects is the remote event task source.

9.2.4 `Last-Event-ID`ヘッダー

Last-Event-ID` HTTPリクエスト ヘッダーは、ユーザーエージェントが接続を再確立するときに、EventSourceオブジェクトの最後のイベントID文字列をサーバーに報告する。

値空間をより適切に定義するには、whatwg/html issue #7363を参照。これは基本的には、U+0000 NULL、U+000A LF、またはU+000D CRを含まない、UTF-8でエンコードされた文字列である。

9.2.5 イベントストリームの解析

このイベントストリームのフォーマットのMIMEタイプは、text/event-streamである。

イベントストリームのフォーマットは、次のABNFのstream生成で説明されているとおりである。文字セットはUnicodeである。[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 scalar value 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 scalar value other than U+000A LINE FEED (LF) or U+000D CARRIAGE RETURN (CR)

このフォーマットのイベントストリームは、常にUTF-8としてエンコードしなければならない。[ENCODING]

行は、U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF)文字ペア、単一のU+000A LINE FEED (LF)文字、または単一のU+000D CARRIAGE RETURN (CR)文字のいずれかで区切らなければならない。

Since connections established to remote servers for such resources are expected to be long-lived, UAs should ensure that appropriate buffering is used. In particular, while line buffering with lines are defined to end with a single U+000A LINE FEED (LF) character is safe, block buffering or line buffering with different expected line endings can cause delays in event dispatch.

9.2.6 イベントストリームの解釈

Streams must be decoded using the UTF-8 decode algorithm.

The UTF-8 decode algorithm strips one leading UTF-8 Byte Order Mark (BOM), if any.

The stream must then be parsed by reading everything line by line, with a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character not preceded by a U+000D CARRIAGE RETURN (CR) character, and a single U+000D CARRIAGE RETURN (CR) character not followed by a U+000A LINE FEED (LF) character being the ways in which a line can end.

When a stream is parsed, a data buffer, an event type buffer, and a last event ID buffer must be associated with it. They must be initialized to the empty string.

Lines must be processed, in the order they are received, as follows:

If the line is empty (a blank line)

Dispatch the event, as defined below.

If the line starts with a U+003A COLON character (:)

Ignore the line.

If the line contains a U+003A COLON character (:)

Collect the characters on the line before the first U+003A COLON character (:), and let field be that string.

Collect the characters on the line after the first U+003A COLON character (:), and let value be that string. If value starts with a U+0020 SPACE character, remove it from value.

Process the field using the steps described below, using field as the field name and value as the field value.

Otherwise, the string is not empty but does not contain a U+003A COLON character (:)

Process the field using the steps described below, using the whole line as the field name, and the empty string as the field value.

Once the end of the file is reached, any pending data must be discarded. (If the file ends in the middle of an event, before the final empty line, the incomplete event is not dispatched.)


The steps to process the field given a field name and a field value depend on the field name, as given in the following list. Field names must be compared literally, with no case folding performed.

If the field name is "event"

Set the event type buffer to the field value.

If the field name is "data"

Append the field value to the data buffer, then append a single U+000A LINE FEED (LF) character to the data buffer.

If the field name is "id"

If the field value does not contain U+0000 NULL, then set the last event ID buffer to the field value. Otherwise, ignore the field.

If the field name is "retry"

If the field value consists of only ASCII digits, then interpret the field value as an integer in base ten, and set the event stream's reconnection time to that integer. Otherwise, ignore the field.

そうでなければ

The field is ignored.

When the user agent is required to dispatch the event, the user agent must process the data buffer, the event type buffer, and the last event ID buffer using steps appropriate for the user agent.

For web browsers, the appropriate steps to dispatch the event are as follows:

  1. Set the last event ID string of the event source to the value of the last event ID buffer. The buffer does not get reset, so the last event ID string of the event source remains set to this value until the next time it is set by the server.

  2. If the data buffer is an empty string, set the data buffer and the event type buffer to the empty string and return.

  3. If the data buffer's last character is a U+000A LINE FEED (LF) character, then remove the last character from the data buffer.

  4. Let event be the result of creating an event using MessageEvent, in the relevant realm of the EventSource object.

  5. Initialize event's type attribute to "message", its data attribute to data, its origin attribute to the serialization of the origin of the event stream's final URL (i.e., the URL after redirects), and its lastEventId attribute to the last event ID string of the event source.

  6. If the event type buffer has a value other than the empty string, change the type of the newly created event to equal the value of the event type buffer.

  7. Set the data buffer and the event type buffer to the empty string.

  8. Queue a task which, if the readyState attribute is set to a value other than CLOSED, dispatches the newly created event at the EventSource object.

If an event doesn't have an "id" field, but an earlier event did set the event source's last event ID string, then the event's lastEventId field will be set to the value of whatever the last seen "id" field was.

For other user agents, the appropriate steps to dispatch the event are implementation dependent, but at a minimum they must set the data and event type buffers to the empty string before returning.

次のイベントストリームの後には、空白行が1行続く:

data: YHOO
data: +2
data: 10

インターフェイスMessageEventをもつイベントmessageEventSourceオブジェクトに送出される。イベントのdata属性には、文字列"YHOO\n+2\n10"が含まれる("\n"は改行を表す)。

これは、次のように使用できる:

var stocks = new EventSource("https://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つのブロックが含まれている。最初のブロックにはコメントのみが含まれており、何も発火しない。2番目のブロックには、それぞれ"data"および"id"という名前の2つのフィールドがある。このブロックに対して、データ"first event"でイベントが発生し、最後のイベントIDを"1"に設定する。これにより、このブロックと次のブロックとの間の接続が切断された場合、サーバーには値`1`の`Last-Event-ID`ヘッダーが送信される。3番目のブロックは"second event"というデータでイベントを発火し、"id" フィールドも持っているが、今回は値が存在しない。これは、最後のイベントIDを空の文字列にリセットする(つまり、再接続が試行された場合に`Last-Event-ID`ヘッダーが送信されなくなる)。最後に、最終ブロックは、データ" third event"(先頭に1つのスペース文字)をもつイベントを発火するだけである。最後の行は空白行で終了する必要があることに注意する。ストリームの終わりは、最後のイベントの早出をトリガーするのに十分ではない。

: test stream

data: first event
id: 1

data:second event
id

data:  third event

次のストリームは、2つのイベントを発火させる:

data

data
data

data:

最初のブロックは、データが空の文字列に設定された状態でイベントを発火させる。最後のブロックの後に空白行が続く場合も同様である。中間のブロックは、データが単一の改行文字に設定されたイベントを発火させる。最後のブロックは、その後に空白行がないため破棄される。

次のストリームは、2つの同じイベントを発火させる:

data:test

data: test

これは、コロンの後のスペースが存在する場合、無視されるためである。

9.2.7 オーサリングに関する注意事項

レガシープロキシサーバーは、特定のケースにおいて、短いタイムアウトの後にHTTP接続を切断することが知られている。そのようなプロキシサーバーから保護するために、著者は約15秒ごとにコメント行(':'文字で始まる行)を含めることができる。

イベントソース接続を相互に、または以前に配信された特定の文書に関連付けたい著者は、IPアドレスに依存することが機能しないことに気づくかもしれない。これは、個々のクライアントが複数のIPアドレスを持つことができ(複数のプロキシサーバーがあるため)、そして個々のIPアドレスが複数のクライアントを持つことができる(プロキシサーバーを共有しているため)あるためである。文書が提供されるときにその文書に一意の識別子を含め、接続が確立されるときにその識別子をURLの一部として渡す方がよい。

著者はまた、特にタイミング要件を認識しない別のレイヤーでチャンクが行われる場合、HTTPチャンクがこのプロトコルの信頼性に予期しない悪影響を与える可能性があることに注意する。これが問題である場合、イベントストリームの配信時にチャンクを無効にすることができる。

HTTPのサーバーごとの接続制限をサポートするクライアントは、各ページが同じドメインへのEventSourceを持つ場合、あるサイトから複数のページを開くときに問題が発生する可能性がある。著者は、接続ごとに一意なドメイン名を使用するという比較的複雑なメカニズムを使用する、ユーザーがページごとにEventSource機能を有効もしくは無効にできるようにすること、または共有ワーカーを使用して単一のEventSourceオブジェクトを共有することによって、この問題を回避できる。

9.2.8 Connectionless push and other features

User agents running in controlled environments, e.g. browsers on mobile handsets tied to specific carriers, may offload the management of the connection to a proxy on the network. In such a situation, the user agent for the purposes of conformance is considered to include both the handset software and the network proxy.

For example, a browser on a mobile device, after having established a connection, might detect that it is on a supporting network and request that a proxy server on the network take over the management of the connection. The timeline for such a situation might be as follows:

  1. Browser connects to a remote HTTP server and requests the resource specified by the author in the EventSource constructor.
  2. The server sends occasional messages.
  3. In between two messages, the browser detects that it is idle except for the network activity involved in keeping the TCP connection alive, and decides to switch to sleep mode to save power.
  4. The browser disconnects from the server.
  5. The browser contacts a service on the network, and requests that the service, a "push proxy", maintain the connection instead.
  6. The "push proxy" service contacts the remote HTTP server and requests the resource specified by the author in the EventSource constructor (possibly including a `Last-Event-ID` HTTP header, etc.).
  7. The browser allows the mobile device to go to sleep.
  8. The server sends another message.
  9. The "push proxy" service uses a technology such as OMA push to convey the event to the mobile device, which wakes only enough to process the event and then returns to sleep.

This can reduce the total data usage, and can therefore result in considerable power savings.

As well as implementing the existing API and text/event-stream wire format as defined by this specification and in more distributed ways as described above, formats of event framing defined by other applicable specifications may be supported. This specification does not define how they are to be parsed or processed.

9.2.9 Garbage collection

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.

9.2.10 Implementation advice

この節は非規範的である。

User agents are strongly urged to provide detailed diagnostic information about EventSource objects and their related network connections in their development consoles, to aid authors in debugging code using this API.

For example, a user agent could have a panel displaying all the EventSource objects a page has created, each listing the constructor's arguments, whether there was a network error, what the CORS status of the connection is and what headers were sent by the client and received from the server to lead to that status, the messages that were received and how they were parsed, and so forth.

Implementations are especially encouraged to report detailed information to their development consoles whenever an error event is fired, since little to no information can be made available in the events themselves.