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.
RemoteEventTarget interfaceAny 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 remove only one instance of that URI for each invocation
of the removeEventSource() method.
Relative URIs must be resolved relative to ....
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.
Each event source in the list must have associated with it the following:
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 contain only formats of event framing that
are supported by the user agent (one of which must be
text/event-stream, as described below).
Other formats of event framing may also be supported in addition to
text/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.
If the event source's last event ID string is not the empty string, then
a Last-Event-ID HTTP header must be included with
the request, whose value is the value of the event source's last event ID
string.
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 text/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 equal to the reconnection time of the event source.
HTTP 200 OK responses that have a Content-Type other than
text/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 delay equal to the reconnection time of the event source.
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 delay equal to the reconnection time of the event source.
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.
This event stream format's MIME type is text/event-stream.
The event stream format is (in pseudo-BNF):
<stream> ::= <bom>? <event>*
<event> ::= [ <comment> | <field> ]* <newline>
<comment> ::= <colon> <any-char>* <newline>
<field> ::= <name-char>+ [ <colon> <space>? <any-char>* ]? <newline>
# 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
<colon> ::= a single U+003A COLON character (':')
<name-char> ::= a single Unicode character other than
U+003A COLON, 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.
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, with a U+000D CARRIAGE RETURN U+000A LINE FEED (CRLF) character pair, a single U+000A LINE FEED (LF) character, a single U+000D CARRIAGE RETURN (CR) character, and the end of the file being the four ways in which a line can end.
When a stream is parsed, a data buffer and an event name 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:
Dispatch the event, as defined below.
Ignore the line.
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 single 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.
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, the user agent must dispatch the event one final time, as defined below.
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.
Set the event name buffer the to field value.
If the data buffer is not the empty string, then append a single U+000A LINE FEED character to the data buffer. Append the field value to the data buffer.
Set the event stream's last event ID to the field value.
If the field value consists of only characters in the range U+0030 DIGIT ZERO ('0') U+0039 DIGIT NINE ('9'), 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, then the user agent must act as follows:
If the data buffer is an empty string, set the data buffer and the event name buffer to the empty string and abort these steps.
If the event name buffer is not the empty string but is also not a valid NCName, set the data buffer and the event name buffer to the empty string and abort these steps.
Otherwise, create an event that uses the MessageEvent interface, with the event
name message,
which does not bubble, is cancelable, and has no default action. The
data
attribute must be set to the value of the data
buffer, the origin attribute must be set to the origin of the event stream, the lastEventId attribute must be set to the
last event ID string of the event source, and the source
attribute must be set to null.
If the event name buffer has a value other than the empty string, change the type of the newly created event to equal the value of the event name buffer.
Set the data buffer and the event name buffer to the empty string.
Dispatch the newly created event at the RemoteEventTarget object to which
the event stream is registered.
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.
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, whose
data
attribute would contain the string YHOO\n-2\n10 (where
\n 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. The first block has just a
comment, and will fire nothing. The second block has two fields with
names "data" and "id" respectively; an event will be fired for this
block, with the data "first event", and will then set the last event ID
to "1" so that if the connection died between this block and the next,
the server would be sent a Last-Event-ID header
with the value "1". The third block fires an event with data "second
event", and also has an "id" field, this time with no value, which resets
the last event ID to the empty string (meaning no Last-Event-ID header will now be sent in the event of a
reconnection being attempted). Finally the last block just fires an event
with the data "third event". Note that the last block doesn't have to end
with a blank line, the end of the stream is enough to trigger the
dispatch of the last event.
: test stream data: first event id: 1 data: second event id data: third event
The following stream fires just one event:
data data data data:
The first and last blocks do nothing, since they do not contain any actual data (the data buffer remains at the empty string, and so nothing gets dispatched). The middle block fires an event with the data set to a single newline character.
The following stream fires two identical events:
data:test data: test
This is because the space after the colon is ignored if present.
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.