Stream: jco

Topic: Using WASI in jco


view this post on Zulip Landon James (Jan 04 2024 at 00:09):

I am trying to wrap my head around using WASI with the component model and have some questions. Lets say I have a component written in Rust like:

package wasm-version-tests:component;

interface clients {
  resource wasm-version-tests-client {
    constructor();
    hello-world: func() -> string;
  }
}


world wasm-version-tests {
  export clients;
}
wit_bindgen::generate!({
world: "wasm-version-tests",
exports: {
    "wasm-version-tests:component/clients/wasm-version-tests-client": WasmVersionTestsClients,
},
use exports::wasm_version_tests::component::clients::GuestWasmVersionTestsClient;

pub struct WasmVersionTestsClients;

impl GuestWasmVersionTestsClient for WasmVersionTestsClients {
    fn fetch_url(&self, url: String) -> String {
        //Pretend fetch is doing an http call
        let data = fetch(url);
        return "Hello World".to_string();
    }

    fn new() -> Self {
        WasmVersionTestsClients
    }
}

This component performs an http call. If I compile this to wasm32-wasi and use jco transpile on the resulting binary, will the wasi:http shim automatically be included? Or do I need to specify an import wasi:http statement in my .wit file and use the imported wasi:http functions to handle all http traffic? I know in the wasm-bindgen era several crates (http ones specifically) had special compilation flags for wasm32 targets that let them work directly with the bindings, but as far as I can tell that doesn't seem to be a thing yet for wit and the component model.

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:39):

@Landon James in order to depend on HTTP in WASI, you do indeed need to directly specify you depend on it.

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:41):

What we did in the surf crate (one of the HTTP crates from the wasm-bindgen era) was to just assume that if you compiled with the bindgen flag on, that the js-sys/web-sys APIs would be present. This really wasn't great.

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:41):

Actually, let me walk back my earlier statement a little bit perhaps

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:42):

if you want to use wasi:http in Rust, you do need to import it directly. jco knows how to provide that interface, so you'll generally be fine if you do that.

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:44):

A different way of doing this could be to just use the Rust stdlib's TCP abstraction, and bring your own HTTP stack. Doing this natively for WASI Preview 2 is likely going to be some work because afaik there are no async Rust runtimes which directly support it yet (the stdlib doesn't either). But it is possible to support it by targeting WASI Preview 1 and using the compat shim to allow it to work on Preview 2.

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:45):

wrt jco: targeting Node.js should give you access to TCP sockets (though I think we might still be missing the TCP bind syscall in the implementation) - while targeting the browser will only give you access to the high-level HTTP interfaces (but the browser impl has been temporarily de-prioritized in favor of getting Node.js over the finish line first)

view this post on Zulip Yoshua Wuyts (Jan 04 2024 at 12:46):

Does that... make sense?

view this post on Zulip Landon James (Jan 05 2024 at 18:12):

Yes I think that (mostly) makes sense, thank you! My one clarifying question would be around:

if you want to use wasi:http in Rust, you do need to import it directly. jco knows how to provide that interface, so you'll generally be fine if you do that.

I am assuming that this means importing the wasmtime-wasi-http crate and using the functions from there to make my http calls? But I would not need to import the wasi:http wit definitions from https://github.com/WebAssembly/wasi-http unless I wanted to include those types in my component's public API?

Non-jco related sidenote: importing wasmtime-wasi-http to my project and building for wasm32-wasi causes several build failures via the wasmtime-fiber crate:

error: fibers are not supported on this platform
  --> /Users/lnj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmtime-fiber-16.0.0/src/lib.rs:17:9
   |
17 |         compile_error!("fibers are not supported on this platform");
   |         ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

error[E0433]: failed to resolve: use of undeclared crate or module `imp`
  --> /Users/lnj/.cargo/registry/src/index.crates.io-6f17d22bba15001f/wasmtime-fiber-16.0.0/src/lib.rs:27:17
   |
27 |         Ok(Self(imp::FiberStack::new(size)?))
   |                 ^^^ use of undeclared crate or module `imp`
Contribute to WebAssembly/wasi-http development by creating an account on GitHub.

view this post on Zulip Pat Hickey (Jan 06 2024 at 19:54):

wasmtime-wasi-http depends on wasmtime, so it will only build for the platforms wasmtime builds for

view this post on Zulip Pat Hickey (Jan 06 2024 at 19:54):

it is a host implementation of wasi-http

view this post on Zulip Pat Hickey (Jan 06 2024 at 19:54):

if you are trying to use wasi-http interfaces from webassembly, you should use wit-bindgen in your crate

view this post on Zulip Pat Hickey (Jan 06 2024 at 19:55):

with the wasi-http wits

view this post on Zulip Landon James (Jan 10 2024 at 02:29):

Got this all figured out and documented in this repo. Thanks for all the help!

Contribute to landonxjames/wasi-http-test development by creating an account on GitHub.

view this post on Zulip Victor Adossi (Jan 10 2024 at 02:35):

Funnily enough, I happen to be doing something similar and ended up with a codebase very similar to yours -- one thing I wanted to ask is how you built those generated typescript bindings? I used only incoming-handler so I just wrote the minimal required type declarations by hand.

I did a tiny bit of searching around jco and componentize-js underneath to see if there was something for that (generating type declarations) but didn't find anything.

view this post on Zulip Landon James (Jan 10 2024 at 02:46):

Thankfully thats one of the easier steps, you can look through the build script in that repo's package.json for the full steps, but the gist of it is:

npx jco transpile ./path/to/your/componentized/binary -o  ./path/to/output --no-namespaced-exports

And it will output the typescript definitions. In my repo that is everything in this directory. Note that the --no-namespaced-exports flag is required because jco by default generates some code that is just barely not typescript compatible.

view this post on Zulip Victor Adossi (Jan 10 2024 at 03:29):

Thanks for the tips and spelling it out in detail, I'll see if I can work that into my flow!

view this post on Zulip Ralph (Jan 10 2024 at 11:41):

@Landon James if I already have a 12_05 component, I should just be able to use this directly, yes? In other words, I should just be able to jco transpile and directly use it.

view this post on Zulip Victor Adossi (Jan 10 2024 at 18:18):

Oh hey @Landon James if you're interested in the code that I ended up with, it's up here after a bunch of polishing:

https://github.com/wasmCloud/wasmCloud/pull/1300/files

Feature or Problem As Javascript support for WebAssembly progresses along with the jco toolchain, it's possible to build actors that work with the wasmcloud ecosystem, leveraging the existing ...

view this post on Zulip Victor Adossi (Jan 10 2024 at 18:19):

hopefully it's pretty easy to follow -- I ended up copying type definitions from jco explicitly, the ones in there are pretty complete so I didn't have to work too hard -- just some typescript type declaration wrangling

view this post on Zulip Landon James (Jan 10 2024 at 19:01):

Ralph said:

Landon James if I already have a 12_05 component, I should just be able to use this directly, yes? In other words, I should just be able to jco transpile and directly use it.

Yep that is my understanding! jco makes it pretty easy to transpile the js bindings from any wasm (component) binary.


Last updated: Dec 23 2024 at 12:05 UTC