This repository is about playing around with WebAssembly on the server-side. Testing the concept of sandboxed wasm applications and there similarity to containers. The examples are based on the resources below and will be extended incrementally.
- https://github.com/rstropek/rust-samples/tree/master/hello-wagi
- https://slides.com/rainerstropek/wasm-container-killer/fullscreen
- Awesome talk: https://www.youtube.com/watch?v=Xumf_n2KlBM
WebAssembly (abbreviated Wasm) is a binary instruction format for a stack-based virtual machine. Wasm is designed as a portable compilation target for programming languages, enabling deployment on the web for client and server applications. (Reference)
A fast and secure runtime for WebAssembly. (Reference)
WASI is a modular system interface for WebAssembly. As described in the initial announcement, it’s focused on security and portability. (Reference)
WAGI allows you to run WebAssembly WASI binaries as HTTP handlers. Write a "command line" application that prints a few headers, and compile it to WASM32-WASI. Add an entry to the modules.toml matching URL to WASM module. That's it. (Reference)
All examples are implemented in Rust. However, no language-specific knowledge is necessary to understand the code snippets. To execute more complex shell commands the justfile project was used.
Just start by implementing a Hello World
program written in Rust. The code can be found here. To build the project with cargo
, execute the following command:
just example1-build
To run the generated executable run the following command:
just example1-run
The same code can be compiled to wasi
. Therefore the target of cargo build
has to be set to --target wasm32-wasi
. Furthermore it is possible to execute it via the wasmtime
runtime. Just run the following command:
just example1-with-wasmtime
All commands are specified in justfile.
The next examples use watchexec
which simply recompiles the source code when it is updated. For this example to run, a modules.toml
file has to be created. For this example it is sufficient to insert the following lines into the file:
[[module]]
route = "/example2-ping"
module = "./target/wasm32-wasi/debug/example2.wasm"
Wagi is an CGI (Common Gateway Interface) implementation for WebAssembly. The specified module is served as http handler at /example2-ping
. The handler runs sandboxed (eg. handler does not have access to other files on the host and only limited access to environment variables).
The example 2 code just writes the raw format of an HTTP response on standard out.
fn main() {
println!("Content-Type: text/plain");
println!(); // separates header and body
println!("pong")
}
just watch example2
curl -X GET http://localhost:3000/example2-ping \
-H "Content-Type: text/plain"
The third example shows what happens to the header, query string and body of a POST request. The code can be found here.
just watch example3
curl -X POST http://localhost:3000/example3?someQuery=test \
-H "Content-Type: application/json" \
-d '{ "firstname": "michael", "lastname": "neuhold" }'
This example shows how to provide access to static files inside the sandbox. Therefore, the rust code used returns HTML that links to a static styles.css
file. Without explicitly providing the static folder, the sandbox cannot access this file.
just watch example4
In modules.toml
, access can be set up by binding the static folder to the sandbox, which is similar to Docker's volume binding.
[[module]]
route = "/static/..."
module = "./fileserver.gr.wasm"
volumes = {"/" = "/Users/michaelneuhold/Development/repos.nosync/wasm-server-side/_static"}
Now the styles.css
and favicon.ico
can be loaded.
TODO
just watch example5