This is a snapshot of an early working draft and has therefore been superseded by the HTML standard.

This document will not be further updated.

HTML 5

Call For Comments — 27 October 2007

6.2. Server-sent DOM events

This section describes a mechanism for allowing servers to dispatch DOM events into documents that expect it. The event-source element provides a simple interface to this mechanism.

6.2.1. The RemoteEventTarget interface

Any object that implements the EventTarget interface must also implement the RemoteEventTarget interface.

interface RemoteEventTarget {
  void addEventSource(in DOMString src);
  void removeEventSource(in DOMString src);
};

When the addEventSource(src) method is invoked, the user agent must add the URI specified in src to the list of event sources for that object. The same URI can be registered multiple times.

When the removeEventSource(src) method is invoked, the user agent must remove the URI specified in src from the list of event sources for that object. If the same URI has been registered multiple times, removing it must only remove one instance of that URI for each invocation of the removeEventSource() method.

Relative URIs must be resolved relative to ....

6.2.2. Connecting to an event stream

Each object implementing the EventTarget and RemoteEventTarget interfaces has a list of event sources that are registered for that object.

When a new URI is added to this list, the user agent should, as soon as all currently executing scripts (if any) have finished executing, and if the specified URI isn't removed from the list before they do so, fetch the resource identified by that URI.

When an event source is removed from the list of event sources for an object, if that resource is still being fetched, then the relevant connection must be closed.

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 may be safe if lines are defined to end with a single U+000A LINE FEED character, block buffering or line buffering with different expected line endings can cause delays in event dispatch.

In general, the semantics of the transport protocol specified by the URIs for the event sources must be followed, including HTTP caching rules.

For HTTP connections, the Accept header may be included; if included, it must only contain formats of event framing that are supported by the user agent (one of which must be application/x-dom-event-stream, as described below).

Other formats of event framing may also be supported in addition to application/x-dom-event-stream, but this specification does not define how they are to be parsed or processed.

Such formats could include systems like SMS-push; for example servers could use Accept headers and HTTP redirects to an SMS-push mechanism as a kind of protocol negotiation to reduce network load in GSM environments.

User agents should use the Cache-Control: no-cache header in requests to bypass any caches for requests of event sources.

For connections to domains other than the document's domain, the semantics of the Access-Control HTTP header must be followed. [ACCESSCONTROL]

HTTP 200 OK responses with a Content-Type header specifying the type application/x-dom-event-stream that are either from the document's domain or explicitly allowed by the Access-Control HTTP headers must be processed line by line as described below.

For the purposes of such successfully opened event streams only, user agents should ignore HTTP cache headers, and instead assume that the resource indicates that it does not wish to be cached.

If such a resource completes loading (i.e. the entire HTTP response body is received or the connection itself closes), the user agent should request the event source resource again after a delay of approximately five seconds.

HTTP 200 OK responses that have a Content-Type other than application/x-dom-event-stream (or some other supported type), and HTTP responses whose Access-Control headers indicate that the resource are not to be used, must be ignored and must prevent the user agent from refetching the resource for that event source.

HTTP 201 Created, 202 Accepted, 203 Non-Authoritative Information, and 206 Partial Content responses must be treated like HTTP 200 OK responses for the purposes of reopening event source resources. They are, however, likely to indicate an error has occurred somewhere and may cause the user agent to emit a warning.

HTTP 204 No Content, and 205 Reset Content responses must be treated as if they were 200 OK responses with the right MIME type but no content, and should therefore cause the user agent to refetch the resource after a short delay.

HTTP 300 Multiple Choices responses should be handled automatically if possible (treating the responses as if they were 302 Found responses pointing to the appropriate resource), and otherwise must be treated as HTTP 404 responses.

HTTP 301 Moved Permanently responses must cause the user agent to reconnect using the new server specified URI instead of the previously specified URI for all subsequent requests for this event source. (It doesn't affect other event sources with the same URI unless they also receive 301 responses, and it doesn't affect future sessions, e.g. if the page is reloaded.)

HTTP 302 Found, 303 See Other, and 307 Temporary Redirect responses must cause the user agent to connect to the new server-specified URI, but if the user agent needs to again request the resource at a later point, it must return to the previously specified URI for this event source.

HTTP 304 Not Modified responses should be handled like HTTP 200 OK responses, with the content coming from the user agent cache. A new request should then be made after a short delay of approximately five seconds.

HTTP 305 Use Proxy, HTTP 401 Unauthorized, and 407 Proxy Authentication Required should be treated transparently as for any other subresource.

Any other HTTP response code not listed here should cause the user agent to stop trying to process this event source.

DNS errors must be considered fatal, and cause the user agent to not open any connection for that event source.

For non-HTTP protocols, UAs should act in equivalent ways.

