EventSource polyfill - http://www.w3.org/TR/eventsource/
IE 8+, Firefox 3.5+, Chrome 6+, Safari 5+, Opera 12+
- Simple server-side code - you don't need any library.
- Based on latest specification of EventSource
- Polyfill is independent from document methods, so you can use it in a Web Worker's
- Cross-domain requests support (anonymous mode)
- "Last-Event-ID" sended in POST body (CORS + "Last-Event-ID" header is not supported by all browsers)
- IE requires send two kilobyte padding at the top of the response stream - see http://blogs.msdn.com/b/ieinternals/archive/2010/04/06/comet-streaming-in-internet-explorer-with-xmlhttprequest-and-xdomainrequest.aspx?PageIndex=1
- you need to send "comment" message each 15-30 seconds
- https://github.com/remy/polyfills/blob/master/EventSource.js by Remy Sharp
- https://github.com/rwldrn/jquery.eventsource by rick waldron
CORS
- https://bugzilla.mozilla.org/show_bug.cgi?id=664179 (Firefox 11)
- https://bugs.webkit.org/show_bug.cgi?id=61862 (not implemented)
- Opera 12 alpha supports EventSource + CORS
lastEventId shouldn' be set when connection dropped without data dispatch - http://www.w3.org/Bugs/Public/show_bug.cgi?id=13761
-
Opera DSK-353296, Opera DSK-346814
-
DSK-362337 - Opera bug with event-stream with "message", "error", "open" events (minor)
-
http://code.google.com/p/chromium/issues/detail?id=86230 - Crhome bug with small "retry" (minor)
-
http://lists.w3.org/Archives/Public/public-webapps/2012AprJun/0388.html
var http = require('http');
var fs = require('fs');
http.createServer(function (req, res) {
var t = null;
if (req.url.indexOf('/events') === 0) {
res.writeHead(200, {
'Content-Type': 'text/event-stream',
'Cache-Control': 'no-cache',
'Connection': 'keep-alive',
'Access-Control-Allow-Origin': '*'
});
res.write(':' + Array(2049).join(' ') + '\n'); //2kb padding for IE
res.write('data: ' + Date() + '\n\n');
t = setInterval(function () {
res.write('data: ' + Date() + '\n\n');
}, 1000);
res.socket.on('close', function () {
clearInterval(t);
});
} else {
if (req.url === '/index.html' || req.url === '/eventsource.js') {
res.writeHead(200, {'Content-Type': req.url === '/index.html' ? 'text/html' : 'text/javascript'});
res.write(fs.readFileSync(__dirname + req.url));
}
res.end();
}
}).listen(8081); //! port :8081
<?
header('Access-Control-Allow-Origin: *');
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// prevent bufferring
if (function_exists('apache_setenv')) {
@apache_setenv('no-gzip', 1);
}
@ini_set('zlib.output_compression', 0);
@ini_set('implicit_flush', 1);
for ($i = 0; $i < ob_get_level(); $i++) { ob_end_flush(); }
ob_implicit_flush(1);
// getting last-event-id from POST or from http headers
$postData = @file_get_contents('php://input');
parse_str($postData, $tmp);
if (isset($tmp['Last-Event-ID'])) {
$lastEventId = $tmp['Last-Event-ID'];
} else {
$lastEventId = @$_SERVER["HTTP_LAST_EVENT_ID"];
}
// 2kb padding for IE
echo ':' . str_repeat(' ', 2048) . "\n";
// event-stream
for ($i = intval($lastEventId) + 1; $i < 100; $i++) {
echo "id: $i\n";
echo "data: $i;\n\n";
sleep(1);
}
?>
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>EventSource example</title>
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<script src="../eventsource.js"></script>
<script>
var es = new EventSource('events.php');
es.addEventListener('open', function (event) {
var div = document.createElement('div');
div.innerHTML = 'opened: ' + es.url;
document.body.appendChild(div);
}, false);
es.addEventListener('message', function (event) {
document.body.appendChild(document.createTextNode(event.data));
}, false);
es.addEventListener('error', function (event) {
var div = document.createElement('div');
div.innerHTML = 'closed';
document.body.appendChild(div);
}, false);
</script>
</head>
<body>
</body>
</html>