Menggunakan WebTransport

WebTransport adalah API yang menawarkan pesan server klien berlatensi rendah dan dua arah. Pelajari lebih lanjut kasus penggunaannya, dan cara memberikan masukan untuk masa depan penerapan.

Latar belakang

Apa itu WebTransport?

WebTransport adalah API web yang menggunakan protokol HTTP/3 sebagai transportasi dua arah. Ini dimaksudkan untuk komunikasi dua arah antara klien web dan server HTTP/3. Platform ini mendukung pengiriman data secara tidak dapat diandalkan melalui API datagram, dan secara andal melalui API streaming-nya.

Datagram ideal untuk mengirim dan menerima data yang tidak memerlukan jaminan pengiriman yang kuat. Setiap paket data dibatasi ukurannya oleh unit transmisi maksimum (MTU) dari koneksi yang mendasarinya, serta mungkin berhasil atau tidak berhasil dikirim, dan jika ditransfer, data tersebut mungkin akan diterima dalam urutan arbitrer. Karakteristik ini membuat API datagram ideal untuk transmisi data dengan upaya terbaik dan berlatensi rendah. Anda dapat menganggap datagram sebagai pesan protokol datagram pengguna (UDP), tetapi dienkripsi dan dikontrol kemacetan.

Sebaliknya, API aliran data menyediakan transfer data yang dapat diandalkan dan diurutkan. Paket ini cocok untuk skenario saat Anda perlu mengirim atau menerima satu atau beberapa aliran data yang diurutkan. Menggunakan beberapa streaming WebTransport setara dengan membuat beberapa koneksi TCP, tetapi karena HTTP/3 menggunakan protokol QUIC yang lebih ringan di balik layar, streaming tersebut dapat dibuka dan ditutup tanpa banyak overhead.

Kasus penggunaan

Ini adalah daftar kecil kemungkinan cara developer menggunakan WebTransport.

  • Mengirim status game pada interval reguler dengan latensi minimal ke server melalui pesan kecil, tidak dapat diandalkan, dan tidak berurutan.
  • Menerima aliran media yang didorong dari server dengan latensi minimal, terlepas dari aliran data lainnya.
  • Menerima notifikasi yang dikirim dari server saat halaman web terbuka.

Kami ingin mendengar lebih lanjut rencana Anda terkait penggunaan WebTransport.

Dukungan browser

Dukungan Browser

  • Chrome: 97.
  • Edge: 97.
  • Firefox: 114.
  • Safari: tidak didukung.

Sumber

Seperti semua fitur yang tidak memiliki dukungan browser universal, coding secara defensif melalui deteksi fitur merupakan praktik terbaik.

Status saat ini

Langkah Status
1. Buat penjelasan Selesai
2. Membuat draf awal spesifikasi Selesai
3. Mengumpulkan masukan dan melakukan iterasi desain Selesai
4. Uji coba origin Selesai
5. Peluncuran Chromium 97

Hubungan WebTransport dengan teknologi lain

Apakah WebTransport sebagai pengganti WebSockets?

Mungkin. Ada kasus penggunaan ketika WebSockets atau WebTransport mungkin merupakan protokol komunikasi yang valid untuk digunakan.

Model komunikasi WebSockets didasarkan pada satu aliran pesan yang dapat diandalkan, dan teratur, yang cocok untuk beberapa jenis kebutuhan komunikasi. Jika Anda memerlukan karakteristik tersebut, Stream API WebTransport juga dapat menyediakannya. Sebagai perbandingan, API datagram WebTransport memberikan pengiriman latensi rendah, tanpa jaminan terkait keandalan atau pemesanan, sehingga API tersebut bukan pengganti langsung untuk WebSockets.

Dengan menggunakan WebTransport, melalui API datagram atau melalui beberapa instance Streams API secara bersamaan, Anda tidak perlu khawatir tentang pemblokiran head-of-line, yang dapat menjadi masalah dengan WebSockets. Selain itu, ada manfaat performa saat membuat koneksi baru, karena QUIC handshake yang mendasarinya lebih cepat daripada memulai TCP melalui TLS.

WebTransport adalah bagian dari spesifikasi draf baru, sehingga ekosistem WebSocket di sekitar library klien dan server saat ini jauh lebih tangguh. Jika Anda memerlukan sesuatu yang berfungsi "siap pakai" dengan penyiapan server umum, dan dengan dukungan klien web yang luas, WebSockets adalah pilihan yang lebih baik saat ini.

