Building Components
Build wasi:http/incoming-handler@0.2.0 components in any language that can run on mik or any WASI HTTP runtime.
Overview
Section titled “Overview”mik uses WASI HTTP 0.2.0. When building components, use matching WIT definitions.
| Language | SDK/Toolchain | Raw Size | Stripped |
|---|---|---|---|
| C/C++ | wasi-sdk + wit-bindgen | ~88 KB | ~25 KB |
| Rust | wit-bindgen / mik-sdk | ~100 KB | ~100 KB |
| JavaScript | jco (ComponentizeJS) | ~12 MB | ~12 MB |
| Python | componentize-py | ~39 MB | ~17 MB |
Tip: Use
mik strip component.wasmto remove debug info and names (auto-downloads wasm-tools if needed), or directly:wasm-tools strip --all component.wasm -o stripped.wasm
Prerequisites
Section titled “Prerequisites”# C/C++ (wasi-sdk 25+)# Download from https://github.com/WebAssembly/wasi-sdk/releasescargo install wit-bindgen-cli # For generating C bindings
# Rustrustup target add wasm32-wasip2cargo install cargo-component wasm-tools
# JavaScriptnpm install -g @bytecodealliance/jco @bytecodealliance/componentize-js
# Pythonpip install componentize-py# Or use uv: uv run --with componentize-py componentize-py ...Rust produces compact components. Two options available.
Option 1: mik-sdk (Recommended)
Section titled “Option 1: mik-sdk (Recommended)”mik new my-handlercd my-handler#[allow(warnings)]mod bindings;
use bindings::exports::mik::core::handler::{self, Guest, Response};use mik_sdk::prelude::*;
routes! { GET "/" | "" => hello,}
fn hello(_req: &Request) -> Response { ok!({ "message": "Hello from Rust!", "lang": "rust" })}mik build -rcOption 2: wit-bindgen (Direct)
Section titled “Option 2: wit-bindgen (Direct)”cargo new --lib my-component && cd my-componentcargo add wit-bindgen[lib]crate-type = ["cdylib"]cargo component build --releaseC produces the smallest components using wasi-sdk.
mkdir hello-c && cd hello-c
# Get WASI HTTP 0.2.0 WITgit clone --depth 1 --branch v0.2.0 https://github.com/WebAssembly/wasi-http.git
# Generate C bindingswit-bindgen c wasi-http/wit --out-dir gen --world proxy#include "gen/proxy.h"#include <string.h>
static const char* RESPONSE_BODY = "{\"message\":\"Hello from C!\",\"lang\":\"c\"}";
void exports_wasi_http_incoming_handler_handle( exports_wasi_http_incoming_handler_own_incoming_request_t request, exports_wasi_http_incoming_handler_own_response_outparam_t response_out) { wasi_http_types_incoming_request_drop_own(request);
// Create response wasi_http_types_own_fields_t headers = wasi_http_types_constructor_fields(); wasi_http_types_own_outgoing_response_t response = wasi_http_types_constructor_outgoing_response(headers);
wasi_http_types_borrow_outgoing_response_t resp_borrow = (wasi_http_types_borrow_outgoing_response_t){ response.__handle }; wasi_http_types_method_outgoing_response_set_status_code(resp_borrow, 200);
// Get body and stream wasi_http_types_own_outgoing_body_t body; wasi_http_types_method_outgoing_response_body(resp_borrow, &body);
wasi_io_streams_own_output_stream_t stream; wasi_http_types_borrow_outgoing_body_t body_borrow = (wasi_http_types_borrow_outgoing_body_t){ body.__handle }; wasi_http_types_method_outgoing_body_write(body_borrow, &stream);
// Set response before writing wasi_http_types_result_own_outgoing_response_error_code_t result = { .is_err = false, .val.ok = response }; wasi_http_types_static_response_outparam_set(response_out, &result);
// Write body proxy_list_u8_t body_bytes = { (uint8_t*)RESPONSE_BODY, strlen(RESPONSE_BODY) }; wasi_io_streams_stream_error_t err; wasi_io_streams_borrow_output_stream_t stream_borrow = (wasi_io_streams_borrow_output_stream_t){ stream.__handle }; wasi_io_streams_method_output_stream_blocking_write_and_flush(stream_borrow, &body_bytes, &err);
wasi_io_streams_output_stream_drop_own(stream); wasi_http_types_error_code_t body_err; wasi_http_types_static_outgoing_body_finish(body, NULL, &body_err);}# Set WASI_SDK to your installation pathWASI_SDK=/path/to/wasi-sdk
$WASI_SDK/bin/clang --target=wasm32-wasip2 -O2 \ -c gen/proxy.c -o proxy.o$WASI_SDK/bin/clang --target=wasm32-wasip2 -O2 \ -c hello.c -o hello.o$WASI_SDK/bin/clang --target=wasm32-wasip2 -O2 \ proxy.o hello.o gen/proxy_component_type.o -o hello-c.wasmJavaScript
Section titled “JavaScript”Uses jco (ComponentizeJS).
mkdir hello-js && cd hello-jsnpm install @bytecodealliance/jco @bytecodealliance/componentize-js
# Get WASI HTTP 0.2.0 WITgit clone --depth 1 --branch v0.2.0 https://github.com/WebAssembly/wasi-http.gitcp -r wasi-http/wit .import { ResponseOutparam, OutgoingBody, OutgoingResponse, Fields,} from "wasi:http/types@0.2.0";
export const incomingHandler = { handle(_incomingRequest, responseOutparam) { const response = new OutgoingResponse(new Fields()); response.setStatusCode(200);
let body = response.body(); let stream = body.write(); stream.blockingWriteAndFlush( new Uint8Array( new TextEncoder().encode( JSON.stringify({ message: "Hello from JavaScript!", lang: "javascript", }) ) ) ); stream[Symbol.dispose](); OutgoingBody.finish(body, undefined); ResponseOutparam.set(responseOutparam, { tag: "ok", val: response }); },};npx jco componentize app.js --wit wit --world-name proxy -o hello-js.wasmPython
Section titled “Python”Uses componentize-py.
mkdir hello-python && cd hello-python
# Get WASI HTTP 0.2.0 WITgit clone --depth 1 --branch v0.2.0 https://github.com/WebAssembly/wasi-http.gitcp -r wasi-http/wit .Generate Bindings
Section titled “Generate Bindings”# Using pipcomponentize-py -d wit -w proxy bindings .
# Or using uv (recommended)uv run --with componentize-py componentize-py -d wit -w proxy bindings .from wit_world import exportsfrom componentize_py_types import Okfrom wit_world.imports.types import ( IncomingRequest, ResponseOutparam, OutgoingResponse, Fields, OutgoingBody)
class IncomingHandler(exports.IncomingHandler): def handle(self, _: IncomingRequest, response_out: ResponseOutparam): response = OutgoingResponse(Fields.from_list([ ("content-type", b"application/json"), ])) response.set_status_code(200) body = response.body()
# IMPORTANT: Set response BEFORE writing body ResponseOutparam.set(response_out, Ok(response))
body.write().blocking_write_and_flush( b'{"message":"Hello from Python!","lang":"python"}' ) OutgoingBody.finish(body, None)# Using pipcomponentize-py -d wit -w proxy componentize app -o hello-python.wasm
# Or using uv (recommended)uv run --with componentize-py componentize-py -d wit -w proxy componentize app -o hello-python.wasmVerify Component
Section titled “Verify Component”# Check exportswasm-tools component wit my-component.wasm | grep "export wasi:http"# export wasi:http/incoming-handler@0.2.0
# Run with mikmik run my-component.wasm
# Testcurl http://localhost:3000/run/my-component/Troubleshooting
Section titled “Troubleshooting”| Issue | Solution |
|---|---|
module requires import interface wasi:http/types | Use wasi-http v0.2.0 WIT (not latest) |
ResponseOutparam.set is not a function (JS) | Use { tag: 'ok', val: response } |
missing Ok wrapper (Python) | Import Ok from componentize_py_types |
| Empty response | Call ResponseOutparam.set() BEFORE writing body |
Version Compatibility
Section titled “Version Compatibility”| mik | wasmtime | wasi-http WIT |
|---|---|---|
| 0.0.1 | 40.0.0 | 0.2.0 |