|
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