WASI HTTP
WASI HTTP example
This WASI HTTP example uses the Rust sample-wasi-http-rust component. It implements a complete WASI HTTP server that handles GET, POST, and header inspection using the wasi:http/proxy world.
Source Code
The source code is available in the Propeller examples directory. The sample-wasi-http-rust example is a Git submodule from bytecodealliance/sample-wasi-http-rust.
Loading...
Build Wasm
Initialize the Git submodule and build the example:
cd propeller
git submodule update --init --remote
cd examples/sample-wasi-http-rustInstall the required Rust target and dependencies:
rustup target add wasm32-wasip2
cargo install wkg
wkg wit fetchBuild the example:
cargo build --target wasm32-wasip2Your output should look like this:
Compiling sample-wasi-http-rust v0.0.0 (/home/user/propeller/examples/sample-wasi-http-rust)
Finished `dev` profile [unoptimized + debuginfo] target(s) in 5.65sDocker Setup
The wasi-http example requires specific proplet configuration. Before running, configure your docker/.env file:
PROPLET_EXTERNAL_WASM_RUNTIME=""
PROPLET_HTTP_ENABLED=true
PROPLET_HTTP_PROXY_PORT=8081These settings are required because:
PROPLET_EXTERNAL_WASM_RUNTIME=""— Must be empty. When set towasmtime, the proplet spawnswasmtime run, which cannot serve awasi:http/proxycomponent. The internal WasmtimeRuntime (used when unset) handles HTTP proxy components natively.PROPLET_HTTP_ENABLED=true— Enables the HTTP proxy capability, which is disabled by default.PROPLET_HTTP_PROXY_PORT=8081— Sets the HTTP proxy port to match the exposed container port.
Then restart the proplet to apply the changes:
cd docker
docker compose up -d propletYou should see the following in the proplet startup logs, confirming the correct configuration:
Using Wasmtime runtime
http_enabled: true, http_proxy_port: 8081Create Task
Create a daemon task for the HTTP server:
curl -X POST "http://localhost:7070/tasks" \
-H "Content-Type: application/json" \
-d '{"name": "_start", "daemon": true}'Your output should look like this:
{
"id": "62fc5c37-da87-4d01-846d-713f885f3447",
"name": "_start",
"kind": "standard",
"state": 0,
"cli_args": null,
"daemon": true,
"encrypted": false,
"start_time": "0001-01-01T00:00:00Z",
"finish_time": "0001-01-01T00:00:00Z",
"created_at": "2026-03-03T10:55:48.013225031Z",
"updated_at": "0001-01-01T00:00:00Z",
"next_run": "0001-01-01T00:00:00Z",
"priority": 50
}Upload Wasm
Upload the compiled wasm file (replace task ID with yours):
curl -X PUT "http://localhost:7070/tasks/62fc5c37-da87-4d01-846d-713f885f3447/upload" \
-F "file=@$(pwd)/target/wasm32-wasip2/debug/sample_wasi_http_rust.wasm"Your output should look like this:
{
"id": "62fc5c37-da87-4d01-846d-713f885f3447",
"name": "_start",
"kind": "standard",
"state": 0,
"file": "...<redacted>...",
"cli_args": null,
"daemon": true,
"encrypted": false,
"start_time": "0001-01-01T00:00:00Z",
"finish_time": "0001-01-01T00:00:00Z",
"created_at": "2026-03-03T10:55:48.013225031Z",
"updated_at": "2026-03-03T10:56:07.314125682Z",
"next_run": "0001-01-01T00:00:00Z",
"priority": 50
}Start Task
Start the HTTP server task:
curl -X POST "http://localhost:7070/tasks/62fc5c37-da87-4d01-846d-713f885f3447/start"Your output should look like this:
{"started":true}Query Task Status
Query the task status:
curl -X GET "http://localhost:7070/tasks/62fc5c37-da87-4d01-846d-713f885f3447"Your output should look like this:
{
"id": "62fc5c37-da87-4d01-846d-713f885f3447",
"name": "_start",
"kind": "standard",
"state": 2,
"cli_args": null,
"daemon": true,
"encrypted": false,
"proplet_id": "d66600de-8827-4096-bc6f-ce1b5a0b2482",
"results": "",
"start_time": "2026-03-03T10:56:15.959761675Z",
"finish_time": "0001-01-01T00:00:00Z",
"created_at": "2026-03-03T10:55:48.013225031Z",
"updated_at": "2026-03-03T10:56:15.959761909Z",
"next_run": "0001-01-01T00:00:00Z",
"priority": 50
}The "state": 2 indicates the task is Running. For daemon tasks like this HTTP server, state 2 is the expected state — the task keeps running indefinitely to serve HTTP requests. Task states are: 0 (Pending), 1 (Dispatched), 2 (Running), 3 (Completed), 4 (Failed).
Test Endpoints
Test the HTTP endpoints on the proplet's HTTP port (8081):
curl http://localhost:8081/Your output should look like this:
Hello, wasi:http/proxy world!Test the wait endpoint:
curl http://localhost:8081/waitYour output should look like this:
slept for 1000 millisTest the echo endpoint:
curl http://localhost:8081/echo -d 'hello from propeller'Your output should look like this:
hello from propellerTest the headers endpoint:
curl -v http://localhost:8081/echo-headers -H 'X-Test: 123' -H 'X-Foo: bar'The request headers are echoed back as response headers:
< HTTP/1.1 200 OK
< x-foo: bar
< user-agent: curl/8.5.0
< accept: */*
< x-test: 123Running Standalone with WasmTime
You can also run the component standalone using wasmtime (without Propeller):
wasmtime serve -Scli -Shttp target/wasm32-wasip2/debug/sample_wasi_http_rust.wasmYour output should look like this:
Serving HTTP on http://0.0.0.0:8080/Test the endpoints:
# Root endpoint
curl http://localhost:8080/
# Wait endpoint (sleeps for ~1 second)
curl http://localhost:8080/wait
# Echo endpoint (returns the request body)
curl http://localhost:8080/echo -d 'hello from propeller'
# Echo headers endpoint (returns request headers as response headers)
curl -v http://localhost:8080/echo-headers -H 'X-Test: 123' -H 'X-Foo: bar'The output should be the same as shown in the Test Endpoints section above.
When you are done: Go back to the terminal running
wasmtime serveand pressCtrl+Cto stop the server.