Comment diffuser des réponses API en continu avec Server-Sent Events (SSE) ?

Ashley Innocent

Ashley Innocent

13 March 2026

Comment diffuser des réponses API en continu avec Server-Sent Events (SSE) ?

Apidog pour les entreprises

Déploiement sur site

SSO & RBAC

Conforme SOC 2

Découvrir Apidog Enterprise

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.

button

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 :

É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 :

  1. Créer une requête SSE
  2. Définir Accept: text/event-stream
  3. Se connecter et visualiser les événements en temps réel
  4. Valider le format de l'événement
  5. 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.

Pratiquez le Design-first d'API dans Apidog

Découvrez une manière plus simple de créer et utiliser des API