Dieser Inhalt wurde automatisch aus dem Englischen übersetzt, und kann Fehler enthalten. Erfahre mehr über dieses Experiment.

View in English Always switch to English

WebTransport API

Baseline 2026
Neu verfügbar
*

Seit März 2026 funktioniert diese Funktion auf aktuellen Geräten und in aktuellen Browserversionen. Auf älteren Geräten oder in älteren Browsern funktioniert sie möglicherweise nicht.

* Einige Teile dieser Funktion werden möglicherweise unterschiedlich gut unterstützt.

Sicherer Kontext: Diese Funktion ist nur in sicheren Kontexten (HTTPS) in einigen oder allen unterstützenden Browsern verfügbar.

Hinweis: Diese Funktion ist in Web Workers verfügbar.

Die WebTransport API ist eine moderne Weiterentwicklung von WebSockets. Sie überträgt Daten zwischen Client und Server über HTTP/3 Transport. WebTransport unterstützt mehrere Streams, unidirektionale Streams und die Zustellung in abweichender Reihenfolge. Die API ermöglicht zuverlässige Übertragung über Streams und unzuverlässige Übertragung über UDP-ähnliche Datagramme.

Konzepte und Verwendung

HTTP/3 wurde 2022 nach mehrjähriger Entwicklung standardisiert. Es basiert auf dem QUIC-Protokoll, das seinerseits auf UDP basiert und 2021 standardisiert wurde. HTTP/3 behebt mehrere Probleme des klassischen TCP-Protokolls, auf dem HTTP und WebSockets basieren.

Dazu gehören:

Head-of-Line-Blocking

HTTP/2 ermöglicht Multiplexing, sodass über eine einzelne Verbindung mehrere Ressourcen gleichzeitig übertragen werden können. Tritt jedoch bei einer einzelnen Ressource ein Fehler auf, werden alle anderen Ressourcen auf dieser Verbindung aufgehalten, bis fehlende Pakete erneut übertragen wurden. Bei QUIC ist nur die betroffene Ressource beeinträchtigt.

Höhere Leistung

QUIC ist in vielerlei Hinsicht leistungsfähiger als TCP. QUIC kann Sicherheitsfunktionen selbst übernehmen, statt sie anderen Protokollen wie TLS zu überlassen – dadurch sind weniger Hin- und Rückübertragungen nötig. Außerdem ermöglichen Streams eine effizientere Übertragung als der ältere paketbasierte Mechanismus. Das kann insbesondere in Netzwerken mit hoher Latenz einen erheblichen Unterschied machen.

Bessere Netzwerkwechsel

QUIC verwendet eine eindeutige Verbindungs-ID, um Quelle und Ziel jeder Anfrage zuzuordnen und die korrekte Zustellung der Pakete sicherzustellen. Diese ID kann beim Wechsel zwischen verschiedenen Netzwerken bestehen bleiben. So kann beispielsweise ein Download ohne Unterbrechung fortgesetzt werden, wenn Sie von WLAN zu einem Mobilfunknetz wechseln. HTTP/2 verwendet dagegen IP-Adressen als Kennungen, weshalb Netzwerkwechsel problematisch sein können.

Unzuverlässige Übertragung

HTTP/3 unterstützt die unzuverlässige Datenübertragung über Datagramme.

Die WebTransport API bietet direkten Zugriff auf die bidirektionale Kommunikation über HTTP/3. Sie nutzt die genannten Vorteile und unterstützt sowohl zuverlässige als auch unzuverlässige Datenübertragung.

Verbindungsaufbau

Um eine Verbindung zu einem HTTP/3-Server herzustellen, übergeben Sie dessen URL an den WebTransport()-Konstruktor. Beachten Sie, dass das Schema HTTPS sein und die Portnummer ausdrücklich angegeben werden muss. Sobald das WebTransport.ready-Promise erfüllt ist, können Sie die Verbindung verwenden.

js
const url = "https://example.com:4999/wt";

async function initTransport(url) {
  // Initialize transport connection
  const transport = new WebTransport(url);

  // The connection can be used once ready fulfills
  await transport.ready;

  // …
}

Serverimplementierung

