Usa WebTransport

WebTransport es una API que ofrece mensajería bidireccional y de baja latencia entre cliente y servidor. Obtén más información sobre sus casos de uso y cómo enviar comentarios sobre el futuro de la implementación.

Segundo plano

¿Qué es WebTransport?

WebTransport es una API web que usa el protocolo HTTP/3 como transporte bidireccional. Está diseñado para comunicaciones de dos vías entre un cliente web y un servidor HTTP/3. Admite el envío de datos de forma no confiable a través de sus APIs de datagramas y de forma confiable a través de sus APIs de flujos.

Los datagramas son ideales para enviar y recibir datos que no necesitan garantías de entrega sólidas. El tamaño de los paquetes de datos individuales está limitado por la unidad máxima de transmisión (MTU) de la conexión subyacente y pueden transmitirse o no de forma correcta. Si se transfieren, pueden llegar en un orden arbitrario. Estas características hacen que las APIs de datagramas sean ideales para la transmisión de datos de latencia baja y del mejor esfuerzo. Puedes considerar los datagramas como mensajes del protocolo de datagramas de usuario (UDP), pero encriptados y controlados por congestión.

En cambio, las APIs de flujos proporcionan una transferencia de datos ordenada y confiable. Son adecuadas para situaciones en las que necesitas enviar o recibir uno o más flujos de datos ordenados. El uso de múltiples transmisiones de WebTransport es similar a establecer varias conexiones TCP, pero como HTTP/3 usa el protocolo QUIC más ligero, se pueden abrir y cerrar sin tanta sobrecarga.

Casos de uso

Esta es una pequeña lista de las posibles formas en que los desarrolladores pueden usar WebTransport.

  • Envía el estado del juego a un servidor en un intervalo regular con latencia mínima a través de mensajes pequeños, poco confiables y fuera de orden.
  • Recibir transmisiones de contenido multimedia enviadas desde un servidor con latencia mínima, independientemente de otras transmisiones de datos
  • Recibir notificaciones enviadas desde un servidor mientras una página web está abierta

Nos gustaría obtener más información sobre cómo planeas usar WebTransport.

Navegadores compatibles

Navegadores compatibles

  • Chrome: 97.
  • Edge: 97.
  • Firefox: 114.
  • Safari: No se admite.

Origen

Al igual que con todas las funciones que no tienen compatibilidad universal con navegadores, se recomienda codificar de forma defensiva a través de la detección de funciones.

Estado actual

Paso Estado
1. Crea una explicación Completar
2. Crea un borrador inicial de la especificación Completar
3. Recopila comentarios y itera el diseño Completado
4. Prueba de origen Completado
5. Lanzamiento Chromium 97

Relación de WebTransport con otras tecnologías

¿WebTransport reemplaza a WebSockets?

Tal vez. Hay casos de uso en los que WebSockets o WebTransport pueden ser protocolos de comunicación válidos para usar.

Las comunicaciones de WebSockets se modelan en torno a una sola transmisión de mensajes ordenada, confiable y segura, lo que es adecuado para algunos tipos de necesidades de comunicación. Si necesitas esas características, las APIs de flujos de WebTransport también pueden proporcionarlas. En comparación, las APIs de datagramas de WebTransport proporcionan una entrega de baja latencia, sin garantías de confiabilidad ni orden, por lo que no son un reemplazo directo de WebSockets.

El uso de WebTransport, a través de las APIs de datagramas o de varias instancias simultáneas de la API de Streams, significa que no tienes que preocuparte por el bloqueo de fila de prioridad, que puede ser un problema con WebSockets. Además, hay beneficios de rendimiento cuando se establecen conexiones nuevas, ya que el protocolo de enlace QUIC subyacente es más rápido que iniciar TCP a través de TLS.

WebTransport forma parte de un nuevo borrador de especificación y, por lo tanto, el ecosistema de WebSocket en torno a las bibliotecas de clientes y servidores es actualmente mucho más sólido. Si necesitas algo que funcione “listo para usar” con configuraciones de servidor comunes y con una amplia compatibilidad con clientes web, WebSockets es la mejor opción en la actualidad.

¿WebTransport es lo mismo que una API de socket UDP?

No. WebTransport no es una API de socket UDP. Si bien WebTransport usa HTTP/3, que a su vez usa UDP "debajo del capó", tiene requisitos relacionados con la encriptación y el control de congestión que lo convierten en algo más que una API básica de socket UDP.

¿WebTransport es una alternativa a los canales de datos de WebRTC?

Sí, para las conexiones cliente-servidor. WebTransport comparte muchas de las mismas propiedades que los canales de datos de WebRTC, aunque los protocolos subyacentes son diferentes.

