En bref
Utilisez les Server-Sent Events (SSE) pour diffuser les réponses d'API via HTTP. Envoyez Content-Type: text/event-stream et écrivez les événements comme data: {json}\n\n. Les SSE sont utiles pour la diffusion de réponses d'IA, les mises à jour de progression et les flux en direct. La Modern PetstoreAPI utilise les SSE pour les recommandations d'animaux par IA et les mises à jour du statut des commandes.
Introduction
Votre API génère des recommandations d'animaux par IA. La réponse prend 10 secondes. Faites-vous attendre les utilisateurs, ou diffusez-vous les résultats au fur et à mesure qu'ils sont générés ?
Avec les Server-Sent Events (SSE), vous diffusez les réponses en temps réel. Les utilisateurs voient les résultats immédiatement à mesure que l'IA les génère, ce qui crée une meilleure expérience.
La Modern PetstoreAPI utilise les SSE pour les recommandations d'animaux par IA, les mises à jour du statut des commandes et les changements d'inventaire.
Si vous testez des API de streaming, Apidog prend en charge les tests et la validation SSE.
Bases des SSE
Les SSE sont un flux unidirectionnel basé sur HTTP, du serveur au client.
Format SSE
Content-Type: text/event-stream
Cache-Control: no-cache
data: {"message":"First chunk"}\n\n
data: {"message":"Second chunk"}\n\n
data: {"message":"Third chunk"}\n\n
Chaque événement :
- Commence par
data: - Contient la charge utile
- Se termine par
\n\n(deux nouvelles lignes)
Événements nommés
event: recommendation
data: {"petId":"019b4132","score":0.95}
event: recommendation
data: {"petId":"019b4127","score":0.89}
event: complete
data: {"total":2}
ID d'événement
id: 1
data: {"message":"First"}
id: 2
data: {"message":"Second"}
Le client peut reprendre à partir du dernier ID s'il est déconnecté.
Implémentation du serveur SSE
Exemple Node.js/Express
app.get('/v1/pets/recommendations/stream', async (req, res) => {
// Définir les en-têtes SSE
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
// Envoyer les recommandations au fur et à mesure qu'elles sont générées
const recommendations = await generateRecommendations(req.query.userId);
for (const rec of recommendations) {
res.write(`data: ${JSON.stringify(rec)}\n\n`);
await sleep(100); // Simuler un délai de diffusion
}
// Envoyer l'événement de complétion
res.write(`event: complete\ndata: {"total":${recommendations.length}}\n\n`);
res.end();
});
Exemple Python/FastAPI
from fastapi import FastAPI
from fastapi.responses import StreamingResponse
import json
import asyncio
app = FastAPI()
@app.get("/v1/pets/recommendations/stream")
async def stream_recommendations(user_id: str):
async def generate():
recommendations = await get_recommendations(user_id)
for rec in recommendations:
yield f"data: {json.dumps(rec)}\n\n"
await asyncio.sleep(0.1)
yield f"event: complete\ndata: {json.dumps({'total': len(recommendations)})}\n\n"
return StreamingResponse(
generate(),
media_type="text/event-stream",
headers={
"Cache-Control": "no-cache",
"Connection": "keep-alive"
}
)
Implémentation du client SSE
JavaScript/Navigateur
const eventSource = new EventSource(
'https://petstoreapi.com/v1/pets/recommendations/stream?userId=user-456'
);
eventSource.onmessage = (event) => {
const data = JSON.parse(event.data);
displayRecommendation(data);
};
eventSource.addEventListener('complete', (event) => {
const data = JSON.parse(event.data);
console.log(`Received ${data.total} recommendations`);
eventSource.close();
});
eventSource.onerror = (error) => {
console.error('SSE error:', error);
if (eventSource.readyState === EventSource.CLOSED) {
// Connexion fermée, se reconnectera automatiquement
} else {
// Autre erreur
console.error('SSE error:', error);
}
eventSource.close();
};
Hook React
import { useEffect, useState } from 'react';
function useSSE(url) {
const [data, setData] = useState([]);
const [complete, setComplete] = useState(false);
useEffect(() => {
const eventSource = new EventSource(url);
eventSource.onmessage = (event) => {
const item = JSON.parse(event.data);
setData(prev => [...prev, item]);
};
eventSource.addEventListener('complete', () => {
setComplete(true);
eventSource.close();
});
return () => eventSource.close();
}, [url]);
return { data, complete };
}
// Utilisation
function Recommendations({ userId }) {
const { data, complete } = useSSE(
`https://petstoreapi.com/v1/pets/recommendations/stream?userId=${userId}`
);
return (
<div>
{data.map(rec => (
<PetCard key={rec.petId} pet={rec} />
))}
{!complete && <Spinner />}
</div>
);
}
Comment la Modern PetstoreAPI utilise les SSE
Recommandations d'animaux par IA
Diffuser des recommandations générées par IA :
GET /v1/pets/recommendations/stream?userId=user-456
Accept: text/event-stream
event: recommendation
data: {"petId":"019b4132","name":"Fluffy","score":0.95,"reason":"Matches your preference for cats"}
event: recommendation
data: {"petId":"019b4127","name":"Buddy","score":0.89,"reason":"Similar to pets you liked"}
event: complete
data: {"total":2,"processingTime":850}
Mises à jour du statut des commandes
Diffuser les étapes de traitement des commandes :
GET /v1/orders/019b4132/status/stream
Accept: text/event-stream
data: {"status":"payment_processing","timestamp":"2026-03-13T10:30:00Z"}
data: {"status":"payment_confirmed","timestamp":"2026-03-13T10:30:02Z"}
data: {"status":"preparing_shipment","timestamp":"2026-03-13T10:30:05Z"}
event: complete
data: {"status":"shipped","trackingNumber":"1Z999AA10123456784"}
Changements d'inventaire
Diffuser les mises à jour d'inventaire en temps réel :
GET /v1/inventory/stream
Accept: text/event-stream
event: stock-change
data: {"petId":"019b4132","oldStock":5,"newStock":4}
event: price-change
data: {"petId":"019b4127","oldPrice":299.99,"newPrice":279.99}
Consultez la documentation SSE de la Modern PetstoreAPI.
Tester les SSE avec Apidog
Apidog prend en charge les tests SSE :
- Créer une requête SSE
- Définir
Accept: text/event-stream - Se connecter et visualiser les événements en temps réel
- Valider le format de l'événement
- Tester la reconnexion
Bonnes pratiques
1. Définir les en-têtes appropriés
res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no'); // Désactiver la mise en mémoire tampon de nginx
2. Envoyer des signaux de vie (heartbeats)
Maintenir la connexion active :
const heartbeat = setInterval(() => {
res.write(': heartbeat\n\n');
}, 15000);
res.on('close', () => clearInterval(heartbeat));
3. Gérer les erreurs avec élégance
eventSource.onerror = (error) => {
if (eventSource.readyState === EventSource.CLOSED) {
// Connexion fermée, se reconnectera automatiquement
} else {
// Autre erreur
console.error('SSE error:', error);
}
};
4. Utiliser les ID d'événement pour la reprise
let lastEventId = 0;
app.get('/stream', (req, res) => {
const startId = parseInt(req.headers['last-event-id'] || '0');
for (let i = startId + 1; i <= 100; i++) {
res.write(`id: ${i}\ndata: {"message":"Event ${i}"}\n\n`);
}
});
5. Fermer les connexions
// Côté client
eventSource.addEventListener('complete', () => {
eventSource.close();
});
// Côté serveur
res.on('close', () => {
// Nettoyer les ressources
});
Conclusion
Les SSE sont parfaites pour la diffusion de réponses d'API. Elles sont plus simples que les WebSockets pour la communication unidirectionnelle, fonctionnent via HTTP et gèrent la reconnexion automatiquement.
La Modern PetstoreAPI utilise les SSE pour le streaming IA, les mises à jour de commandes et les flux en direct. Testez les points de terminaison SSE avec Apidog.
FAQ
Les SSE peuvent-elles fonctionner à travers les pare-feu d'entreprise ?
Oui, les SSE utilisent HTTP/HTTPS standard, elles fonctionnent donc à travers la plupart des pare-feu et des proxies.
Combien de temps les connexions SSE peuvent-elles rester ouvertes ?
Indéfiniment, mais utilisez des signaux de vie (heartbeats) toutes les 15 à 30 secondes pour maintenir les connexions actives à travers les proxies.
Puis-je envoyer des données binaires via SSE ?
Non, les SSE sont uniquement textuelles. Encodez les données binaires en Base64 ou utilisez WebSocket à la place.
Les SSE prennent-elles en charge la communication bidirectionnelle ?
Non, les SSE sont uniquement du serveur au client. Les clients utilisent des requêtes HTTP régulières pour la communication client-serveur.
Combien de connexions SSE un navigateur peut-il avoir ?
Les navigateurs limitent les connexions SSE par domaine (généralement 6). Utilisez le multiplexage ou WebSocket pour un grand nombre de connexions.
