Skip to content

Commit fccc90b

Browse files
committed
init
0 parents  commit fccc90b

40 files changed

+11495
-0
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
/target

.vscode/settings.json

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,3 @@
1+
{
2+
"rust-analyzer.check.overrideCommand": ["cargo", "component", "check", "--message-format=json"]
3+
}

Cargo.lock

Lines changed: 25 additions & 0 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

Cargo.toml

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,32 @@
1+
[package]
2+
name = "hello-wasi-http"
3+
version = "0.0.0"
4+
edition = "2021"
5+
publish = false
6+
7+
[lib]
8+
crate-type = ["cdylib"]
9+
10+
[package.metadata.component]
11+
package = "component:hello-wasi-http"
12+
# This tells cargo-component to use a special adapter, which doesn't depend on
13+
# `get-environment` or other things not present in the proxy world.
14+
proxy = true
15+
16+
[package.metadata.component.dependencies]
17+
18+
[package.metadata.component.target]
19+
20+
[package.metadata.component.target.dependencies]
21+
"wasi:http" = { path = "wit/deps/http" }
22+
"wasi:clocks" = { path = "wit/deps/clocks" }
23+
"wasi:io" = { path = "wit/deps/io" }
24+
"wasi:random" = { path = "wit/deps/random" }
25+
"wasi:cli" = { path = "wit/deps/cli" }
26+
"wasi:filesystem" = { path = "wit/deps/filesystem" }
27+
"wasi:sockets" = { path = "wit/deps/sockets" }
28+
29+
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
30+
31+
[dependencies]
32+
wit-bindgen-rt = { version = "0.24.0", features = ["bitflags"] }

README.md

Lines changed: 128 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,128 @@
1+
# Hello WASI HTTP!
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.
5+
6+
[Wasmtime]: https://wasmtime.dev
7+
[WASI HTTP]: https://github.com/WebAssembly/wasi-http/
8+
9+
The WASI HTTP API is now stable, and part of WASI 0.2.
10+
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 hello-wasi-http v0.0.0 (/home/wasm/hello-wasi-http)
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 hello-wasi-http
94+
Created binary (application) `hello-wasi-http` package
95+
Updated manifest of package `hello-wasi-http`
96+
Generated source file `src/main.rs`
97+
$ cd hello-wasi-http
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.

0 commit comments

Comments
 (0)