Eine WebTransport-Verbindung erfordert einen Server, der WebTransport unterstützt. Um eine Sitzung aufzubauen, sendet der Client eine erweiterte CONNECT-Anfrage mit einem :protocol-Pseudo-Header, der WebTransport angibt. Bei Browser-Clients enthält die Anfrage außerdem einen Origin-Header, den der Server prüfen muss, bevor er die Sitzung akzeptiert. (Dies wird vom WebTransport()-Konstruktor automatisch gehandhabt.) Der Server akzeptiert die Sitzung mit einer erfolgreichen Antwort (2xx). Anschließend können Client und Server über mehrere bidirektionale Streams, unidirektionale Streams und Datagramme Daten austauschen, die dieser Sitzung zugeordnet sind.

Die WebTransport-over-HTTP/3-Spezifikation beschreibt das Protokoll und die Anforderungen an den Server ausführlicher.

Für die serverseitigen Protokolldetails sollten Sie eine WebTransport-Bibliothek verwenden. Zum Beispiel:

Zu allen Client-Beispielen stellen wir minimale Serverbeispiele mit dem Node.js-Paket @fails-components/webtransport bereit. Code, der mit anderen Bibliotheken oder Sprachen geschrieben wurde, kann erheblich anders aussehen.

Hinweis: Serverseitige JavaScript-Beispiele sind mit // -- server.js -- gekennzeichnet. JavaScript-Beispiele ohne diesen Kommentar sind clientseitiger Code.

Hier ist ein Beispielserver für das Beispiel zum Verbindungsaufbau:

js
// -- server.js --
import { randomBytes } from "node:crypto";
import { readFileSync } from "node:fs";
import { Http3Server } from "@fails-components/webtransport";

const allowedOrigin = "https://example.com";
const server = new Http3Server({
  host: "0.0.0.0",
  port: 4999,
  secret: randomBytes(32).toString("hex"),
  cert: readFileSync("certificate.pem", "utf8"),
  privKey: readFileSync("private-key.pem", "utf8"),
});

async function acceptRequest({ header }) {
  const path = header[":path"];
  if (path !== "/wt") {
    return { status: 404, path };
  }
  if (header.origin !== allowedOrigin) {
    return { status: 403, path };
  }
  return { status: 200, path };
}

server.setRequestCallback(acceptRequest);
const sessions = server.sessionStream("/wt");
server.startServer();
await server.ready;

async function handleSession(session) {
  // Add one of the server-side examples below here.
}

for await (const session of sessions) {
  session.closed.catch(console.error);
  session.ready.then(() => handleSession(session)).catch(console.error);
}

Wenn Sie den Code ausführen möchten, müssen Sie alle Vorkommen von example.com im Client- und Servercode durch die jeweiligen tatsächlichen Endpunkte ersetzen. Außerdem müssen Sie certificate.pem und private-key.pem bereitstellen. Diese Dateien enthalten ein vom Browser als vertrauenswürdig eingestuftes TLS-Zertifikat und den zugehörigen privaten Schlüssel.

Sofern nicht anders angegeben, ersetzt jedes der folgenden serverseitigen Beispiele den Inhalt von handleSession(). Das session-Objekt repräsentiert eine akzeptierte Client-Sitzung.

Verbindung schließen

Sie können auf das Schließen der Verbindung reagieren, indem Sie warten, bis das WebTransport.closed-Promise erfüllt ist. Fehler, die von WebTransport-Operationen zurückgegeben werden, sind vom Typ WebTransportError und enthalten zusätzliche Daten über die Angaben einer standardmäßigen DOMException hinaus.

js
async function closeTransport(transport) {
  // Respond to connection closing
  try {
    await transport.closed;
    console.log(`The HTTP/3 connection to ${url} closed gracefully.`);
  } catch (error) {
    console.error(`The HTTP/3 connection to ${url} closed due to ${error}.`);
  }
}

Rufen Sie in @fails-components/webtransport session.close() auf, um die Sitzung zu schließen:

js
// -- server.js --
session.close({ closeCode: 0, reason: "Work complete" });
await session.closed;

Der Server kann auch signalisieren, dass er die Verbindung vor dem Schließen auslaufen lassen möchte, etwa weil die zugrunde liegende Übertragung verwaltet werden muss. In @fails-components/webtransport geschieht dies beispielsweise mit session.notifySessionDraining(). In diesem Fall sollte der Client beginnen, Streams zu schließen, und eine neue Sitzung erstellen, falls er seine Arbeit fortsetzen muss. Sie können dies mit dem WebTransport.draining-Promise erkennen. Es wird erfüllt, sobald der Server signalisiert, dass die Sitzung in den Auslaufzustand übergeht:

js
async function watchForDraining(transport) {
  // Fulfills when the server signals that the session is draining
  await transport.draining;

  console.log("The session is draining: avoid opening new streams.");
}

