Server Sent Events 1.0

Working Draft 8 June 2004

This version:
http://www.hixie.ch/specs/html/server-sent-events/server-sent-events-1
Latest version:
http://www.hixie.ch/specs/html/server-sent-events/server-sent-events
Previous versions:
http://ln.hixie.ch/?start=1083167110&count=1
Editor:
Ian Hickson, Opera Software, ian@hixie.ch

Abstract

This specification describes a mechanism for allowing servers to dispatch DOM events into documents that expect it.

Status of this document

This document currently has no official standing within the W3C at all. It is the result of loose collaboration between interested parties in private e-mail. To become involved in the development of this document, please send comments to ian@hixie.ch. Your input will be taken into consideration.

This is a working draft and may therefore be updated, replaced or rendered obsolete by other documents at any time. It is inappropriate to use Working Drafts as reference material or to cite them as other than "work in progress".

This draft may contain namespaces that use the uuid: URI scheme. These are temporary and will be changed before this specification is ready to be implemented.

To find the latest version of this working draft, please follow the "Latest version" link above.

Table of contents


1. The event-source element

To specify an event source in an HTML document authors use a new (empty) element event-source, with an attribute src="" that takes a URI to open as a stream and, if the data found at that URI is of the appropriate type, treat as an event source.

The event-source element may also have an onevent="" attribute. If present, the attribute is treated as script representing an event handler registered as non-capture listener of events with name event and the namespace uuid:755e2d2d-a836-4539-83f4-16b51156341f or null, that are targetted at or bubble through the element.

1.1. Processing model

When an event-source element has a src attribute set, the UA should fetch the resource indicated by the attribute's value. If the resource has the type application/x-dom-event-stream, then it is processed line by line as described below.

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 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 "src" attribute must be followed. Clients should re-open event-source connections that get closed after a short interval (such as 5 seconds), unless they were closed due to problems that aren't expected to be resolved.

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

HTTP 200 OK responses that have a Content-Type other than application/x-dom-event-stream should be ignored and should prevent the user agent from reopening the connection for that event-source. HTTP 200 OK responses with the right MIME type, however, should, when closed, be reopened after a small delay.

HTTP 201 Created, 202 Accepted, 203 Non-Authoritative Information, and 206 Partial Content responses should be treated like HTTP 200 OK responses for the purposes of reopening event-source connections. 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 should be treated as if they were 200 OK responses with the right MIME type but no content, and should therefore should cause the user agent to reopen the connection after a short delay.

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

HTTP 301 Moved Permanently responses should cause the user agent to use the server specified URI instead of the one specified in the event-source's "src" attribute for future connections.

HTTP 302 Found, 303 See Other, and 307 Temporary Redirect responses should cause the user agent to use the server specified URI instead of the one specified in the event-source's "src" attribute for the next connection, but if the user agent needs to reopen the connection at a later point, it should once again start from the "src" attribute (or the last URI given by a 301 Moved Permanently response in complicated cases where such responses are chained).

HTTP 304 Not Modified responses should be handled like HTTP 200 OK responses, with the content coming from the user agent cache.

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

HTTP 400 Bad Request, 403 Forbidden, 404 Not Found, 405 Method Not Allowed, 406 Not Acceptable, 408 Request Timeout, 409 Conflict, 410 Gone, 411 Length Required, 412 Precondition Failed, 413 Request Entity Too Large, 414 Request-URI Too Long, 415 Unsupported Media Type, 416 Requested Range Not Satisfiable, 417 Expectation Failed, 500 Internal Server Error, 501 Not Implemented, 502 Bad Gateway, 503 Service Unavailable, 504 Gateway Timeout, and 505 HTTP Version Not Supported responses, and any other HTTP response code not listed here, should cause the user agent to stop trying to process this event-source element.

2. The event stream format

The event stream MIME type is application/x-dom-event-stream.

The event stream is always be encoded as UTF-8. Line are always be terminated by a single U+000A line feed character.

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

<stream>  ::= <event>*
<event>   ::= [ <comment> | <field> ]+ <newline>

<comment> ::= ';' <data> <newline>
<field>   ::= <name> [ ':' <space>? <data> ]? <newline>

<name>    ::= one or more UNICODE characters other than ':' and U+000A
<data>    ::= zero or more UNICODE characters other than U+000A
<space>   ::= a single U+0020 character (' ')
<newline> ::= a single U+000A character

The stream is parsed by reading everything line by line, in blocks separated by blank lines (blank lines are those consisting of just a single lone line feed character). Comment lines (those starting with the character ';' not proceeded by any other characters) are ignored.

For each non-blank, non-comment line, the field name is first taken. This is everything on the line up to but not including the first colon (':') or the line feed, whichever comes first. Then, if there was a colon, the data for that line is 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, the data values for those lines are concatenated with a newline between them.

For example, the following:

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.

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

3. Event stream interpretation

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

Once a blank line is reached, an event of the appropriate type is synthesized and dispatched to the appropriate node as described by the fields above. No event is dispatched until a blank line has been received.

4. The RemoteEvent interface

The RemoteEvent interface is defined as follows:

interface RemoteEvent : Event {
  readonly attribute DOMString       data;
  void               initRemoteEvent(in DOMString typeArg,
                                     in boolean canBubbleArg,
                                     in boolean cancelableArg,
                                     in DOMString dataArg);
  void               initRemoteEventNS(in DOMString namespaceURI,
                                       in DOMString type,
                                       in boolean canBubbleArg,
                                       in boolean cancelableArg,
                                       in DOMString dataArg);
};

Events that use the RemoteEvent interface never have any default action associated with them.

5. Example

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

Event: stock change
data: YHOO
data: -2
data: 10

...would cause an event stock change with the interface RemoteEvent 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" id="stock">
<script type="text/javascript">
document.getElementById('stock').addEventListener('stock change',
  function () {
    var data = event.data.split('\n');
    updateStocks(data[0], data[1], data[2]);
  }, false);
</script>

...where updateStocks is a function defined as:

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

...or some such.

Acknowledgements

Thanks to Tom Pike and Joshua Randall for their substantial comments.