Por lo general, ejecutar un servidor compatible con HTTP/3 requiere menos configuración que mantener un servidor WebRTC, lo que implica comprender varios protocolos (ICE, DTLS y SCTP) para obtener un transporte que funcione. WebRTC implica muchos más elementos móviles que podrían provocar negociaciones fallidas entre el cliente y el servidor.

La API de WebTransport se diseñó teniendo en cuenta los casos de uso de los desarrolladores web y debería ser más similar a escribir código de plataforma web moderno que usar las interfaces de canal de datos de WebRTC. A diferencia de WebRTC, WebTransport es compatible con Web Workers, lo que te permite realizar comunicaciones cliente-servidor independientemente de una página HTML determinada. Debido a que WebTransport expone una interfaz compatible con Streams, admite optimizaciones en torno a la presión de retorno.

Sin embargo, si ya tienes una configuración de cliente-servidor de WebRTC que funciona y te satisface, es posible que cambiar a WebTransport no ofrezca muchas ventajas.

Probar

La mejor manera de experimentar con WebTransport es iniciar un servidor HTTP/3 compatible. Luego, puedes usar esta página con un cliente de JavaScript básico para probar las comunicaciones cliente-servidor.

Además, hay un servidor de eco mantenido por la comunidad disponible en webtransport.day.

Usar la API

WebTransport se diseñó sobre primitivas modernas de la plataforma web, como la API de Streams. Se basa en gran medida en las promesas y funciona bien con async y await.

La implementación actual de WebTransport en Chromium admite tres tipos de tráfico distintos: datagramas, así como flujos unidireccionales y bidireccionales.

Conexión con un servidor

Para conectarte a un servidor HTTP/3, crea una instancia de WebTransport. El esquema de la URL debe ser https. Debes especificar explícitamente el número de puerto.

Debes usar la promesa ready para esperar a que se establezca la conexión. Esta promesa no se cumplirá hasta que se complete la configuración y se rechazará si la conexión falla en la etapa QUIC/TLS.

La promesa closed se cumple cuando la conexión se cierra de forma normal y se rechaza si el cierre fue inesperado.

Si el servidor rechaza la conexión debido a un error de indicación del cliente (p.ej., la ruta de acceso de la URL no es válida), se rechaza closed, mientras que ready permanece sin resolver.

const url = 'https://example.com:4999/foo/bar';
const transport = new WebTransport(url);

// Optionally, set up functions to respond to
// the connection closing:
transport.closed.then(() => {
  console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
}).catch((error) => {
  console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
});

// Once .ready fulfills, the connection can be used.
await transport.ready;

APIs de datagramas

Una vez que tengas una instancia de WebTransport conectada a un servidor, podrás usarla para enviar y recibir bits de datos discretos, conocidos como datagrams.

El método get writeable muestra un WritableStream, que un cliente web puede usar para enviar datos al servidor. El método get readable muestra un ReadableStream, lo que te permite escuchar datos del servidor. Ambas transmisiones son inherentemente poco confiables, por lo que es posible que el servidor no reciba los datos que escribas y viceversa.

Ambos tipos de flujos usan instancias de Uint8Array para la transferencia de datos.

// Send two datagrams to the server.
const writer = transport.datagrams.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);

// Read datagrams from the server.
const reader = transport.datagrams.readable.getReader();
while (true) {
  const {value, done} = await reader.read();
  if (done) {
    break;
  }
  // value is a Uint8Array.
  console.log(value);
}

APIs de Streams

Una vez que te conectes al servidor, también puedes usar WebTransport para enviar y recibir datos a través de sus APIs de Streams.

Cada fragmento de todas las transmisiones es un Uint8Array. A diferencia de las APIs de Datagram, estas transmisiones son confiables. Sin embargo, cada flujo es independiente, por lo que no se garantiza el orden de los datos entre los flujos.

WebTransportSendStream

El cliente web crea un WebTransportSendStream con el método createUnidirectionalStream() de una instancia de WebTransport, que muestra una promesa para el WebTransportSendStream.

Usa el método close() de WritableStreamDefaultWriter para cerrar la conexión HTTP/3 asociada. El navegador intenta enviar todos los datos pendientes antes de cerrar la conexión asociada.

// Send two Uint8Arrays to the server.
const stream = await transport.createUnidirectionalStream();
const writer = stream.writable.getWriter();
const data1 = new Uint8Array([65, 66, 67]);
const data2 = new Uint8Array([68, 69, 70]);
writer.write(data1);
writer.write(data2);
try {
  await writer.close();
  console.log('All data has been sent.');
} catch (error) {
  console.error(`An error occurred: ${error}`);
}

Del mismo modo, usa el método abort() de WritableStreamDefaultWriter para enviar un RESET\_STREAM al servidor. Cuando se usa abort(), el navegador puede descartar los datos pendientes que aún no se enviaron.