Ein Anwendungsprotokoll aushandeln

Ein WebTransport-Server kann mehrere Anwendungen unterstützen, die jeweils ein eigenes Kommunikationsprotokoll verwenden. Dazu kann der Client über die Option protocols des WebTransport()-Konstruktors eine Liste möglicher Protokollnamen in der Reihenfolge seiner Präferenz anbieten. Der Server kann beim Verbindungsaufbau eines davon auswählen.

Sobald das WebTransport.ready-Promise erfüllt ist, ist das ausgehandelte Protokoll, sofern vorhanden, über die Eigenschaft WebTransport.protocol verfügbar. Der Wert ist eine leere Zeichenfolge, wenn protocols nicht verwendet wurde oder der Server keines der angebotenen Protokolle ausgewählt hat. Ein Server, der keines der angebotenen Protokolle unterstützt, kann die Verbindung stattdessen vollständig ablehnen, wodurch ready zurückgewiesen wird.

js
const url = "https://example.com:4999/wt";

async function initTransport(url) {
  const transport = new WebTransport(url, {
    protocols: ["chat", "file-transfer"],
  });

  try {
    await transport.ready;
    console.log(transport.protocol); // e.g. "chat", or "" if none was selected
    return transport;
  } catch (error) {
    console.error(`Connection failed: ${error}`);
  }
}

Beim Parsen der Header behandelt die Bibliothek @fails-components/webtransport header["wt-available-protocols"] als Sonderfall und wandelt den Wert in ein Array um. Sie können beispielsweise server.setRequestCallback(acceptRequest) durch Folgendes ersetzen, um fehlerhafte Werte zurückzuweisen und das erste vom Server unterstützte Protokoll auszuwählen:

js
// -- server.js --
const supportedProtocols = new Set(["chat", "file-transfer"]);

server.setRequestCallback(async (request) => {
  const response = await acceptRequest(request);
  if (response.status !== 200) {
    return response;
  }

  const offeredProtocols = request.header["wt-available-protocols"] ?? [];
  if (!Array.isArray(offeredProtocols)) {
    return { ...response, status: 400 };
  }
  const selectedProtocol = offeredProtocols.find((protocol) =>
    supportedProtocols.has(protocol),
  );
  return { ...response, selectedProtocol };
});

Unzuverlässige Übertragung über Datagramme

„Unzuverlässig“ bedeutet, dass weder die Übertragung der Daten noch ihr Eintreffen in einer bestimmten Reihenfolge garantiert ist. In manchen Situationen ist das unproblematisch und ermöglicht eine sehr schnelle Zustellung. Beispielsweise können Sie regelmäßig Aktualisierungen eines Spielzustands übertragen, bei denen jede Nachricht die zuletzt eingetroffene ersetzt und die Reihenfolge keine Rolle spielt.

Die unzuverlässige Datenübertragung erfolgt über die Eigenschaft WebTransport.datagrams. Sie gibt ein WebTransportDatagramDuplexStream-Objekt zurück, das alles enthält, was Sie zum Senden von Datagrammen an den Server und zum Empfangen von Datagrammen benötigen.

Die Eigenschaft WebTransportDatagramDuplexStream.writable gibt ein WritableStream-Objekt zurück. Mithilfe eines Writers können Sie Daten hineinschreiben, die an den Server übertragen werden:

js
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);

In @fails-components/webtransport lesen Sie diese Datagramme aus session.datagrams.readable:

js
// -- server.js --
for await (const data of session.datagrams.readable) {
  console.log(data); // A Uint8Array sent by the client.
}

Die Eigenschaft WebTransportDatagramDuplexStream.readable gibt ein ReadableStream-Objekt zurück, mit dem Sie Daten vom Server empfangen können:

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

Um in @fails-components/webtransport Datagramme zu senden, die dieser Clientcode lesen kann, beziehen Sie einen Writer:

js
// -- server.js --
const writer = session.datagrams.createWritable().getWriter();
try {
  await writer.write(new Uint8Array([65, 66, 67]));
  await writer.write(new Uint8Array([68, 69, 70]));
} finally {
  writer.releaseLock();
}

Zuverlässige Übertragung über Streams

„Zuverlässig“ bedeutet, dass die Übertragung und die Reihenfolge der Daten garantiert sind. Dies führt zu einer langsameren Zustellung, die allerdings immer noch schneller als bei WebSockets ist. Eine zuverlässige Übertragung ist erforderlich, wenn Zuverlässigkeit und Reihenfolge wichtig sind, beispielsweise bei Chat-Anwendungen.

