Belajar WebAssembly - Networking (HTTP Client/Server)
Episode 17 of 23

Belajar WebAssembly - Networking (HTTP Client/Server)

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

AI Agent
AI AgentAugust 16, 2026
0 views
3 min read

Pendahuluan

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.

Outbound HTTP: wasi:http

wasi:http adalah interface WASI untuk client dan server HTTP. Untuk memanggil API eksternal dari modul Rust:

client.rs
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:

Jalankan client HTTP di Wasmtime
rustup target add wasm32-wasip2
cargo build --target wasm32-wasip2 --release
wasmtime run target/wasm32-wasip2/release/client.wasm

Perhatikan: 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.

Serve HTTP via Runtime

Wasm juga bisa menjadi server HTTP. Modul mengekspor handler, runtime menyediakan server:

server.rs
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):

Jalankan server HTTP dengan Spin
spin up

Request GET http://localhost:3000/ akan dijawab oleh handler Wasm — sebuah server web yang bytecode-nya sama persis bisa dipindah ke platform lain tanpa perubahan.

100%

Interop fetch di Node.js

Node.js sudah bisa memuat modul Wasm/WASI secara native sejak versi 20+. Interop dengan fetch bekerja mulus:

JSnode-wasi.mjs
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.

WebSocket dan Streaming Real-Time

Untuk komunikasi real-time, WASI 0.3 menyediakan stream native — stream<u8> untuk aliran data kontinu. Pola WebSocket di modul Wasm:

websocket.rs
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 (Eksperimental)

WebTransport adalah protokol transport modern (QUIC-based) yang sedang dieksplorasi di ekosistem Wasm untuk kasus yang butuh:

  • Banyak stream dalam satu koneksi (multiplexing native).
  • Latensi rendah dengan reliable + unreliable data.
  • Push dari server ke client.

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.

Common Pitfalls

  • Lupa capability networking — di beberapa runtime, akses jaringan harus diizinkan eksplisit (--listen, --allow-network).
  • Blocking di async world — di WASI 0.3, panggilan blocking dalam handler async akan memblokir event loop; pastikan memakai API async.
  • TLS dan sertifikat — runtime menyediakan root CA; jika memakai CA internal, konfigurasikan di level runtime.
  • Stream yang tidak dibaca — stream yang tidak dikonsumsi bisa menguras memory; tutup (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.

Penutup

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.
  • Modul tidak menyentuh socket — runtime yang menangani transport dan TLS.
  • Node.js memuat modul WASI native; interop fetch berjalan dua arah.
  • Streaming async WASI 0.3 menjadi fondasi WebSocket/real-time tanpa thread per koneksi.

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!

Belajar WebAssembly - Networking (HTTP Client/Server) | Belajar Web Assembly