I'd like to work on a demo where I can run this wstd http client example using a custom implementation of the WASI http interface.
I'd like to have a runtime that provides implementations using both quiche and arti.
This is what I have for the client program, I am wondering where to start on this?
I saw a wasmtime http example similar to this but also allowing http access, I can't seem to find it again?
//! Example of instantiating a wasm module which uses WASI imports.
/*
You can execute this example with:
cmake examples/
cargo run --example wasip2
*/
use wasmtime::component::{Component, Linker, ResourceTable};
use wasmtime::*;
use wasmtime_wasi::bindings::sync::Command;
use wasmtime_wasi::{IoView, WasiCtx, WasiCtxBuilder, WasiView};
pub struct ComponentRunStates {
// These two are required basically as a standard way to enable the impl of IoView and
// WasiView.
// impl of WasiView is required by [`wasmtime_wasi::add_to_linker_sync`]
pub wasi_ctx: WasiCtx,
pub resource_table: ResourceTable,
// You can add other custom host states if needed
}
impl IoView for ComponentRunStates {
fn table(&mut self) -> &mut ResourceTable {
&mut self.resource_table
}
}
impl WasiView for ComponentRunStates {
fn ctx(&mut self) -> &mut WasiCtx {
&mut self.wasi_ctx
}
}
fn main() -> Result<()> {
// Define the WASI functions globally on the `Config`.
let engine = Engine::default();
let mut linker = Linker::new(&engine);
wasmtime_wasi::add_to_linker_sync(&mut linker)?;
// Create a WASI context and put it in a Store; all instances in the store
// share this context. `WasiCtxBuilder` provides a number of ways to
// configure what the target program will have access to.
let wasi = WasiCtxBuilder::new().inherit_stdio().inherit_args().build();
let state = ComponentRunStates {
wasi_ctx: wasi,
resource_table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);
// Instantiate our component with the imports we've created, and run it.
let component = Component::from_file(&engine, "target/wasm32-wasip2/debug/wasi.wasm")?;
let command = Command::instantiate(&mut store, &component, &linker)?;
let program_result = command.wasi_cli_run().call_run(&mut store)?;
if program_result.is_err() {
std::process::exit(1)
}
// Alternatively, instead of using `Command`, just instantiate it as a normal component
// New states
let wasi = WasiCtxBuilder::new().inherit_stdio().inherit_args().build();
let state = ComponentRunStates {
wasi_ctx: wasi,
resource_table: ResourceTable::new(),
};
let mut store = Store::new(&engine, state);
// Instantiate it as a normal component
let instance = linker.instantiate(&mut store, &component)?;
// Get the index for the exported interface
let interface_idx = instance
.get_export(&mut store, None, "wasi:cli/run@0.2.0")
.expect("Cannot get `wasi:cli/run@0.2.0` interface");
// Get the index for the exported function in the exported interface
let parent_export_idx = Some(&interface_idx);
let func_idx = instance
.get_export(&mut store, parent_export_idx, "run")
.expect("Cannot get `run` function in `wasi:cli/run@0.2.0` interface");
let func = instance
.get_func(&mut store, func_idx)
.expect("Unreachable since we've got func_idx");
// As the `run` function in `wasi:cli/run@0.2.0` takes no argument and return a WASI result that correspond to a `Result<(), ()>`
// Reference:
// * https://github.com/WebAssembly/wasi-cli/blob/main/wit/run.wit
// * Documentation for [Func::typed](https://docs.rs/wasmtime/latest/wasmtime/component/struct.Func.html#method.typed) and [ComponentNamedList](https://docs.rs/wasmtime/latest/wasmtime/component/trait.ComponentNamedList.html)
let typed = func.typed::<(), (Result<(), ()>,)>(&store)?;
let (result,) = typed.call(&mut store, ())?;
// Required, see documentation of TypedFunc::call
typed.post_return(&mut store)?;
result.map_err(|_| anyhow::anyhow!("error"))
}
Once I have a runtime that can successfully provide http capabilities then I can wade through the standard implementation and see what I have to do to
Do the examples here help with what you're looking to achieve?
Last updated: Apr 07 2025 at 10:03 UTC