const ws = await transport.createUnidirectionalStream();
const writer = ws.getWriter();
writer.write(...);
writer.write(...);
await writer.abort();
// Not all the data may have been written.

WebTransportReceiveStream

El servidor inicia un WebTransportReceiveStream. Obtener un WebTransportReceiveStream es un proceso de dos pasos para un cliente web. Primero, llama al atributo incomingUnidirectionalStreams de una instancia WebTransport, que muestra un ReadableStream. Cada fragmento de ese ReadableStream es, a su vez, un WebTransportReceiveStream que se puede usar para leer instancias de Uint8Array que envía el servidor.

async function readFrom(receiveStream) {
  const reader = receiveStream.readable.getReader();
  while (true) {
    const {done, value} = await reader.read();
    if (done) {
      break;
    }
    // value is a Uint8Array
    console.log(value);
  }
}

const rs = transport.incomingUnidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is an instance of WebTransportReceiveStream
  await readFrom(value);
}

Puedes detectar el cierre de la transmisión con la promesa closed de ReadableStreamDefaultReader. Cuando la conexión HTTP/3 subyacente se cierra con el bit FIN, se cumple la promesa closed después de que se leen todos los datos. Cuando la conexión HTTP/3 se cierra de forma abrupta (por ejemplo, por RESET\_STREAM), se rechaza la promesa closed.

// Assume an active receiveStream
const reader = receiveStream.readable.getReader();
reader.closed.then(() => {
  console.log('The receiveStream closed gracefully.');
}).catch(() => {
  console.error('The receiveStream closed abruptly.');
});

WebTransportBidirectionalStream

El servidor o el cliente pueden crear un WebTransportBidirectionalStream.

Los clientes web pueden crear uno con el método createBidirectionalStream() de una instancia de WebTransport, que muestra una promesa para un WebTransportBidirectionalStream.

const stream = await transport.createBidirectionalStream();
// stream is a WebTransportBidirectionalStream
// stream.readable is a ReadableStream
// stream.writable is a WritableStream

Puedes detectar un WebTransportBidirectionalStream creado por el servidor con el atributo incomingBidirectionalStreams de una instancia de WebTransport, que muestra un ReadableStream. Cada fragmento de ese ReadableStream, a su vez, es un WebTransportBidirectionalStream.

const rs = transport.incomingBidirectionalStreams;
const reader = rs.getReader();
while (true) {
  const {done, value} = await reader.read();
  if (done) {
    break;
  }
  // value is a WebTransportBidirectionalStream
  // value.readable is a ReadableStream
  // value.writable is a WritableStream
}

Un WebTransportBidirectionalStream es solo una combinación de WebTransportSendStream y WebTransportReceiveStream. En los ejemplos de las dos secciones anteriores, se explica cómo usar cada uno de ellos.

Más ejemplos

El borrador de la especificación de WebTransport incluye una serie de ejemplos intercalados adicionales, junto con la documentación completa de todos los métodos y propiedades.

WebTransport en las Herramientas para desarrolladores de Chrome

Lamentablemente, las Herramientas para desarrolladores de Chrome no son compatibles con WebTransport en este momento. Puedes "destacar" este problema de Chrome para recibir notificaciones sobre actualizaciones en la interfaz de DevTools.

Polyfill

Hay disponible un polyfill (o ponyfill que proporciona funcionalidad como un módulo independiente que puedes usar) llamado webtransport-ponyfill-websocket que implementa algunas de las funciones de WebTransport. Lee cuidadosamente las restricciones en el README del proyecto para determinar si esta solución puede funcionar para tu caso de uso.

Consideraciones de privacidad y seguridad

Consulta la sección correspondiente del borrador de la especificación para obtener orientación autorizada.

Comentarios

El equipo de Chrome quiere conocer tus opiniones y experiencias con esta API.

Comentarios sobre el diseño de la API

¿Hay algo en la API que sea incómodo o no funcione como se espera? ¿O faltan piezas que necesitas para implementar tu idea?

Informa un problema en el repositorio de GitHub de Web Transport o agrega tus comentarios a un problema existente.

¿Tienes problemas con la implementación?

¿Encontraste un error en la implementación de Chrome?

Informa un error en https://new.crbug.com. Incluye tantos detalles como sea posible, junto con instrucciones simples para reproducirlo.

¿Tienes pensado usar la API?

Tu asistencia pública ayuda a Chrome a priorizar las funciones y les muestra a otros proveedores de navegadores lo importante que es admitirlas.

Análisis general

Puedes usar el grupo de Google web-transport-dev para preguntas o problemas generales que no se ajusten a ninguna de las otras categorías.

Agradecimientos

En este artículo, se incorpora información de la explicación de WebTransport, el borrador de la especificación y los documentos de diseño relacionados. Gracias a los respectivos autores por proporcionar esa base.

La imagen hero de esta publicación es de Robin Pierre en Unsplash.