Apakah WebTransport sama dengan UDP Socket API?

Tidak. WebTransport bukan UDP Socket API. Sementara WebTransport menggunakan HTTP/3, yang selanjutnya menggunakan UDP "di balik layar," WebTransport memiliki persyaratan seputar enkripsi dan kontrol kemacetan yang membuatnya lebih dari sekadar UDP Socket API dasar.

Apakah WebTransport adalah alternatif saluran data WebRTC?

Ya, untuk koneksi klien-server. WebTransport memiliki banyak properti yang sama dengan saluran data WebRTC, meskipun protokol yang mendasarinya berbeda.

Umumnya, menjalankan server yang kompatibel dengan HTTP/3 memerlukan lebih sedikit penyiapan dan konfigurasi daripada mengelola server WebRTC, yang melibatkan pemahaman tentang beberapa protokol (ICE, DTLS, dan SCTP) untuk mendapatkan transport yang berfungsi. WebRTC memerlukan lebih banyak bagian bergerak yang dapat menyebabkan negosiasi klien/server gagal.

WebTransport API dirancang dengan mempertimbangkan kasus penggunaan developer web, dan akan lebih terasa seperti menulis kode platform web modern daripada menggunakan antarmuka saluran data WebRTC. Tidak seperti WebRTC, WebTransport didukung di dalam Web Workers, yang memungkinkan Anda melakukan komunikasi klien-server secara terpisah dari halaman HTML tertentu. Karena WebTransport mengekspos antarmuka yang sesuai dengan Streams, layanan ini mendukung pengoptimalan seputar backpressure.

Namun, jika Anda sudah memiliki penyiapan klien/server WebRTC yang berfungsi sesuai keinginan, maka beralih ke WebTransport mungkin tidak menawarkan banyak keuntungan.

Cobalah

Cara terbaik untuk bereksperimen dengan WebTransport adalah dengan memulai server HTTP/3 yang kompatibel. Kemudian, Anda dapat menggunakan halaman ini dengan klien JavaScript dasar untuk mencoba komunikasi klien/server.

Selain itu, server echo yang dikelola komunitas tersedia di webtransport.day.

Menggunakan API

WebTransport didesain di atas primitif platform web modern, seperti Streams API. Fitur ini sangat bergantung pada promise, dan berfungsi baik dengan async dan await.

Penerapan WebTransport saat ini di Chromium mendukung tiga jenis traffic yang berbeda: datagram, serta aliran searah dan dua arah.

Menghubungkan ke server

Anda dapat terhubung ke server HTTP/3 dengan membuat instance WebTransport. Skema URL harus https. Anda harus menentukan nomor port secara eksplisit.

Anda harus menggunakan promise ready untuk menunggu koneksi dibuat. Promise ini tidak akan terpenuhi hingga penyiapan selesai, dan akan ditolak jika koneksi gagal pada tahap QUIC/TLS.

Promise closed terpenuhi jika koneksi ditutup secara normal, dan menolak jika penutupan tidak terduga.

Jika server menolak koneksi karena error indikasi klien (misalnya, jalur URL tidak valid), hal tersebut menyebabkan closed ditolak, sementara ready tetap belum terselesaikan.

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;

Datagram API

Setelah memiliki instance WebTransport yang terhubung ke server, Anda dapat menggunakannya untuk mengirim dan menerima bit data diskret, yang dikenal sebagai datagram.

Pengambil writeable menampilkan WritableStream, yang dapat digunakan klien web untuk mengirim data ke server. Pengambil readable menampilkan ReadableStream, sehingga Anda dapat memproses data dari server. Kedua aliran data secara inheren tidak dapat diandalkan, jadi ada kemungkinan data yang Anda tulis tidak akan diterima oleh server, dan sebaliknya.

Kedua jenis aliran data menggunakan instance Uint8Array untuk transfer data.

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

Streams API

Setelah terhubung ke server, Anda juga dapat menggunakan WebTransport untuk mengirim dan menerima data melalui Streams API-nya.

Setiap bagian dari semua stream adalah Uint8Array. Tidak seperti Datagram API, streaming ini dapat diandalkan. Namun, setiap stream bersifat independen, sehingga urutan data antar-stream tidak dijamin.

WebTransportSendStream

WebTransportSendStream dibuat oleh klien web menggunakan metode createUnidirectionalStream() dari instance WebTransport, yang menampilkan promise untuk WebTransportSendStream.