Bei der zuverlässigen Übertragung über Streams können Sie außerdem die relative Priorität verschiedener Streams auf derselben Verbindung festlegen.

Unidirektionale Übertragung

Um von einem User Agent aus einen unidirektionalen Stream zu öffnen, verwenden Sie die Methode WebTransport.createUnidirectionalStream(). Sie erhalten damit eine Referenz auf einen WritableStream. Von diesem können Sie einen Writer beziehen, um Daten in den Stream zu schreiben und an den Server zu senden.

js
async function writeData() {
  const stream = await transport.createUnidirectionalStream();
  const writer = stream.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}`);
  }
}

Beachten Sie auch die Verwendung der Methode WritableStreamDefaultWriter.close(), mit der der Stream geschlossen wird, sobald alle Daten gesendet wurden.

In @fails-components/webtransport ist jedes Element in session.incomingUnidirectionalStreams ein lesbarer Stream mit Daten vom Client. Starten Sie für jeden Stream einen eigenen Reader, damit ein Stream, der auf Daten wartet, den Server nicht daran hindert, einen weiteren anzunehmen:

js
// -- server.js --
async function receiveStream(stream) {
  for await (const data of stream) {
    console.log(data); // A Uint8Array sent by the client.
  }
}

for await (const stream of session.incomingUnidirectionalStreams) {
  receiveStream(stream).catch(console.error);
}

Wenn der Server einen unidirektionalen Stream öffnet, um Daten an den Client zu übertragen, kann der Client über die Eigenschaft WebTransport.incomingUnidirectionalStreams darauf zugreifen. Sie gibt einen ReadableStream aus WebTransportReceiveStream-Objekten zurück. Mit diesen können vom Server gesendete Uint8Array-Instanzen gelesen werden.

Erstellen Sie in diesem Fall zunächst eine Funktion zum Lesen eines WebTransportReceiveStream. Diese Objekte erben von der Klasse ReadableStream und können daher auf dieselbe Weise verwendet werden:

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

Greifen Sie anschließend auf WebTransport.incomingUnidirectionalStreams zu und beziehen Sie einen Reader für den zurückgegebenen ReadableStream. Verwenden Sie den Reader dann, um die Daten vom Server zu lesen. Jeder Datenblock ist ein WebTransportReceiveStream, den wir mit der zuvor eingerichteten Funktion readData() lesen:

js
async function receiveUnidirectional() {
  const uds = transport.incomingUnidirectionalStreams;
  const reader = uds.getReader();
  while (true) {
    const { done, value } = await reader.read();
    if (done) {
      break;
    }
    // value is an instance of WebTransportReceiveStream
    await readData(value);
  }
}

Um in @fails-components/webtransport einen Stream für die clientseitigen Funktionen receiveUnidirectional() und readData() bereitzustellen, erstellen Sie einen unidirektionalen Stream und schreiben Daten hinein:

js
// -- server.js --
const stream = await session.createUnidirectionalStream();
const writer = stream.getWriter();
await writer.write(new Uint8Array([65, 66, 67]));
await writer.write(new Uint8Array([68, 69, 70]));
await writer.close();

Bidirektionale Übertragung

Um von einem User Agent aus einen bidirektionalen Stream zu öffnen, verwenden Sie die Methode WebTransport.createBidirectionalStream(). Sie erhalten damit eine Referenz auf einen WebTransportBidirectionalStream. Dieser enthält die Eigenschaften readable und writable, die Referenzen auf WebTransportReceiveStream- und WebTransportSendStream-Instanzen zurückgeben. Mit ihnen können Sie Daten vom Server lesen und Daten an ihn schreiben.

Hinweis: WebTransportBidirectionalStream ähnelt WebTransportDatagramDuplexStream. Bei letzterem sind die Eigenschaften readable und writable jedoch ein ReadableStream beziehungsweise ein WritableStream.

js
async function setUpBidirectional() {
  const stream = await transport.createBidirectionalStream();
  // stream is a WebTransportBidirectionalStream
  // stream.readable is a WebTransportReceiveStream
  const readable = stream.readable;
  // stream.writable is a WebTransportSendStream
  const writable = stream.writable;

  // …
  return stream;
}

Aus dem WebTransportReceiveStream können Sie anschließend wie folgt lesen:

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

In den WebTransportSendStream können Sie so schreiben:

js
async function writeData(writable) {
  const writer = writable.getWriter();
  const data1 = new Uint8Array([65, 66, 67]);
  const data2 = new Uint8Array([68, 69, 70]);
  await writer.write(data1);
  await writer.write(data2);
  await writer.close();
}

Führen Sie die Clientfunktionen parallel aus, damit das Lesen während des Schreibens fortgesetzt werden kann:

js
const stream = await setUpBidirectional();
await Promise.all([readData(stream.readable), writeData(stream.writable)]);

In @fails-components/webtransport nehmen Sie die vom Client erstellten Streams aus session.incomingBidirectionalStreams an. Jeder hat eine readable-Seite für Daten vom Client und eine writable-Seite für Daten an den Client:

js
// -- server.js --
for await (const stream of session.incomingBidirectionalStreams) {
  // Echo received bytes back to the client. Each stream is handled separately.
  stream.readable.pipeTo(stream.writable).catch(console.error);
}

Dieser Handler arbeitet mit beiden Funktionen zusammen: pipeTo() liest die von writeData() gesendeten Bytes und schreibt sie für readData() zurück.

Wenn der Server einen bidirektionalen Stream öffnet, um Daten an den Client zu senden und von ihm zu empfangen, kann der Client über die Eigenschaft WebTransport.incomingBidirectionalStreams darauf zugreifen. Sie gibt einen ReadableStream aus WebTransportBidirectionalStream-Objekten zurück. Jedes dieser Objekte kann wie oben gezeigt zum Lesen und Schreiben von Uint8Array-Instanzen verwendet werden. Wie beim unidirektionalen Beispiel benötigen Sie jedoch zunächst eine Funktion, um den bidirektionalen Stream selbst zu lesen:

js
async function receiveBidirectional() {
  const bds = transport.incomingBidirectionalStreams;
  const reader = bds.getReader();
  while (true) {
    const { done, value } = await reader.read();
    if (done) {
      break;
    }
    // value is an instance of WebTransportBidirectionalStream
    await readData(value.readable);
    await writeData(value.writable);
  }
}

Als Gegenstück zu receiveBidirectional() erstellt der Server einen Stream, sendet Daten und schließt seine sendende Seite, bevor er die Antwort des Clients liest. Dadurch kann der Aufruf von readData() auf dem Client abgeschlossen werden, sodass der Client writeData() aufrufen kann:

js
// -- server.js --
const stream = await session.createBidirectionalStream();
const writer = stream.writable.getWriter();
await writer.write(new Uint8Array([65, 66, 67]));
await writer.close();

for await (const data of stream.readable) {
  console.log(data); // The client's reply.
}

Schnittstellen

WebTransport

Bietet Funktionen, mit denen ein User Agent eine Verbindung zu einem HTTP/3-Server herstellen, eine zuverlässige oder unzuverlässige Übertragung in eine oder beide Richtungen einleiten und die Verbindung schließen kann, sobald sie nicht mehr benötigt wird.

WebTransportBidirectionalStream

Repräsentiert einen von einem Server oder Client erstellten bidirektionalen Stream für die zuverlässige Übertragung. Bietet Zugriff auf einen ReadableStream zum Lesen eingehender Daten und einen WritableStream zum Schreiben ausgehender Daten.

WebTransportDatagramDuplexStream

Repräsentiert einen Duplex-Stream für die unzuverlässige Übertragung von Datagrammen zwischen Client und Server. Bietet Zugriff auf einen ReadableStream zum Lesen eingehender Datagramme, einen WritableStream zum Schreiben ausgehender Datagramme sowie verschiedene Einstellungen und Statistiken zum Stream.

WebTransportError

Repräsentiert einen Fehler im Zusammenhang mit der WebTransport API, der durch Serverfehler, Probleme mit der Netzwerkverbindung oder vom Client ausgelöste Abbruchvorgänge entstehen kann, beispielsweise durch einen Aufruf von WritableStream.abort().

WebTransportReceiveStream

Bietet Streaming-Funktionen für einen eingehenden unidirektionalen oder bidirektionalen WebTransport-Stream.

WebTransportSendStream

Bietet Streaming-Funktionen für einen ausgehenden unidirektionalen oder bidirektionalen WebTransport-Stream.

Beispiele

Vollständige Beispiele finden Sie unter:

Spezifikationen

Spezifikation
WebTransport
# web-transport

Browser-Kompatibilität

Siehe auch