6.2.3. Parsing an event stream

This event stream format's MIME type is application/x-dom-event-stream.

The event stream format is (in pseudo-BNF):

<stream>          ::= <bom>? <event>*
<event>           ::= [ <comment> | <command> | <field> ]* <newline>
<comment>         ::= ';' <any-char>* <newline>
<command>         ::= ':' <any-char>* <newline>
<field>           ::= <name> [ ':' <space>? <any-char>* ]? <newline>
<name>            ::= <name-start-char> <name-char>*

# characters:
<bom>             ::= a single U+FEFF BYTE ORDER MARK character
<space>           ::= a single U+0020 SPACE character (' ')
<newline>         ::= a U+000D CARRIAGE RETURN character
                      followed by a U+000A LINE FEED character
                      | a single U+000D CARRIAGE RETURN character
                      | a single U+000A LINE FEED character
                      | the end of the file
<name-start-char> ::= a single Unicode character other than
                      ':', ';', U+000D CARRIAGE RETURN and U+000A LINE FEED
<name-char>       ::= a single Unicode character other than
                      ':', U+000D CARRIAGE RETURN and U+000A LINE FEED
<any-char>        ::= a single Unicode character other than
                      U+000D CARRIAGE RETURN and U+000A LINE FEED

Event streams in this format must always be encoded as UTF-8. Lines must be separated by either a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, or a single U+000D CARRIAGE RETURN (CR) character. User agents must treat those three variants as equivalent line terminators.

Bytes or sequences of bytes that are not valid UTF-8 sequences must be interpreted as the U+FFFD REPLACEMENT CHARACTER.

One leading U+FEFF BYTE ORDER MARK character must be ignored if any are present.

The stream must then be parsed by reading everything line by line, in blocks separated by blank lines. Comment lines (those starting with the character ';') and command lines (those starting with the character ':') must be ignored.

Command lines are reserved for future extensions.

For each non-blank, non-comment, non-command line, the field name must first be taken. This is everything on the line up to but not including the first colon (':') or the line terminator, whichever comes first. Then, if there was a colon, the data for that line must be taken. This is everything after the colon, ignoring a single space after the colon if there is one, up to the end of the line. If there was no colon the data is the empty string.

Examples:

Field name: Field data
This is a blank field
1. These two lines: have the same data
2. These two lines:have the same data
1. But these two lines:  do not
2. But these two lines: do not

If a field name occurs multiple times in a block, the value for that field in that black must consist of the data parts for each of those lines, concatenated with U+000A LINE FEED characters between them (regardless of what the line terminators used in the stream actually are).

For example, the following block:

Test: Line 1
Foo:  Bar
Test: Line 2

...is treated as having two fields, one called Test with the value "Line 1\nLine 2" (where \n represents a newline), and one called Foo with the value " Bar" (note the leading space character).

A block thus consists of all the name-value pairs for its fields. Command lines have no effect on blocks and are not considered part of a block.

Since any random stream of characters matches the above format, there is no need to define any error handling.

6.2.4. Interpreting an event stream

Once the fields have been parsed, they are interpreted as follows (these are case-sensitive exact comparisons):

Event field

This field gives the name of the event. For example, load, DOMActivate, updateTicker. If there is no field with this name, the name message must be used.

Namespace field

This field gives the DOM3 namespace for the event. (For normal DOM events this would be null.) If it isn't specified the event namespace is null.

Class field

This field gives is the interface used for the event, for instance Event, UIEvent, MutationEvent, KeyboardEvent, etc. For compatibility with DOM3 Events, the values UIEvents, MouseEvents, MutationEvents, and HTMLEvents are valid values and must be treated respectively as meaning the interfaces UIEvent, MouseEvent, MutationEvent, and Event. (This value can therefore be used as the argument to createEvent().)

If the value is not specified but the Namespace is null and the Event field exactly matches one of the events specified by DOM3 Events in section 1.4.2 "Complete list of event types", then the interface used must default to the interface relevant for that event type. [DOM3EVENTS]

For example:

Event: click

...would cause Class to be treated as MouseEvent.

If the Namespace is null and the Event field is message (including if it was not specified explicitly), then the MessageEvent interface must be used.

Otherwise, the Event interface must be used.

It is quite possible to give the wrong class for an event. This is equivalent to creating an event in the DOM using the DOM Event APIs, but using the wrong interface for it.

Bubbles field

This field specifies whether the event is to bubble. If it is specified and has the value No, the event must not bubble. If it is specified and has any other value (including no or NO) then the event must bubble.

If it is not specified but the Namespace field is null and the Event field exactly matches one of the events specified by DOM3 Events in section 1.4.2 "Complete list of event types", then the event must bubble if the DOM3 Events spec specifies that that event bubbles, and musn't bubble if it specifies it does not. [DOM3EVENTS]

