Připomenutí existence „server-sent events” (SSE)
Kromně více známého a rozšířeného WebSocketu a klasického Ajaxového dotazování API serveru existuje také „server-sent events” (dále SSE). SSE slouží k jednosměrnému posílání informací ze serveru ke klientovi.
Obsah
Hlavní vlastnosti
Podrobněji rozebírá [sseVSws] a [mdn].
SSE pracuje přes protokol HTTP(S)1 (může být vstřícnější k firemním firewallům), je podporováno nativně2 v prohlížečích (z předchozího i na serverech) a relativně jednoduché na implementaci a pochopení (viz dále).
Nativní implementace navíc řeší znovupřipojování a spárovávání zpráv s identifikátory.
Klíčovými limitacemi je nepodpora binárních dat a protokol, v případě velmi komplexních/vytížených systémů.
Implementace na straně serveru
Zde použijeme MIME typ text/event-stream
a zprávy posíláme v jednoduchém textovém UTF-8 formátu event stream.
Tedy se zápisem data: zpráva
a oddělujeme je \n\n
3. Ke zprávě lze dodat její jméno event: jméno
a identifikátor id: 1
. Tedy celkem:
Jako zprávu můžeme sapozřejmě použít JSON. Pro PHP bychom mohli tedy vytvořit funkci ve tvaru:
1
2
3
4
5
6
7
8
9
10
11
function eventEmmit($data= "", $event= false, $id= false){
if($id)
echo "id: $id\n";
if($event)
echo "event: $event\n";
if(is_array($data))
$data= json_encode($data);
echo "data: $data\n\n";
ob_end_flush();
flush();
}
Ukázka jednoduché funkce pro zasílání SSE v PHP
1
2
3
4
5
6
7
8
9
10
11
12
13
define('EVENT_DELAY', 1);
header('Cache-Control: no-cache');
header('Content-Type: text/event-stream');
$id= 0;
function out($event, $data){
global $id;
eventEmmit($data, $event, id++);
sleep(EVENT_DELAY);
}
while(true){
$event= 'event_'.(rand(1, 10)>5 ? 'a': 'b');
out($event, array( 'now'=> date(DATE_ISO8601) ));
}
Ukázka použití eventEmmit
Použití/naslouchání v JavaScriptu
Zde stačí inicializovat EventSource
s cestou ke skriptu na serveru. Instance pak mimojiné obsahuje settery onmessage
resp. onerror
(k naslouchání nepojmenovaných zpráv resp. chyb), metodu addEventListener
s jejíž pomocí se dají naslouchat jen vybrané zprávy (dle jména) a metodu close
pro ukončení spojení.
1
2
3
4
5
6
7
8
9
10
11
const sse= new EventSource("cesta/ke/skriptu.php");
const parse= json_candidate=> { try{ return JSON.parse(json_candidate); } catch(e){ return json_candidate; } };
const log= ({ data= "" }= {})=> console.log(parse(data));
sse.addEventListener("event_a", log);
sse.addEventListener("event_b", log);
sse.onerror= console.error;
/*
…
*/
sse.close();
Tedy ukázka pro dřívější serverovou část
Možná (typická) použití
- Tzv. „hot-reload”: Server a klient si pamatují poslední aktualizaci souboru/stránky. Pokud na serveru dojde ke změně, pomocí SSE pošle nové časové razítko klientovi a ten stránku přenačte (např.
location.reload()
). - Rozšířením předchozího je donačítání příspěvků alá Twitter.
- Velmi podobné je také použití pro notifikace.
Reference a související zdroje
- [mdn] Using server-sent events – Přehledový článek dokumnetace k SSE
-
[sseVSws] WebSockets vs. Server-Sent events/EventSource – Docela vyčerávající seznam o vlastnostech SSE a srovnání s
WebSockets
- [rauschma] Poznámky o SSE – Axel Rauschmayer
- [postup-vývoje] Developing Real-Time Web Applications with Server-Sent Events
- [twitter-sse-demo] A demo of a very basic twitter clone that implements server sent events