Gunakan metode close() dari WritableStreamDefaultWriter untuk menutup koneksi HTTP/3 terkait. Browser mencoba mengirim semua data yang tertunda sebelum benar-benar menutup koneksi terkait.

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

Demikian pula, gunakan metode abort() dari WritableStreamDefaultWriter untuk mengirim RESET\_STREAM ke server. Saat menggunakan abort(), browser dapat menghapus data tertunda yang belum dikirim.

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

WebTransportReceiveStream dimulai oleh server. Mendapatkan WebTransportReceiveStream adalah proses dua langkah untuk klien web. Pertama, metode ini memanggil atribut incomingUnidirectionalStreams dari instance WebTransport, yang menampilkan ReadableStream. Setiap bagian dari ReadableStream tersebut, pada gilirannya, adalah WebTransportReceiveStream yang dapat digunakan untuk membaca instance Uint8Array yang dikirim oleh server.

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

Anda dapat mendeteksi penutupan streaming menggunakan promise closed dari ReadableStreamDefaultReader. Jika koneksi HTTP/3 yang mendasarinya ditutup dengan bit FIN, promise closed akan terpenuhi setelah semua data dibaca. Saat koneksi HTTP/3 ditutup secara tiba-tiba (misalnya, dengan RESET\_STREAM), promise closed akan ditolak.

// 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

WebTransportBidirectionalStream dapat dibuat oleh server atau klien.

Klien web dapat membuatnya menggunakan metode createBidirectionalStream() dari instance WebTransport, yang menampilkan promise untuk WebTransportBidirectionalStream.

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

Anda dapat memproses WebTransportBidirectionalStream yang dibuat oleh server dengan atribut incomingBidirectionalStreams dari instance WebTransport, yang menampilkan ReadableStream. Setiap bagian dari ReadableStream tersebut, pada gilirannya, adalah 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
}

WebTransportBidirectionalStream hanyalah kombinasi dari WebTransportSendStream dan WebTransportReceiveStream. Contoh dari dua bagian sebelumnya menjelaskan cara menggunakan masing-masing bagian tersebut.

Contoh lainnya

Spesifikasi draf WebTransport mencakup sejumlah contoh inline tambahan, beserta dokumentasi lengkap untuk semua metode dan properti.

WebTransport di DevTools Chrome

Sayangnya, DevTools Chrome saat ini tidak mendukung WebTransport. Anda dapat "memberi bintang" masalah Chrome ini untuk diberi tahu tentang update pada antarmuka DevTools.

Polyfill

Polyfill (atau lebih tepatnya ponyfill yang menyediakan fungsi sebagai modul mandiri yang dapat Anda gunakan) disebut webtransport-ponyfill-websocket yang menerapkan beberapa fitur WebTransport yang tersedia. Bacalah batasan-batasan pada README project guna menentukan apakah solusi ini dapat cocok untuk kasus penggunaan Anda.

Pertimbangan privasi dan keamanan

Lihat bagian yang sesuai dalam draf spesifikasi untuk mendapatkan panduan yang kredibel.

Masukan

Tim Chrome ingin mengetahui pendapat dan pengalaman Anda saat menggunakan API ini.

Masukan tentang desain API

Apakah ada sesuatu pada API yang aneh atau tidak berfungsi seperti yang diharapkan? Atau apakah ada bagian yang hilang yang diperlukan untuk menerapkan ide Anda?

Laporkan masalah di repo GitHub Web Transport, atau tambahkan pendapat Anda ke masalah yang sudah ada.

Ada masalah dengan implementasinya?

Apakah Anda menemukan bug pada implementasi Chrome?

Laporkan bug di https://new.crbug.com. Sertakan sebanyak mungkin detail, beserta petunjuk sederhana untuk mereproduksi.

Anda berencana menggunakan API?

Dukungan publik Anda membantu Chrome memprioritaskan fitur, dan menunjukkan kepada vendor browser lainnya betapa pentingnya mendukung mereka.

Diskusi umum

Anda dapat menggunakan grup Google web-transport-dev untuk pertanyaan atau masalah umum yang tidak sesuai dengan salah satu kategori lainnya.

Ucapan terima kasih

Artikel ini berisi informasi dari WebTransport Explainer, spesifikasi draf, dan dokumen desain terkait. Terima kasih kepada masing-masing penulis yang telah memberikan dasar tersebut.

Banner besar di postingan ini adalah karya Robin Pierre di Unsplash.