For example:

Event: load

...would cause Bubbles to be treated as No.

Otherwise, the event must bubble.

Cancelable field

This field specifies whether the event can have its default action prevented. If it is specified and has the value No, the event must not be cancelable. If it is specified and has any other value (including no or NO) then the event must be cancelable.

If it is not specified, but the Namespace field is null and the Event field exactly matches one of the events specified by DOM3 Events in section 1.4.2 "Complete list of event types", then the event must be cancelable if the DOM3 Events specification specifies that it is, and must not be cancelable otherwise. [DOM3EVENTS]

For example:

Event: load

...would cause Cancelable to be treated as No.

Otherwise, the event must be cancelable.

Target field

This field gives the node that the event is to be dispatched on.

If the object for which the event source is being processed is not a Node, but the Target field is nonetheless specified, then the event must be dropped.

Otherwise, if field is specified and its value starts with a # character, then the remainder of the value represents an ID, and the event must be dispatched on the same node as would be obtained by the getElementById() method on the ownerDocument of the node whose event source is being processed.

For example,

Target: #test

...would target the element with ID test.

Otherwise, if the field is specified and its value is the literal string "Document", then the event must be dispatched at the ownerDocument of the node whose event source is being processed.

Otherwise, the field (whether specified or not) is ignored and the event must be dispatched at the object itself.

Other fields depend on the interface specified (or possibly implied) by the Class field. If the specified interface has an attribute that exactly matches the name of the field, and the value of the field can be converted (using the type conversions defined in ECMAScript) to the type of the attribute, then it must be used. Any attributes (other than the Event interface attributes) that do not have matching fields are initialised to zero, null, false, or the empty string.

For example:

Event: click
Class: MouseEvent
button: 2

...would result in a 'click' event using the MouseEvent interface that has button set to 2 but screenX, screenY, etc, set to 0, false, or null as appropriate.

If a field does not match any of the attributes on the event, it must be ignored.

For example:

Event: keypress
Class: MouseEvent
keyIdentifier: 0

...would result in a MouseEvent event with its fields all at their default values, with the event name being keypress. The keyIdentifier field would be ignored. (If the author had not included the Class field explicitly, it would have just worked, since the class would have defaulted as described above.)

Once a blank line or the end of the file is reached, an event of the type and namespace given by the Event and Namespace fields respectively must be synthesized and dispatched to the appropriate node as described by the fields above. No event must be dispatched until a blank line has been received or the end of the file reached.

The event must be dispatched as if using the DOM dispatchEvent() method. Thus, if the Event field was omitted, leaving the name as the empty string, or if the name had invalid characters, then the dispatching of the event fails.

Events fired from event sources do not have user-agent default actions.

The following event stream, once followed by a blank line:

data: YHOO
data: -2
data: 10

...would cause an event message with the interface MessageEvent to be dispatched on the event-source element, which would then bubble up the DOM, and whose data attribute would contain the string YHOO\n-2\n10 (where \n again represents a newline).

This could be used as follows:

<event-source src="http://stocks.example.com/ticker.php"
              onmessage="var data = event.data.split('\n'); updateStocks(data[0], data[1], data[2]);">

...where updateStocks() is a function defined as:

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

...or some such.

The following stream contains four blocks and therefore fires four events. The first block has just a comment, and will fire a message event with all the fields set to the empty string or null. The second block has two fields with names "load" and "Target" respectively; since there is no "load" member on the MessageEvent object that field is ignored, leaving the event as a second message event with all the fields set to the empty string or null, but this time the event is targetted at an element with ID "image1". The third block is empty (no lines between two blank lines), and the fourth block has only two comments, so they both yet again fire message events with all the fields set to the empty string or null.

; test

load
Target: #image1


; if any more events follow this block, they will not be affected by
; the "Target" and "load" fields above.

6.2.5. Notes

Legacy proxy servers are known to, in certain cases, drop HTTP connections after a short timeout. To protect against such proxy servers, authors can include a comment line (one starting with a ';' character) every 15 seconds or so.

Authors wishing to relate event source connections to each other or to specific documents previously served might find that relying on IP addresses doesn't work, as individual clients can have multiple IP addresses (due to having multiple proxy servers) and individual IP addresses can have multiple clients (due to sharing a proxy server). It is better to include a unique identifier in the document when it is served and then pass that identifier as part of the URI in the src attribute of the event-source element.

Implementations that support HTTP's per-server connection limitation might run into trouble when opening multiple pages from a site if each page has an event-source to the same domain. Authors can avoid this using the relatively complex mechanism of using unique domain names per connection, or by allowing the user to enable or disable the event-source functionality on a per-page basis.