Lección 6 de 1512 min
Tiempo real y estilos de API
WebSocket y WebTransport para mantener la conexión abierta, y REST, GraphQL, SOAP y RPC como formas de diseñar una API.
Imagina el chat de soporte de una tienda. Con HTTP clásico, el navegador pregunta y el servidor responde; pero cuando el agente escribe, ¿cómo se entera el navegador si nadie ha preguntado? Preguntar cada segundo «¿hay mensajes nuevos?» funciona, pero desperdicia peticiones y siempre llega con algo de retraso.
En esta lección verás dos cosas. Primero, los protocolos que mantienen la conexión abierta para que el servidor hable cuando quiera: WebSocket y WebTransport. Después, los estilos más comunes para diseñar una API (REST, GraphQL, SOAP y RPC), vistos desde lo que viaja por el cable. En el módulo de APIs los estudiarás a fondo.
Conexiones que se quedan abiertas
HTTP es de petición y respuesta: el cliente pregunta, el servidor contesta y ahí acaba la conversación. Para que el servidor pueda enviar algo por iniciativa propia hace falta una conexión persistente, que ninguno de los dos cierra.
Sondeo (polling) y long polling
Preguntar al servidor cada poco tiempo: la solución más simple, y la más cara.
- Modelo:
- petición y respuesta
- Coste:
- una petición por intervalo
En el sondeo (polling), el cliente repite la misma petición cada pocos segundos: «¿hay algo nuevo?». Casi siempre la respuesta es «no», así que gastas peticiones, batería y servidor para nada, y la novedad puede llegar con todo un intervalo de retraso.
El long polling mejora el truco: el servidor no responde hasta que tiene algo que contar (o hasta que pasa un tiempo máximo), y el cliente vuelve a preguntar en cuanto recibe la respuesta. Para avisos que solo van del servidor al cliente existe además Server-Sent Events (EventSource), una respuesta HTTP que se mantiene abierta; lo verás en el módulo de APIs.
Úsalo cuando
Cuando las novedades son poco frecuentes y un retraso de unos segundos no importa: comprobar si ha terminado de generarse un informe o si hay una versión nueva de la app.
Ten en cuenta
Con muchos usuarios y un intervalo corto, el sondeo multiplica la carga del servidor. Si necesitas inmediatez, usa una conexión persistente.
// Pregunta cada 10 segundos si el pedido ha cambiado de estado
async function comprobarPedido() {
const respuesta = await fetch("/api/pedidos/42/estado");
const { estado } = await respuesta.json();
mostrarEstado(estado);
if (estado !== "entregado") setTimeout(comprobarPedido, 10_000);
}
comprobarPedido();WebSocket
Un canal bidireccional y permanente entre el navegador y el servidor.
- Estándar:
- RFC 6455
- Esquemas:
- ws://, wss://
WebSocket empieza como una petición HTTP normal con la cabecera Upgrade: websocket. Si el servidor acepta, responde 101 Switching Protocols y, desde ese momento, esa misma conexión TCP deja de hablar HTTP: los dos lados se envían mensajes de texto o binarios cuando quieren, en ambos sentidos y sin las cabeceras HTTP de cada petición.
Usa los esquemas ws:// y, cifrado con TLS, wss://. En el navegador la API es sencilla: creas un WebSocket, escuchas el evento message y envías con send(). En el servidor necesitas un programa preparado para mantener abiertas miles de conexiones a la vez.
Úsalo cuando
Chats, edición colaborativa, cotizaciones, notificaciones en directo o juegos por turnos: cuando el servidor tiene que hablar sin que le pregunten y el cliente también envía a menudo.
Ten en cuenta
La conexión puede cortarse (el móvil cambia de red, un proxy la cierra por inactividad) y el navegador no reconecta solo: tienes que programar la reconexión y, a menudo, un latido (ping) periódico. En producción, usa siempre wss://.
function conectar() {
const socket = new WebSocket("wss://tienda.ejemplo/chat");
socket.addEventListener("open", () => {
socket.send(JSON.stringify({ tipo: "unirse", sala: "soporte" }));
});
socket.addEventListener("message", (evento) => {
pintarMensaje(JSON.parse(evento.data));
});
// El navegador no reconecta solo: reintenta pasados unos segundos
socket.addEventListener("close", () => setTimeout(conectar, 3000));
}
conectar();WebTransport
Tiempo real sobre HTTP/3: varios flujos independientes y datos que pueden perderse.
- Transporte:
- HTTP/3 (QUIC)
- Esquema:
- https://
WebTransport abre una sesión sobre HTTP/3, es decir, sobre QUIC. Dentro de ella puedes crear varios flujos independientes, fiables y ordenados cada uno, y enviar datagramas: mensajes sueltos que no se reenvían si se pierden. Como viste en la lección de protocolos de red, en QUIC un paquete perdido solo frena su propio flujo.
Es lo que necesitan los juegos, el vídeo en directo o el escritorio remoto: la posición de un jugador de hace medio segundo ya no sirve, así que es mejor perderla que esperarla. Su API se basa en los streams de JavaScript (ReadableStream y WritableStream).
Úsalo cuando
Para tiempo real exigente, donde la latencia importa más que recibirlo todo, o cuando necesitas muchos canales independientes por la misma conexión.
Ten en cuenta
Es mucho más reciente que WebSocket: el soporte en navegadores ha llegado de forma desigual, necesitas un servidor con HTTP/3 y hay menos librerías. Comprueba su compatibilidad en MDN y ten preparado un plan B con WebSocket.
const transporte = new WebTransport("https://juego.ejemplo:4433/partida");
await transporte.ready;
// Datagramas: sin reenvíos, ideales para la posición
const posiciones = transporte.datagrams.writable.getWriter();
posiciones.write(new Uint8Array([jugador.x, jugador.y]));
// Un flujo fiable para lo que no puede perderse, como el chat
const flujo = await transporte.createBidirectionalStream();
const chat = flujo.writable.getWriter();
chat.write(new TextEncoder().encode("¡Buena partida!"));Nota
WebSocket y WebTransport solo transportan mensajes: no dicen nada de qué forma tienen. Encima puedes enviar JSON, datos binarios o incluso operaciones de GraphQL, que es como suelen funcionar sus suscripciones.
Estilos de API: qué viaja por el cable
Una API es el contrato con el que un programa pide cosas a otro. Casi todas viajan sobre HTTP, pero lo usan de formas muy distintas: unas aprovechan sus métodos y sus URL, y otras lo tratan como un simple tubo por el que enviar mensajes.
REST
Recursos con URL propia que manipulas con los métodos de HTTP.
- Propuesto por:
- Roy Fielding
- Desde:
- 2000
- Formato habitual:
- JSON
REST (Representational State Transfer) es un estilo de arquitectura, no un protocolo. Cada cosa de tu sistema es un recurso con su propia URL (/pedidos/42), y los métodos HTTP dicen qué hacer con él: GET lo lee, POST crea uno nuevo, PUT o PATCH lo modifican y DELETE lo borra. Los códigos de estado indican cómo ha ido.
Por el cable viaja HTTP tal cual: la URL, el método, las cabeceras y, normalmente, un cuerpo JSON. Como cada petición se entiende por sí sola, sin que el servidor recuerde las anteriores, y las lecturas usan GET, las cachés de HTTP y las CDN funcionan sin hacer nada especial.
Úsalo cuando
Es la opción por defecto para APIs públicas y para las operaciones de crear, leer, actualizar y borrar (CRUD). Cualquier lenguaje y herramienta lo entiende, empezando por fetch y curl.
Ten en cuenta
Una pantalla que combina muchos datos puede necesitar varias peticiones (el pedido, luego el cliente, luego los productos), y a veces cada respuesta trae campos que no usas. Además, muchas APIs que se llaman REST solo son JSON sobre HTTP, sin seguir todas sus reglas.
GET /pedidos?estado=pendiente → lista de pedidos pendientes
GET /pedidos/42 → el pedido 42
POST /pedidos → crea un pedido (cuerpo JSON)
PATCH /pedidos/42 → cambia algunos campos
DELETE /pedidos/42 → lo borra
HTTP/1.1 200 OK
Content-Type: application/json
{ "id": 42, "estado": "pendiente", "total": 59.9 }GraphQL
Un lenguaje de consulta: el cliente pide exactamente los campos que necesita.
- Creado por:
- Público desde:
- 2015
En GraphQL hay un solo endpoint, normalmente /graphql, y un esquema que describe todos los tipos de datos disponibles. El cliente envía una consulta que dice qué campos quiere, incluidos los de datos relacionados, y recibe un JSON con esa misma forma: ni más ni menos.
Por el cable suele viajar un POST con un cuerpo JSON que contiene la consulta y sus variables. Las lecturas son queries, los cambios son mutations y, para recibir avisos en tiempo real, las subscriptions suelen ir sobre WebSocket. Verás cómo se escribe el esquema en la lección de GraphQL SDL.
Úsalo cuando
Cuando varias pantallas o apps (web, móvil) necesitan combinaciones distintas de datos relacionados y quieres evitar muchas peticiones o campos de sobra.
Ten en cuenta
Como todo va por POST al mismo endpoint, las cachés HTTP no sirven tal cual y se suele cachear en el cliente. Una consulta muy anidada puede salirle carísima al servidor. Y muchos servidores devuelven 200 OK aunque haya fallado algo: mira siempre el campo errors.
POST /graphql
Content-Type: application/json
{
"query": "query ($id: ID!) { pedido(id: $id) { estado cliente { nombre } } }",
"variables": { "id": "42" }
}
→ { "data": { "pedido": { "estado": "pendiente", "cliente": { "nombre": "Ana" } } } }SOAP
Mensajes XML con un sobre estricto y un contrato formal descrito en WSDL.
- Formato:
- XML
- Contrato:
- WSDL
- Mantiene:
- W3C
SOAP es un protocolo de mensajería basado en XML. Cada mensaje es un sobre (Envelope) con una cabecera opcional y un cuerpo que indica la operación y sus datos. El servicio se describe en un documento WSDL, a partir del cual las herramientas generan el código del cliente.
Por el cable viaja, casi siempre, un POST HTTP a una única URL con el XML en el cuerpo: HTTP es solo el transporte. Alrededor de SOAP creció una familia de estándares (WS-*) para firmas, cifrado o mensajería fiable, muy presentes en banca, seguros y administraciones públicas.
Úsalo cuando
Cuando te integras con un sistema que ya lo usa, algo habitual en el sector público, la banca y el software empresarial veterano. Para APIs nuevas casi nadie lo elige.
Ten en cuenta
Es verboso, y los errores llegan como un elemento Fault dentro del XML. Al procesar XML de terceros, desactiva las entidades externas para evitar ataques XXE, como viste en la lección de lenguajes y formatos.
POST /servicios/pedidos HTTP/1.1
Content-Type: application/soap+xml; charset=utf-8
<soap:Envelope xmlns:soap="http://www.w3.org/2003/05/soap-envelope">
<soap:Body>
<ConsultarPedido xmlns="https://tienda.ejemplo/pedidos">
<id>42</id>
</ConsultarPedido>
</soap:Body>
</soap:Envelope>RPC y gRPC
Llamar a una función de otro servidor como si estuviera en tu propio código.
- Formato:
- Protocol Buffers
- Transporte:
- HTTP/2
RPC (Remote Procedure Call) es la idea más antigua de todas: en lugar de recursos, expones funciones. El cliente llama a crearPedido(datos) y la librería se encarga de convertir la llamada en un mensaje, enviarlo y devolverte el resultado. JSON-RPC, XML-RPC o tRPC son variantes de esta idea.
gRPC, creado por Google, es el RPC más extendido entre servicios. Defines las funciones y los mensajes en un archivo .proto y una herramienta genera el cliente y el servidor en el lenguaje que quieras. Por el cable viajan mensajes binarios de Protocol Buffers, mucho más compactos que JSON, sobre HTTP/2, que además le permite enviar flujos de mensajes en ambos sentidos.
Úsalo cuando
Para la comunicación interna entre microservicios, donde controlas los dos extremos y quieres rendimiento y un contrato con tipos estrictos.
Ten en cuenta
El navegador no puede hablar gRPC directamente: necesitas gRPC-Web y un proxy que traduzca. Y como los mensajes son binarios, no se leen a simple vista; para depurar hacen falta herramientas específicas.
syntax = "proto3";
service Pedidos {
rpc Consultar (ConsultaPedido) returns (Pedido);
rpc SeguirEnvio (ConsultaPedido) returns (stream Posicion);
}
message ConsultaPedido { string id = 1; }
message Posicion { double lat = 1; double lng = 2; }
message Pedido {
string id = 1;
string estado = 2;
double total = 3;
}Interactivo
REST, GraphQL, SOAP y gRPC por el cable
Activa o desactiva opciones para compararlas cara a cara.
| Característica | REST | GraphQL | SOAP |
|---|---|---|---|
| Qué expone | Recursos | Un esquema de tipos | Operaciones |
| Qué viaja | HTTP tal cual, normalmente con JSON | POST con la consulta en JSON | Sobres XML por POST |
| URLs | Una por recurso | Una sola, /graphql | Una por servicio |
| Contrato | Opcional (por ejemplo, OpenAPI) | El esquema, obligatorio | WSDL, obligatorio |
| Desde el navegador | Directo con fetch | Directo con fetch o un cliente | Posible, pero incómodo |
| Uso típico | APIs públicas y CRUD | Pantallas que combinan muchos datos | Banca, administración, sistemas veteranos |
Ponlo en práctica
Saber qué es cada cosa es la mitad del trabajo. La otra mitad es reconocer cuándo usarla.
Interactivo
¿Qué usarías?
Lee cada situación y elige la opción que mejor la resuelve. Fallar aquí no cuenta: es para practicar.
Una app de bolsa debe mostrar cada precio en cuanto cambia, y el usuario envía órdenes de compra por el mismo canal. No se puede perder ninguna orden.
Para recordar
- HTTP es petición y respuesta; para que el servidor hable por iniciativa propia hace falta una conexión persistente.
- WebSocket es un canal bidireccional y fiable con soporte universal; WebTransport añade flujos independientes y datagramas sobre HTTP/3.
- REST usa HTTP tal cual, con URLs, métodos y cachés; GraphQL envía consultas a un único endpoint y recibe justo lo que pide.
- SOAP envuelve XML en un sobre con un contrato WSDL; gRPC envía Protocol Buffers binarios sobre HTTP/2 entre servicios.
Comprueba lo aprendido
Cuestionario
Responde las 5 preguntas para completar la lección.
1.¿Cómo empieza una conexión WebSocket?
2.¿Qué aporta WebTransport frente a WebSocket?
3.¿Por qué una CDN cachea con facilidad las lecturas de una API REST, pero no las de una API GraphQL?
4.Tu servidor GraphQL responde
200 OK. ¿Significa que todo ha ido bien?5.¿Por qué no puedes llamar a un servicio gRPC directamente con
fetchdesde el navegador?