📖 1. Introduction aux Server-Sent Events
Les Server-Sent Events (SSE) permettent au serveur d'envoyer des mises à jour automatiques au client (navigation web) via une connexion HTTP persistante.
❌ Polling (avant SSE)
- Requêtes répétitives
- Latence élevée
- Surcharge réseau importante
✅ SSE
- Communication unidirectionnelle serveur → client
- Faible latence
- Reconnexion automatique
- Basé sur HTTP/HTTPS
Temps réel
Notifications instantanées
Auto-reconnexion
Gérée nativement par le navigateur
Facile à utiliser
API simple sur navigateur
Léger
Format texte simple (text/event-stream)
🌐 2. Support navigateurs
Chrome
Firefox
Safari
Edge
Opera
// Détection du support SSE
if (typeof(EventSource) !== "undefined") {
console.log("SSE est supporté");
// Créer une connexion SSE
const source = new EventSource("sse.php");
} else {
console.log("SSE n'est pas supporté");
// Fallback: utiliser le polling
}
💻 3. Client Web Application
Côté client, l'API EventSource permet de se connecter au flux SSE.
// Créer une connexion SSE
const source = new EventSource('chemin/vers/le/script-sse');
// Écouter les messages
source.onmessage = function(event) {
console.log('Message reçu:', event.data);
// Mettre à jour l'interface utilisateur
document.getElementById('notifications').innerHTML += '<p>' + event.data + '</p>';
};
// Gestion des erreurs
source.onerror = function(event) {
console.log('Erreur de connexion SSE');
};
📝 Démo : Client SSE (simulation)
🖥️ 4. Server Side Script
Côté serveur, le script doit envoyer les données au format text/event-stream.
<?php
// sse.php - Exemple PHP
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
header('Access-Control-Allow-Origin: *');
while(true) {
$time = date('H:i:s');
echo "data: Le serveur est actif à {$time}\n\n";
flush();
sleep(2);
}
?>
📌 Format du flux SSE
data: message\n\n– Message standardevent: nom\n– Spécifie le type d'événementid: 123\n– ID du messageretry: 3000\n– Temps de reconnexion (ms)
📡 5. Gestion des événements
onopen
Déclenché lorsque la connexion est établie
onmessage
Déclenché à chaque réception de message
onerror
Déclenché en cas d'erreur (réseau, serveur)
const source = new EventSource('sse.php');
source.onopen = function() {
console.log('Connexion SSE établie');
document.getElementById('status').innerHTML = '🟢 Connecté';
};
source.onmessage = function(event) {
console.log('Données:', event.data);
updateUI(event.data);
};
source.onerror = function(event) {
console.error('Erreur SSE');
document.getElementById('status').innerHTML = '🔴 Erreur de connexion';
};
🏷️ 6. Événements nommés
Il est possible de définir plusieurs types d'événements.
<?php
// Côté serveur (PHP)
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
while(true) {
// Envoi d'un événement "news"
echo "event: news\n";
echo "data: Nouvelle actualité importante !\n\n";
// Envoi d'un événement "weather"
echo "event: weather\n";
echo "data: Température: 22°C\n\n";
flush();
sleep(5);
}
?>
// Côté client
const source = new EventSource('sse.php');
// Écouter l'événement 'news'
source.addEventListener('news', function(event) {
console.log('Actualité:', event.data);
});
// Écouter l'événement 'weather'
source.addEventListener('weather', function(event) {
console.log('Météo:', event.data);
});
📝 Démo : Événements nommés
🔄 7. Reconnexion automatique
Le navigateur tente automatiquement de se reconnecter si la connexion est perdue.
<?php
// Côté serveur : contrôler le délai de reconnexion
header('Content-Type: text/event-stream');
header('Cache-Control: no-cache');
// Définir le délai de reconnexion (5 secondes)
echo "retry: 5000\n\n";
while(true) {
echo "data: Message périodique\n\n";
flush();
sleep(10);
}
?>
📌 Comportement
- Si la connexion est interrompue, le navigateur tente de se reconnecter
- Le délai par défaut est de 3 secondes
- La directive
retry: Xpermet de modifier ce délai (en millisecondes) - La reconnexion est automatique, pas besoin de code supplémentaire
🔌 8. Fermeture de la connexion
Pour fermer manuellement une connexion SSE, utilisez la méthode close().
let source = null;
// Démarrer la connexion
function startSSE() {
source = new EventSource('sse.php');
source.onmessage = function(event) {
console.log(event.data);
};
}
// Fermer la connexion
function stopSSE() {
if (source) {
source.close();
console.log('Connexion SSE fermée');
source = null;
}
}
📝 9. Exemple complet : Flux d'actualités
<!DOCTYPE html>
<html>
<head>
<title>Flux d'actualités en temps réel</title>
<style>
body { font-family: Arial, sans-serif; max-width: 800px; margin: 0 auto; padding: 20px; }
.news-item { background: #f8f9fa; border-left: 4px solid #3498db; padding: 10px; margin: 10px 0; }
.time { color: #666; font-size: 0.8em; }
#status { padding: 8px; border-radius: 6px; margin-bottom: 15px; }
.connected { background: #d4edda; color: #155724; }
.error { background: #f8d7da; color: #721c24; }
</style>
</head>
<body>
<h1>📰 Flux d'actualités en temps réel</h1>
<div id="status">🟡 Connexion en cours...</div>
<div id="news"></div>
<script>
let eventSource = null;
const newsDiv = document.getElementById('news');
const statusDiv = document.getElementById('status');
function startSSE() {
if (eventSource) eventSource.close();
eventSource = new EventSource('news.php');
eventSource.onopen = function() {
statusDiv.className = 'connected';
statusDiv.innerHTML = '🟢 Connecté - En attente d\'actualités...';
};
eventSource.onmessage = function(event) {
const data = JSON.parse(event.data);
const newsItem = document.createElement('div');
newsItem.className = 'news-item';
newsItem.innerHTML = `
<div><strong>${data.title}</strong></div>
<p>${data.content}</p>
<div class="time">${new Date().toLocaleTimeString()}</div>
`;
newsDiv.insertBefore(newsItem, newsDiv.firstChild);
// Garder seulement les 20 dernières actualités
while(newsDiv.children.length > 20) {
newsDiv.removeChild(newsDiv.lastChild);
}
};
eventSource.onerror = function() {
statusDiv.className = 'error';
statusDiv.innerHTML = '🔴 Erreur de connexion - Reconnexion automatique...';
};
}
startSSE();
// Fermer la connexion en quittant la page
window.addEventListener('beforeunload', function() {
if (eventSource) eventSource.close();
});
</script>
</body>
</html>
📝 Démo : Flux d'actualités simulé
📝 Tableau récapitulatif
| Objet/Méthode | Description | Exemple |
|---|---|---|
new EventSource(url) |
Crée une connexion SSE | new EventSource('stream.php') |
onopen |
Événement de connexion établie | source.onopen = () => {...} |
onmessage |
Réception d'un message | source.onmessage = (e) => {...} |
onerror |
Erreur de connexion | source.onerror = () => {...} |
addEventListener() |
Écouter un événement nommé | source.addEventListener('news', fn) |
close() |
Ferme la connexion | source.close() |
📌 Quiz de vérification
Question 1 : Quelle est la différence principale entre SSE et WebSocket ?
SSE est unidirectionnel (serveur → client), WebSocket est bidirectionnel (client ↔ serveur). SSE est plus simple pour des flux de données comme les notifications.
Question 2 : Comment créer une connexion SSE côté client ?
const source = new EventSource('url_du_script_sse');
Question 3 : Quelle en-tête HTTP est obligatoire pour un script SSE ?
Content-Type: text/event-stream
Question 4 : Que se passe-t-il si la connexion SSE est interrompue ?
Le navigateur tente automatiquement de se reconnecter, avec un délai configurable via la directive retry.