Cómo Transmitir Respuestas de API con Eventos Enviados por el Servidor (SSE)

Ashley Innocent

Ashley Innocent

13 March 2026

Cómo Transmitir Respuestas de API con Eventos Enviados por el Servidor (SSE)

TL;DR

Utilice Server-Sent Events (SSE) para transmitir respuestas de API a través de HTTP. Envíe Content-Type: text/event-stream y escriba eventos como data: {json}\n\n. SSE funciona para la transmisión de respuestas de IA, actualizaciones de progreso y feeds en vivo. Modern PetstoreAPI utiliza SSE para recomendaciones de mascotas con IA y actualizaciones de estado de pedidos.

Introducción

Su API genera recomendaciones de mascotas con IA. La respuesta tarda 10 segundos. ¿Hace esperar a los usuarios o transmite los resultados a medida que se generan?

Con Server-Sent Events (SSE), transmite las respuestas en tiempo real. Los usuarios ven los resultados inmediatamente a medida que la IA los genera, creando una mejor experiencia.

Modern PetstoreAPI utiliza SSE para recomendaciones de mascotas con IA, actualizaciones de estado de pedidos y cambios de inventario.

Si está probando APIs de transmisión, Apidog es compatible con las pruebas y la validación de SSE.

button

Conceptos Básicos de SSE

SSE es una transmisión unidireccional basada en HTTP del servidor al cliente.

Formato 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

Cada evento:

Eventos Nombrados

event: recommendation
data: {"petId":"019b4132","score":0.95}

event: recommendation
data: {"petId":"019b4127","score":0.89}

event: complete
data: {"total":2}

IDs de Eventos

id: 1
data: {"message":"First"}

id: 2
data: {"message":"Second"}

El cliente puede reanudar desde el último ID si se desconecta.

Implementación del Servidor SSE

Ejemplo con Node.js/Express

app.get('/v1/pets/recommendations/stream', async (req, res) => {
  // Establecer encabezados SSE
  res.setHeader('Content-Type', 'text/event-stream');
  res.setHeader('Cache-Control', 'no-cache');
  res.setHeader('Connection', 'keep-alive');

  // Enviar recomendaciones a medida que se generan
  const recommendations = await generateRecommendations(req.query.userId);

  for (const rec of recommendations) {
    res.write(`data: ${JSON.stringify(rec)}\n\n`);
    await sleep(100); // Simular retraso de transmisión
  }

  // Enviar evento de finalización
  res.write(`event: complete\ndata: {"total":${recommendations.length}}\n\n`);
  res.end();
});

Ejemplo con 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"
        }
    )

Implementación del Cliente SSE

JavaScript/Navegador

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);
  eventSource.close();
};

Hook de 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 };
}

// Uso
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>
  );
}

Cómo Modern PetstoreAPI Utiliza SSE

Recomendaciones de Mascotas con IA

Transmita recomendaciones generadas por 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}

Actualizaciones de Estado de Pedidos

Transmita los pasos de procesamiento de pedidos:

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"}

Cambios de Inventario

Transmita actualizaciones de inventario en tiempo real:

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}

Consulte la documentación de SSE de Modern PetstoreAPI.

Prueba de SSE con Apidog

Apidog es compatible con las pruebas de SSE:

  1. Crear solicitud SSE
  2. Establecer Accept: text/event-stream
  3. Conectar y ver eventos en tiempo real
  4. Validar formato de evento
  5. Probar reconexión

Mejores Prácticas

1. Establecer Encabezados Apropiados

res.setHeader('Content-Type', 'text/event-stream');
res.setHeader('Cache-Control', 'no-cache');
res.setHeader('Connection', 'keep-alive');
res.setHeader('X-Accel-Buffering', 'no'); // Deshabilitar el almacenamiento en búfer de Nginx

2. Enviar Latidos (Heartbeats)

Mantener la conexión activa:

const heartbeat = setInterval(() => {
  res.write(': heartbeat\n\n');
}, 15000);

res.on('close', () => clearInterval(heartbeat));

3. Manejar Errores con Gracia

eventSource.onerror = (error) => {
  if (eventSource.readyState === EventSource.CLOSED) {
    // Conexión cerrada, se reconectará automáticamente
  } else {
    // Otro error
    console.error('SSE error:', error);
  }
};

4. Usar IDs de Eventos para Reanudar

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. Cerrar Conexiones

// Cliente
eventSource.addEventListener('complete', () => {
  eventSource.close();
});

// Servidor
res.on('close', () => {
  // Limpiar recursos
});

Conclusión

SSE es perfecto para transmitir respuestas de API. Es más sencillo que WebSocket para la comunicación unidireccional, funciona a través de HTTP y maneja la reconexión automáticamente.

Modern PetstoreAPI utiliza SSE para la transmisión de IA, actualizaciones de pedidos y feeds en vivo. Pruebe los puntos finales de SSE con Apidog.

Preguntas Frecuentes

¿Puede SSE funcionar a través de firewalls corporativos?

Sí, SSE utiliza HTTP/HTTPS estándar, por lo que funciona a través de la mayoría de los firewalls y proxies.

¿Cuánto tiempo pueden permanecer abiertas las conexiones SSE?

Indefinidamente, pero use latidos (heartbeats) cada 15-30 segundos para mantener las conexiones activas a través de proxies.

¿Puedo enviar datos binarios a través de SSE?

No, SSE es solo texto. Codifique los datos binarios en Base64 o use WebSocket en su lugar.

¿SSE admite comunicación bidireccional?

No, SSE es solo de servidor a cliente. Los clientes usan solicitudes HTTP regulares para la comunicación de cliente a servidor.

¿Cuántas conexiones SSE puede tener un navegador?

Los navegadores limitan las conexiones SSE por dominio (típicamente 6). Use multiplexación o WebSocket para muchas conexiones.

Practica el diseño de API en Apidog

Descubre una forma más fácil de construir y usar APIs