|
1 | | -# Hello WASI HTTP! |
| 1 | +# Rust WASI Hello |
2 | 2 |
|
3 | | -This is a simple tutorial to get started with WASI HTTP using the `wasmtime serve` command introduced in [Wasmtime] 18.0. |
4 | | -It runs an HTTP server and forwards requests to a Wasm component via the [WASI HTTP] API. |
| 3 | +## Roadmap |
5 | 4 |
|
6 | | -[Wasmtime]: https://wasmtime.dev |
7 | | -[WASI HTTP]: https://github.com/WebAssembly/wasi-http/ |
| 5 | +- [x] get a base version compiling |
| 6 | +- [x] Create a GitHub Actions Workflow |
| 7 | +- [x] Add routes to the HTTP handler |
| 8 | +- [ ] Create a wasm OCI publish action |
| 9 | +- [ ] Setup a codespace with all tools pre-installed |
| 10 | +- [ ] Demo unit tests in CI |
8 | 11 |
|
9 | | -The WASI HTTP API is now stable, and part of WASI 0.2. |
| 12 | +## License |
10 | 13 |
|
11 | | -So without further ado... |
12 | | - |
13 | | -## Let's go! |
14 | | - |
15 | | -First, [install `cargo-component`](https://github.com/bytecodealliance/cargo-component#requirements) (version 0.13.2 or later). `cargo-component` is a tool for building Wasm components implemented in Rust. For more |
16 | | -information on building Wasm components from different languages, check [here]! |
17 | | - |
18 | | -[here]: https://component-model.bytecodealliance.org/language-support.html |
19 | | - |
20 | | -With that, build the Wasm component from source in this repository: |
21 | | -```sh |
22 | | -$ cargo component build |
23 | | - Compiling rust-wasi-hello v0.0.0 (/home/wasm/rust-wasi-hello) |
24 | | - Finished `dev` profile [unoptimized + debuginfo] target(s) in 2.01s |
25 | | - Creating component target/wasm32-wasip1/debug/hello_wasi_http.wasm |
26 | | -``` |
27 | | - |
28 | | -This builds a Wasm component at `target/wasm32-wasip1/debug/hello_wasi_http.wasm`. |
29 | | - |
30 | | -To run it, we'll need at least Wasmtime `18.0`. Installation instructions are on [wasmtime.dev]. For example, on Linux or macOS, use the command below: |
31 | | - |
32 | | -```sh |
33 | | -$ curl https://wasmtime.dev/install.sh -sSf | bash |
34 | | -``` |
35 | | - |
36 | | -[wasmtime.dev]: https://wasmtime.dev/ |
37 | | - |
38 | | -Then, run in your terminal: |
39 | | -```sh |
40 | | -$ cargo component serve |
41 | | -``` |
42 | | -This starts up an HTTP server that, by default, listens on `0.0.0.0:8080`. |
43 | | - |
44 | | -With that running, in another window, we can now make requests! |
45 | | -```sh |
46 | | -$ curl http://localhost:8080 |
47 | | -Hello, wasi:http/proxy world! |
48 | | -``` |
49 | | - |
50 | | -## Optimizing! |
51 | | - |
52 | | -The above uses a `debug` build. To make a component that runs faster, build with `cargo component build --release`. |
53 | | - |
54 | | -It's also worth making sure you have a release build of Wasmtime; if you installed it from the instructions above |
55 | | -with wasmtime.dev, you're good. |
56 | | - |
57 | | -Wasmtime has several tuning options that can improve performance in different situations—pass `-O help` for a |
58 | | -list. One that's especially useful here is `-O pooling-allocator`. |
59 | | - |
60 | | -## Notes |
61 | | - |
62 | | -`wasmtime serve` uses the [proxy] world, which is a specialized world just for accepting requests and producing |
63 | | -responses. One interesting thing about the proxy world is that it doesn't have a filesystem or network API. If you add |
64 | | -code to the example that tries to access files or network sockets, it won't be able to build, because those APIs are |
65 | | -not available in this world. This allows proxy components to run in many different places, including specialized |
66 | | -serverless environments which may not provide traditional filesystem and network access. |
67 | | - |
68 | | -But, what if you do want to have it serve some files? One option will be to use |
69 | | -[WASI-Virt](https://github.com/bytecodealliance/WASI-Virt), which is a tool that can bundle a filesystem with a |
70 | | -component. |
71 | | - |
72 | | -Another option is to use a custom `world`. The proxy world is meant to be able to run in many different environments, |
73 | | -but if you know your environment, and you know it has a filesystem, you could create your own world, by including both |
74 | | -the `"wasi:http/proxy"` and `"wasi:filesystem/types"` or any other APIs you want the Wasm to be able to access. This |
75 | | -would require a custom embedding of Wasmtime, as it wouldn't run under plain `wasmtime serve`, so it's a little more |
76 | | -work to set up. |
77 | | - |
78 | | -In the future, we expect to see standard `world`s emerge that combine WASI HTTP with many other APIs, such as |
79 | | -[wasi-cloud-core]. |
80 | | - |
81 | | -If you're interested in tutorials for any of these options, please reach out and say hi! |
82 | | - |
83 | | -[proxy]: https://github.com/WebAssembly/wasi-http/blob/main/wit/proxy.wit |
84 | | -[wasi-cloud-core]: https://github.com/WebAssembly/wasi-cloud-core |
85 | | - |
86 | | -## Creating this repo |
87 | | - |
88 | | -Here are my notes on how I created this repository, in case you're interested in recreating it. |
89 | | - |
90 | | -To create a new project, run: |
91 | | - |
92 | | -```sh |
93 | | -$ cargo component new --proxy --lib rust-wasi-hello |
94 | | - Created binary (application) `rust-wasi-hello` package |
95 | | - Updated manifest of package `rust-wasi-hello` |
96 | | - Generated source file `src/main.rs` |
97 | | -$ cd rust-wasi-hello |
98 | | -``` |
99 | | - |
100 | | -Copy the `wit` directory from your version of Wasmtime, to ensure that we're using the same version of the API that |
101 | | -Wasmtime is built with (e.g., for Wasmtime 18.0.0: https://github.com/bytecodealliance/wasmtime/tree/release-18.0.0). |
102 | | - |
103 | | -Then, I manually trimmed the filesystem and sockets dependencies out. |
104 | | - |
105 | | -In the future, we'll have wit dependencies stored in a registry, which will make this all much easier. |
106 | | - |
107 | | -I derived `src/lib.rs` from Wasmtime's `crates/test-programs/src/bin/api_proxy.rs` contents on the `main` branch, |
108 | | -adapted it to work with cargo component, in particular by adding: |
109 | | - |
110 | | -```rust |
111 | | -cargo_component_bindings::generate!(); |
112 | | -``` |
113 | | - |
114 | | -Then, I renamed the `T` type to `Component`, which the bindings expect. |
115 | | - |
116 | | -Finally, add dependencies: |
117 | | -``` |
118 | | -$ cargo component add --target --path wit/deps/clocks wasi:clocks |
119 | | -$ cargo component add --target --path wit/deps/io wasi:io |
120 | | -$ cargo component add --target --path wit/deps/random wasi:random |
121 | | -$ cargo component add --target --path wit/deps/cli wasi:cli |
122 | | -$ cargo component add --target --path wit/deps/logging wasi:logging |
123 | | -``` |
124 | | - |
125 | | -These don't all actually get used in this tutorial, but they're currently needed because of some of the interfaces we |
126 | | -copied in from the Wasmtime tree reference them. |
127 | | - |
128 | | -> TODO: I should also make a `api_proxy_streaming.rs` version to show streaming. |
| 14 | +MIT OR Apache-2.0 |
0 commit comments