Menjelajahi networking untuk WebAssembly: outbound request via wasi:http, melayani HTTP lewat runtime, interop fetch di Node.js, serta streaming async WASI 0.3 untuk real-time dan WebTransport eksperimental

Setelah di episode 16 kalian memahami model keamanan Wasm — pada episode ini kita membuka jalur komunikasi keluar: networking. Hingga beberapa tahun lalu, "Wasm berjaringan" adalah oxymoron — modul dikurung dalam sandbox tanpa socket. Sekarang, dengan wasi:http, modul Wasm bisa mengirim request HTTP, melayani response, dan berkomunikasi real-time.
Mengapa networking penting? Karena tanpa jaringan, Wasm hanya bisa memproses data yang diberikan lokal. Dengan jaringan, ia menjadi unit komputasi mandiri — service, API proxy, aggregator, dan gateway bisa dibangun sepenuhnya dalam modul portabel yang sama di semua runtime.
wasi:http adalah interface WASI untuk client dan server HTTP. Untuk memanggil API eksternal dari modul Rust:
use wasi::http::outgoing_handler::{handle, OutgoingRequest};
use wasi::http::types::Method;
#[tokio::main]
async fn main() {
let req = OutgoingRequest::new(Method::Get, "https://api.example.com/data")
.header("accept", "application/json")
.build();
let response = handle(&req).await.unwrap();
let body = response.body().read().await.unwrap();
println!("status: {}", response.status());
println!("body: {}", String::from_utf8_lossy(&body));
}Build dan jalankan:
rustup target add wasm32-wasip2
cargo build --target wasm32-wasip2 --release
wasmtime run target/wasm32-wasip2/release/client.wasmPerhatikan: modul memanggil wasi:http, runtime yang menyediakan transport TCP/TLS. Modul tidak pernah menyentuh socket — ia hanya meminta "kirim request ini, beri response ini". Keamanan capability (episode 16) tetap berlaku.
Wasm juga bisa menjadi server HTTP. Modul mengekspor handler, runtime menyediakan server:
use wasi::http::incoming_handler::{IncomingRequest, ResponseOutparam};
use wasi::http::types::{Response, StatusCode};
fn handle(request: IncomingRequest, response_out: ResponseOutparam) {
let response = Response::new(StatusCode::OK)
.body("Halo dari server WebAssembly!".to_string())
.build();
ResponseOutparam::set(response_out, Ok(response));
}
wasi::http::incoming_handler::export!(handle);Untuk menjalankan, deploy ke platform yang menyediakan HTTP server (Spin, Fastly Compute, atau wasi-http world di Wasmtime):
spin upRequest GET http://localhost:3000/ akan dijawab oleh handler Wasm — sebuah server web yang bytecode-nya sama persis bisa dipindah ke platform lain tanpa perubahan.
Node.js sudah bisa memuat modul Wasm/WASI secara native sejak versi 20+. Interop dengan fetch bekerja mulus:
import { WASI } from "node:wasi"
import { readFile } from "node:fs/promises"
const wasi = new WASI({
version: "preview2",
args: [],
env: {},
})
const wasm = await readFile(new URL("./server.wasm", import.meta.url))
const { instance } = await WebAssembly.instantiate(wasm, {
wasi_snapshot_preview1: wasi.wasiImport,
})
wasi.start(instance)Pola ini membuka integrasi: service Node.js bisa memanggil fungsi Wasm, dan sebaliknya modul Wasm bisa memakai fetch via interop JS — kombinasi terbaik dari kedua dunia.
Untuk komunikasi real-time, WASI 0.3 menyediakan stream native — stream<u8> untuk aliran data kontinu. Pola WebSocket di modul Wasm:
use wasi::streams::stream::Stream;
use wasi::websocket::websocket::{connect, Message};
async fn sinkron() {
let mut ws = connect("wss://echo.example.com").await.unwrap();
let mut out = ws.open_send().await.unwrap();
out.write(b"ping".to_vec()).await.unwrap();
let mut inp = ws.open_receive().await.unwrap();
while let Some(msg) = inp.read().await.unwrap() {
if let Message::Text(t) = msg {
println!("terima: {t}");
}
}
}Dengan model async WASI 0.3, satu thread bisa melayani ribuan koneksi WebSocket — setiap koneksi adalah stream yang tidak memblokir thread (konsep dari episode 10).
Tip
Untuk pola real-time, jangan pikirkan "koneksi per thread" seperti server klasik. WASI 0.3 async memakai model event-driven: banyak stream, sedikit thread. Ini sebabnya runtime Wasm bisa menghemat resource hingga orde besaran dibanding server blocking.
WebTransport adalah protokol transport modern (QUIC-based) yang sedang dieksplorasi di ekosistem Wasm untuk kasus yang butuh:
Statusnya masih eksperimental — tidak semua runtime mendukungnya. Untuk produksi saat ini, kombinasi wasi:http + streaming async sudah menutupi sebagian besar kebutuhan. Pantau proposal WebTransport di roadmap WebAssembly untuk workload real-time kelas berat.
--listen, --allow-network).close) stream yang sudah selesai.Warning
Networking membuka permukaan serangan terbesar bagi modul yang tidak dipercaya: validasi setiap response (size limit, status, konten), dan jangan pernah melewati data untrusted langsung ke parser internal tanpa guard — pola dari episode 14 dan 16.
Pada episode 17 ini, kalian telah memahami networking WebAssembly dari outbound HTTP hingga streaming real-time.
Inti yang harus dibawa pulang:
wasi:http menyediakan outbound request dan server HTTP dalam satu interface.fetch berjalan dua arah.Di episode 18 selanjutnya kita akan membahas persistence & state management — IndexedDB/localStorage di browser, Redis/object storage via host functions di server, pola stateless + external state (KV), dan snapshot/rehydrate memory Wasm. Sampai jumpa di episode 18!