├── .github └── workflows │ ├── artifacts.yml │ ├── build.yml │ ├── container-preview.yml │ └── container-release.yml ├── .gitignore ├── CODE_OF_CONDUCT.md ├── CONTRIBUTING.md ├── Cargo.lock ├── Cargo.toml ├── LICENSE ├── Makefile ├── NOTICE ├── README.md ├── crates ├── api-manage-openapi │ ├── Cargo.toml │ ├── build.rs │ └── src │ │ ├── lib.rs │ │ └── openapi.json ├── api-manage │ ├── Cargo.toml │ └── src │ │ ├── handlers │ │ ├── mod.rs │ │ └── v0 │ │ │ ├── mod.rs │ │ │ └── workers.rs │ │ ├── lib.rs │ │ └── models │ │ ├── mod.rs │ │ ├── worker.rs │ │ └── worker_config.rs ├── config │ ├── Cargo.toml │ └── src │ │ ├── errors.rs │ │ └── lib.rs ├── data-kv │ ├── Cargo.toml │ └── src │ │ ├── lib.rs │ │ └── store.rs ├── panel │ ├── Cargo.toml │ ├── build.rs │ ├── client │ │ ├── .gitignore │ │ ├── dist │ │ │ └── .gitkeep │ │ ├── index.html │ │ ├── package.json │ │ ├── public │ │ │ └── .gitkeep │ │ ├── src │ │ │ ├── app.jsx │ │ │ ├── components │ │ │ │ ├── content.jsx │ │ │ │ ├── content.scss │ │ │ │ ├── header.jsx │ │ │ │ ├── header.scss │ │ │ │ ├── sidebar.jsx │ │ │ │ ├── sidebar.scss │ │ │ │ └── workerCard.jsx │ │ │ ├── main.jsx │ │ │ ├── main.scss │ │ │ ├── router.jsx │ │ │ └── routes │ │ │ │ ├── home.jsx │ │ │ │ ├── worker.jsx │ │ │ │ └── workers.jsx │ │ └── vite.config.js │ └── src │ │ ├── handlers │ │ ├── mod.rs │ │ └── panel.rs │ │ └── lib.rs ├── project │ ├── Cargo.toml │ ├── README.md │ ├── src │ │ ├── errors.rs │ │ ├── fetch.rs │ │ ├── lib.rs │ │ ├── metadata.rs │ │ ├── options.rs │ │ └── types │ │ │ ├── git.rs │ │ │ └── mod.rs │ └── tests │ │ └── data │ │ └── index.js ├── router │ ├── Cargo.toml │ ├── src │ │ ├── files.rs │ │ ├── lib.rs │ │ ├── route.rs │ │ └── route │ │ │ ├── route_type.rs │ │ │ └── segment.rs │ └── tests │ │ └── data │ │ └── files │ │ ├── _home.ext │ │ ├── _index.js │ │ ├── _internal │ │ └── index.js │ │ ├── examples.js │ │ ├── examples │ │ ├── _index │ │ │ ├── home.ext │ │ │ └── index.js │ │ ├── home.ext │ │ ├── index │ │ │ ├── home.ext │ │ │ ├── index.js │ │ │ └── public │ │ │ │ └── index.js │ │ └── public.js │ │ ├── home.ext │ │ ├── index.js │ │ ├── public.js │ │ └── public │ │ ├── home.ext │ │ └── index.js ├── runtimes │ ├── Cargo.toml │ └── src │ │ ├── errors.rs │ │ ├── lib.rs │ │ ├── modules │ │ ├── external.rs │ │ ├── javascript.rs │ │ ├── mod.rs │ │ └── native.rs │ │ └── runtime.rs ├── server │ ├── Cargo.toml │ └── src │ │ ├── errors.rs │ │ ├── handlers │ │ ├── assets.rs │ │ ├── mod.rs │ │ ├── not_found.rs │ │ └── worker.rs │ │ └── lib.rs ├── store │ ├── Cargo.toml │ └── src │ │ ├── errors.rs │ │ └── lib.rs └── worker │ ├── Cargo.toml │ └── src │ ├── bindings │ ├── http.rs │ └── mod.rs │ ├── config.rs │ ├── errors.rs │ ├── features │ ├── data.rs │ ├── folders.rs │ ├── http_requests.rs │ ├── mod.rs │ └── wasi_nn.rs │ ├── io.rs │ ├── lib.rs │ └── stdio.rs ├── deny.toml ├── docs ├── .gitignore ├── README.md ├── babel.config.js ├── docs │ ├── containers.md │ ├── features │ │ ├── _category_.json │ │ ├── all.md │ │ ├── dynamic-routes.md │ │ ├── environment-variables.md │ │ ├── http-requests.md │ │ ├── key-value.md │ │ ├── machine-learning.md │ │ ├── mount-folders.md │ │ ├── multiple-language-runtimes.md │ │ └── static-assets.md │ ├── get-started │ │ ├── _category_.json │ │ ├── how-it-works.md │ │ ├── introduction.mdx │ │ └── quickstart.md │ └── languages │ │ ├── _category_.json │ │ ├── go.md │ │ ├── introduction.md │ │ ├── javascript.md │ │ ├── python.md │ │ ├── ruby.md │ │ ├── rust.md │ │ └── zig.md ├── docusaurus.config.js ├── package.json ├── sidebars.js ├── src │ ├── components │ │ └── HomepageFeatures │ │ │ ├── index.js │ │ │ └── styles.module.css │ ├── css │ │ └── custom.css │ └── pages │ │ ├── diagram.svg │ │ ├── index.js │ │ └── index.module.css └── static │ ├── .nojekyll │ ├── _redirects │ └── img │ ├── docs │ └── features │ │ └── wasi-nn.webp │ ├── favicon.svg │ ├── languages │ ├── go.svg │ ├── js.svg │ ├── python.svg │ ├── ruby.svg │ ├── rust.svg │ └── zig.svg │ └── logo.svg ├── examples ├── Makefile ├── README.md ├── components │ ├── .gitignore │ ├── README.md │ └── wasi-component-adapter │ │ ├── README.md │ │ ├── wasi_snapshot_preview1-command.wasm │ │ └── wasi_snapshot_preview1-reactor.wasm ├── containers │ ├── .gitignore │ ├── Dockerfile │ ├── Makefile │ ├── README.md │ ├── apps-src │ │ ├── tmp │ │ │ └── file.txt │ │ ├── user-generation-go │ │ │ ├── .gitignore │ │ │ ├── go.mod │ │ │ ├── go.sum │ │ │ ├── main.go │ │ │ ├── user-generation-go.toml │ │ │ └── vendor │ │ │ │ ├── github.com │ │ │ │ ├── tidwall │ │ │ │ │ ├── gjson │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── SYNTAX.md │ │ │ │ │ │ ├── gjson.go │ │ │ │ │ │ └── logo.png │ │ │ │ │ ├── match │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ └── match.go │ │ │ │ │ ├── pretty │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ └── pretty.go │ │ │ │ │ └── sjson │ │ │ │ │ │ ├── LICENSE │ │ │ │ │ │ ├── README.md │ │ │ │ │ │ ├── logo.png │ │ │ │ │ │ └── sjson.go │ │ │ │ └── vmware-labs │ │ │ │ │ └── wasm-workers-server │ │ │ │ │ ├── LICENSE │ │ │ │ │ ├── NOTICE │ │ │ │ │ └── kits │ │ │ │ │ └── go │ │ │ │ │ └── worker │ │ │ │ │ ├── README.md │ │ │ │ │ ├── bindings │ │ │ │ │ ├── bindings.c │ │ │ │ │ ├── bindings.go │ │ │ │ │ ├── bindings.h │ │ │ │ │ └── bindings_types.go │ │ │ │ │ ├── doc.go │ │ │ │ │ └── worker.go │ │ │ │ └── modules.txt │ │ ├── user-generation-js │ │ │ ├── user-generation-js.js │ │ │ └── user-generation-js.toml │ │ ├── user-generation-python │ │ │ ├── index.py │ │ │ ├── index.toml │ │ │ └── tmp │ │ ├── user-generation-ruby │ │ │ ├── index.rb │ │ │ ├── index.toml │ │ │ └── tmp │ │ └── user-generation-rust │ │ │ ├── .cargo │ │ │ └── config.toml │ │ │ ├── .gitignore │ │ │ ├── Cargo.lock │ │ │ ├── Cargo.toml │ │ │ ├── rust-toolchain.toml │ │ │ ├── src │ │ │ └── main.rs │ │ │ └── user-generation-rust.toml │ ├── apps │ │ └── root │ │ │ ├── .wws.toml │ │ │ ├── user-generation-go.toml │ │ │ ├── user-generation-js.js │ │ │ ├── user-generation-js.toml │ │ │ ├── user-generation-python │ │ │ ├── index.py │ │ │ ├── index.toml │ │ │ └── tmp │ │ │ │ └── file.txt │ │ │ ├── user-generation-ruby │ │ │ ├── index.rb │ │ │ ├── index.toml │ │ │ └── tmp │ │ │ │ └── file.txt │ │ │ └── user-generation-rust.toml │ └── tmp │ │ └── file.txt ├── go-basic │ ├── README.md │ ├── go.mod │ ├── go.sum │ └── main.go ├── go-envs │ ├── README.md │ ├── envs.go │ └── envs.toml ├── go-fetch │ ├── README.md │ ├── go.mod │ ├── go.sum │ ├── index.toml │ └── main.go ├── go-kv │ ├── README.md │ ├── counter.go │ └── counter.toml ├── go-params │ ├── README.md │ ├── main.go │ └── public │ │ ├── main.css │ │ └── water.min.css ├── js-async │ ├── README.md │ └── index.js ├── js-basic │ ├── README.md │ └── index.js ├── js-catchall │ ├── README.md │ ├── [...slug] │ │ └── index.js │ ├── about.js │ └── other │ │ └── [...slug].js ├── js-fetch │ ├── README.md │ ├── index.js │ └── index.toml ├── js-hono │ ├── README.md │ ├── dist │ │ └── [...app].js │ └── src │ │ ├── index.js │ │ └── package.json ├── js-json │ ├── README.md │ ├── handler.js │ ├── handler.toml │ └── public │ │ └── robots.txt ├── js-modules │ ├── README.md │ └── index.js ├── js-params │ ├── README.md │ ├── [id].js │ ├── [id] │ │ └── fixed.js │ ├── fixed.js │ ├── public │ │ ├── main.css │ │ └── water.min.css │ └── sub │ │ └── [id].js ├── js-redirect │ ├── README.md │ └── handler.js ├── js-tictactoe │ ├── README.md │ ├── handler.js │ └── handler.toml ├── protomaps │ ├── .gitignore │ ├── .wws.toml │ ├── Dockerfile │ ├── Makefile │ ├── README.md │ ├── [z] │ │ └── [x] │ │ │ └── [y] │ │ │ ├── index.py │ │ │ └── index.toml │ ├── _libs │ │ ├── __init__.py │ │ ├── reader.py │ │ └── tile.py │ ├── _maps │ │ ├── .keep │ │ └── map.pmtiles │ └── public │ │ ├── css │ │ └── leaflet.css │ │ ├── index.html │ │ └── js │ │ ├── leaflet.js │ │ └── protomaps.min.js ├── python-basic │ ├── .wws.toml │ ├── README.md │ └── index.py ├── python-envs │ ├── .wws.toml │ ├── README.md │ ├── envs.py │ └── envs.toml ├── python-kv │ ├── .wws.toml │ ├── README.md │ ├── counter.py │ └── counter.toml ├── python-libs │ ├── .wws.toml │ ├── README.md │ ├── _libs │ │ └── .gitignore │ ├── index.py │ ├── index.toml │ └── requirements.txt ├── python-mount │ ├── .wws.toml │ ├── README.md │ ├── _assets │ │ └── index.html │ ├── index.py │ └── index.toml ├── ruby-basic │ ├── .wws.toml │ ├── README.md │ └── index.rb ├── ruby-envs │ ├── .wws.toml │ ├── README.md │ ├── envs.rb │ └── envs.toml ├── ruby-kv │ ├── .wws.toml │ ├── README.md │ ├── counter.rb │ └── counter.toml ├── ruby-mount │ ├── .wws.toml │ ├── README.md │ ├── _images │ │ └── ruby.svg │ ├── image.rb │ ├── image.toml │ └── public │ │ ├── css │ │ └── styles.css │ │ └── index.html ├── rust-basic │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── rust-basic.toml │ └── src │ │ └── main.rs ├── rust-fetch │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── index.toml │ └── src │ │ └── main.rs ├── rust-kv │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── rust-kv.toml │ └── src │ │ └── main.rs ├── rust-params │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── public │ │ ├── main.css │ │ └── water.min.css │ └── src │ │ └── main.rs ├── rust-pdf-create │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ └── src │ │ └── main.rs ├── rust-wasi-nn-preload │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── _data │ │ └── dataset.json │ ├── _images │ │ └── .gitkeep │ ├── _models │ │ └── mobilenet │ │ │ └── .gitkeep │ ├── index.js │ ├── inference.toml │ ├── inference.wasm │ ├── prepare.sh │ ├── public │ │ ├── main.css │ │ └── main.js │ └── src │ │ └── main.rs ├── rust-wasi-nn │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── README.md │ ├── _images │ │ └── .gitkeep │ ├── _models │ │ └── dataset.json │ ├── index.js │ ├── inference.toml │ ├── inference.wasm │ ├── prepare.sh │ ├── public │ │ ├── main.css │ │ └── main.js │ └── src │ │ └── main.rs ├── zig-basic │ ├── README.md │ ├── build.zig │ └── src │ │ └── basic.zig ├── zig-envs │ ├── README.md │ ├── build.zig │ ├── src │ │ └── envs.zig │ └── zig-out │ │ └── bin │ │ └── envs.toml ├── zig-kv │ ├── README.md │ ├── build.zig │ ├── src │ │ └── worker-kv.zig │ └── zig-out │ │ └── bin │ │ └── worker-kv.toml ├── zig-mount │ ├── build.zig │ ├── src │ │ └── mount.zig │ └── zig-out │ │ └── bin │ │ ├── _images │ │ └── zig.svg │ │ └── mount.toml └── zig-params │ ├── README.md │ ├── build.zig │ └── src │ └── worker-params.zig ├── go.mod ├── go.sum ├── image ├── Dockerfile └── Prebuilt.dockerfile ├── install.sh ├── kits ├── go │ └── worker │ │ ├── README.md │ │ ├── bindings │ │ ├── bindings.c │ │ ├── bindings.go │ │ ├── bindings.h │ │ ├── bindings_component_type.o │ │ └── bindings_types.go │ │ ├── doc.go │ │ └── worker.go ├── javascript │ ├── .gitignore │ ├── Cargo.lock │ ├── Cargo.toml │ ├── Makefile │ ├── README.md │ ├── build.rs │ ├── shims │ │ ├── bindings.js │ │ ├── index.js │ │ ├── package.json │ │ └── types │ │ │ ├── cache.js │ │ │ ├── headers.js │ │ │ ├── index.js │ │ │ ├── request.js │ │ │ └── response.js │ ├── src │ │ ├── bindings.rs │ │ ├── error.rs │ │ └── main.rs │ └── wasm-workers-quick-js-engine.wasm ├── rust │ ├── Cargo.toml │ ├── src │ │ ├── bindings.rs │ │ ├── cache.rs │ │ ├── content.rs │ │ ├── io.rs │ │ └── lib.rs │ └── worker │ │ ├── Cargo.toml │ │ └── src │ │ ├── args.rs │ │ ├── expand.rs │ │ └── lib.rs └── zig │ └── worker │ ├── README.md │ └── src │ └── worker.zig ├── metadata └── repository │ └── v1 │ ├── files │ ├── python │ │ ├── 3 │ │ │ ├── poly.py │ │ │ └── wrapper.txt │ │ └── 3-1 │ │ │ ├── poly.py │ │ │ └── wrapper.txt │ └── ruby │ │ ├── 3 │ │ ├── poly.rb │ │ └── wrapper.txt │ │ └── 3-1 │ │ ├── poly.rb │ │ └── wrapper.txt │ └── index.toml ├── src ├── commands │ ├── main.rs │ ├── mod.rs │ └── runtimes.rs ├── lib.rs ├── main.rs └── utils │ ├── errors.rs │ ├── mod.rs │ ├── options.rs │ └── runtimes.rs ├── tests ├── data │ ├── metadata │ │ ├── repository.toml │ │ └── runtime.toml │ ├── params │ │ ├── [id].wasm │ │ ├── [id] │ │ │ ├── fixed.wasm │ │ │ └── sub.wasm │ │ ├── fixed.wasm │ │ └── sub │ │ │ ├── [...all].wasm │ │ │ ├── [id].wasm │ │ │ └── sub │ │ │ └── [...all].wasm │ └── public │ │ ├── .keep │ │ ├── about │ │ └── index.html │ │ ├── index.html │ │ └── main.css └── e2e.rs └── wit ├── core ├── http-types.wit └── http.wit └── go-ephemeral ├── http-types.wit └── http.wit /.gitignore: -------------------------------------------------------------------------------- 1 | target 2 | *.wasm 3 | !tests/**/*.wasm 4 | examples/*.toml 5 | .DS_Store 6 | .wws 7 | **/zig-cache 8 | **/zig-out 9 | node_modules 10 | -------------------------------------------------------------------------------- /Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build 2 | 3 | build: 4 | cargo build --release 5 | 6 | image-amd64: 7 | docker build -f image/Dockerfile --platform amd64 -t wasm-workers-server:latest-amd64 . 8 | 9 | image-arm64: 10 | docker build -f image/Dockerfile --platform arm64 -t wasm-workers-server:latest-arm64 . 11 | 12 | push-image-multiarch: 13 | docker buildx build -f image/Dockerfile --platform linux/arm64/v8,linux/amd64 --push -t projects.registry.vmware.com/wasmlabs/containers/wasm-workers-server:latest . 14 | -------------------------------------------------------------------------------- /NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 VMware, Inc. 2 | 3 | This product is licensed to you under the Apache License, V2.0 (the "License"). You may not use this product except in compliance with the License. 4 | 5 | This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -------------------------------------------------------------------------------- /crates/api-manage-openapi/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-api-manage-openapi" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | 11 | [build-dependencies] 12 | utoipa = { version = "3.3.0", features = ["actix_extras"] } 13 | wws-api-manage = { path = "../api-manage" } 14 | -------------------------------------------------------------------------------- /crates/api-manage-openapi/build.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Trick to generate the OpenAPI spec on build time. 5 | // See: https://github.com/juhaku/utoipa/issues/214#issuecomment-1179589373 6 | 7 | use std::fs; 8 | use utoipa::OpenApi; 9 | use wws_api_manage::ApiDoc; 10 | 11 | fn main() { 12 | let spec = ApiDoc::openapi().to_pretty_json().unwrap(); 13 | fs::write("./src/openapi.json", spec).expect("Error writing the OpenAPI documentation"); 14 | } 15 | -------------------------------------------------------------------------------- /crates/api-manage-openapi/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// Contains the Open API Spec of the wws management API. 5 | pub static OPEN_API_SPEC: &str = include_str!("./openapi.json"); 6 | -------------------------------------------------------------------------------- /crates/api-manage/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-api-manage" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | actix-web = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | wws-router = { workspace = true } 14 | wws-worker = { workspace = true } 15 | utoipa = { version = "3.3.0", features = ["actix_extras"] } 16 | -------------------------------------------------------------------------------- /crates/api-manage/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod v0; 5 | -------------------------------------------------------------------------------- /crates/api-manage/src/handlers/v0/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod workers; 5 | -------------------------------------------------------------------------------- /crates/api-manage/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | mod handlers; 5 | mod models; 6 | 7 | use actix_web::web::ServiceConfig; 8 | use models::Worker; 9 | use utoipa::OpenApi; 10 | 11 | /// Add the administration panel HTTP handlers to an existing 12 | /// Actix application. 13 | pub fn config_manage_api_handlers(cfg: &mut ServiceConfig) { 14 | cfg.service(handlers::v0::workers::handle_api_workers); 15 | cfg.service(handlers::v0::workers::handle_api_worker); 16 | } 17 | 18 | #[derive(OpenApi)] 19 | #[openapi( 20 | info( 21 | title = "Wasm Workers Server Management API", 22 | description = "Exposes methods to read current workers, services and to configure and run projects", 23 | license( 24 | name = "Apache 2.0", 25 | url = "https://github.com/vmware-labs/wasm-workers-server/blob/main/LICENSE" 26 | ), 27 | contact(), 28 | version = "1" 29 | ), 30 | paths( 31 | handlers::v0::workers::handle_api_workers, 32 | handlers::v0::workers::handle_api_worker 33 | ), 34 | components(schemas(Worker)) 35 | )] 36 | pub struct ApiDoc; 37 | -------------------------------------------------------------------------------- /crates/api-manage/src/models/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | mod worker; 5 | mod worker_config; 6 | 7 | pub use worker::Worker; 8 | pub use worker_config::WorkerConfig; 9 | -------------------------------------------------------------------------------- /crates/api-manage/src/models/worker.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::Serialize; 5 | use utoipa::ToSchema; 6 | use wws_router::{Route, WORKERS}; 7 | 8 | #[derive(Serialize, ToSchema)] 9 | /// Defines a worker in a given application. 10 | pub struct Worker { 11 | /// Worker identifier 12 | id: String, 13 | /// The associated name to this worker 14 | #[schema(example = "default")] 15 | name: String, 16 | /// API path for this specific worker. 17 | #[schema(example = "/api/hello")] 18 | path: String, 19 | /// Associated source code / wasm module to this worker 20 | #[schema(example = "/app/api/hello.js")] 21 | filepath: String, 22 | } 23 | 24 | impl From<&Route> for Worker { 25 | fn from(value: &Route) -> Self { 26 | let workers = WORKERS 27 | .read() 28 | .expect("error locking worker lock for reading"); 29 | let name = workers 30 | .get(&value.worker) 31 | .expect("unexpected missing worker") 32 | .config 33 | .name 34 | .as_ref(); 35 | 36 | Self { 37 | id: value.worker.clone(), 38 | name: name.unwrap_or(&String::from("default")).to_string(), 39 | path: value.path.clone(), 40 | filepath: value.handler.to_string_lossy().to_string(), 41 | } 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/config/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-config" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | serde = { workspace = true } 11 | serde_json = { workspace = true } 12 | toml = { workspace = true } 13 | wws-project = { workspace = true } 14 | -------------------------------------------------------------------------------- /crates/config/src/errors.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub type Result = std::result::Result; 5 | 6 | #[derive(Debug)] 7 | pub enum ConfigError { 8 | CannotLoadConfig(std::io::Error), 9 | CannotParseConfig(toml::de::Error), 10 | CannotSaveConfig, 11 | } 12 | 13 | impl std::fmt::Display for ConfigError { 14 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 | match self { 16 | Self::CannotLoadConfig(err) => write!(f, "Could not load configuration: {}", err), 17 | Self::CannotParseConfig(err) => write!(f, "Could not parse configuration: {}", err), 18 | Self::CannotSaveConfig => write!(f, "Could not save configuration"), 19 | } 20 | } 21 | } 22 | 23 | impl From for ConfigError { 24 | fn from(error: std::io::Error) -> Self { 25 | ConfigError::CannotLoadConfig(error) 26 | } 27 | } 28 | 29 | impl From for ConfigError { 30 | fn from(error: toml::de::Error) -> ConfigError { 31 | ConfigError::CannotParseConfig(error) 32 | } 33 | } 34 | 35 | impl From for ConfigError { 36 | fn from(_: toml::ser::Error) -> ConfigError { 37 | ConfigError::CannotSaveConfig 38 | } 39 | } 40 | -------------------------------------------------------------------------------- /crates/data-kv/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-data-kv" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | serde = { workspace = true } 11 | serde_json = { workspace = true } -------------------------------------------------------------------------------- /crates/data-kv/src/store.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::collections::HashMap; 5 | 6 | /// A K/V store. It's composed by a namespace and the list of Key/Values 7 | pub struct KVStore { 8 | /// The namespace associated to this Key/Value store 9 | pub namespace: String, 10 | /// The list of Key - Values. In this project, both keys and values are considered 11 | /// strings. 12 | store: HashMap, 13 | } 14 | 15 | impl KVStore { 16 | /// Creates a new K/V store for the given namespace 17 | pub fn new(namespace: String) -> Self { 18 | Self { 19 | namespace, 20 | store: HashMap::new(), 21 | } 22 | } 23 | 24 | /// Clone the current content of the Key/Value store 25 | pub fn clone(&self) -> HashMap { 26 | self.store.clone() 27 | } 28 | 29 | /// Replace the content of the K/V store with a new state 30 | pub fn replace(&mut self, state: HashMap) { 31 | self.store = state; 32 | } 33 | } 34 | -------------------------------------------------------------------------------- /crates/panel/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-panel" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | rust-embed = "6.6.1" 11 | mime_guess = "2.0.4" 12 | actix-web = { workspace = true } 13 | -------------------------------------------------------------------------------- /crates/panel/build.rs: -------------------------------------------------------------------------------- 1 | use std::{io::ErrorKind, process::Command}; 2 | 3 | // Build the client admin panel. 4 | fn main() { 5 | // First check if NPM is available in the system 6 | match Command::new("npm").spawn() { 7 | Ok(_) => { 8 | Command::new("npm") 9 | .current_dir("client") 10 | .arg("install") 11 | .status() 12 | .expect("failed to execute process"); 13 | 14 | Command::new("npm") 15 | .current_dir("client") 16 | .args(["run", "build"]) 17 | .status() 18 | .expect("failed to execute process"); 19 | } 20 | Err(e) => { 21 | if let ErrorKind::NotFound = e.kind() { 22 | eprintln!("`npm` was not found in your system. Please, install NodeJS / NPM to build the admin panel."); 23 | eprintln!("See: https://nodejs.dev/en/download/"); 24 | } else { 25 | eprintln!( 26 | "There was an error when building the admin panel with NodeJS / NPM: {e}" 27 | ); 28 | } 29 | } 30 | } 31 | 32 | // Tell Cargo that if the given file changes, to rerun this build script. 33 | println!("cargo:rerun-if-changed=client/src/*"); 34 | println!("cargo:rerun-if-changed=client/public/*"); 35 | println!("cargo:rerun-if-changed=client/index.html"); 36 | println!("cargo:rerun-if-changed=client/vite.config.js"); 37 | } 38 | -------------------------------------------------------------------------------- /crates/panel/client/.gitignore: -------------------------------------------------------------------------------- 1 | package-lock.json 2 | node_modules 3 | 4 | # Keep the dist folder to avoid errors when the client is not built. 5 | dist/* 6 | !dist/.gitkeep 7 | -------------------------------------------------------------------------------- /crates/panel/client/dist/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/panel/client/dist/.gitkeep -------------------------------------------------------------------------------- /crates/panel/client/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | Wasm Workers Server 6 | 7 | 8 | 9 | 10 | 11 |
12 | 13 | 14 | 15 | 16 | -------------------------------------------------------------------------------- /crates/panel/client/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wws-panel", 3 | "version": "1.0.0", 4 | "main": "index.js", 5 | "private": "true", 6 | "scripts": { 7 | "dev": "vite", 8 | "build": "vite build", 9 | "preview": "vite preview" 10 | }, 11 | "dependencies": { 12 | "@cds/city": "^1.1.0", 13 | "@cds/core": "^6.4.2", 14 | "@cds/react": "^6.4.2", 15 | "react-router-dom": "^6.12.0" 16 | }, 17 | "devDependencies": { 18 | "@vitejs/plugin-react": "^4.0.0", 19 | "sass": "^1.62.1", 20 | "vite": "^4.3.9" 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/panel/client/public/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/panel/client/public/.gitkeep -------------------------------------------------------------------------------- /crates/panel/client/src/app.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import Header from './components/header'; 5 | import Sidebar from './components/sidebar'; 6 | import Content from './components/content'; 7 | import { Outlet } from 'react-router-dom'; 8 | 9 | function App() { 10 | return ( 11 |
12 |
13 |
14 | 15 |
16 | 17 | 18 | 19 |
20 |
21 |
22 | ) 23 | } 24 | 25 | export default App 26 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/content.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import "./content.scss"; 5 | 6 | const Content = ({ children }) => ( 7 |
8 | {children} 9 |
10 | ); 11 | 12 | export default Content; 13 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/content.scss: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | .content { 5 | &>*:first-child { 6 | margin-top: 0; 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/header.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import "./header.scss"; 5 | 6 | const Header = () => ( 7 |
8 | Wasm Workers Server 9 |
10 | ) 11 | 12 | export default Header; 13 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/header.scss: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | header.header { 5 | background: var(--cds-global-color-blue-1000); 6 | color: var(--cds-global-color-gray-0); 7 | } 8 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/sidebar.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { CdsNavigation, CdsNavigationItem } from "@cds/react/navigation"; 5 | import { CdsIcon } from "@cds/react/icon"; 6 | import { ClarityIcons, cogIcon, cogIconName, fileIcon, fileIconName, homeIcon, homeIconName } from '@cds/core/icon'; 7 | import { NavLink } from "react-router-dom"; 8 | 9 | ClarityIcons.addIcons(cogIcon, fileIcon, homeIcon); 10 | 11 | import "./sidebar.scss"; 12 | 13 | const items = [ 14 | { 15 | name: "Server", 16 | url: "/_panel/", 17 | shape: homeIconName, 18 | }, 19 | { 20 | name: "Workers", 21 | url: "/_panel/workers", 22 | shape: cogIconName, 23 | } 24 | ]; 25 | 26 | // Main submenu 27 | const Sidebar = () => ( 28 |
29 | 45 |
46 | ); 47 | 48 | export default Sidebar; 49 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/sidebar.scss: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | .sidebar { 5 | display: flex; 6 | flex-direction: column; 7 | // 71px from the header 8 | min-height: calc(100vh - 71px); 9 | position: relative; 10 | width: 12rem; 11 | 12 | // Add a border with after due to collision with 13 | // the nav items. 14 | &:after { 15 | content: ""; 16 | background-color: var(--cds-alias-status-disabled-tint); 17 | height: 100%; 18 | width: 1px; 19 | position: absolute; 20 | right: -1px; 21 | } 22 | 23 | a { 24 | text-decoration: none; 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /crates/panel/client/src/components/workerCard.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { CdsCard } from "@cds/react/card"; 5 | import { CdsDivider } from "@cds/react/divider"; 6 | import { CdsIcon } from "@cds/react/icon"; 7 | import { CdsButton } from "@cds/react/button"; 8 | import { ClarityIcons, linkIcon, linkIconName, eyeIcon, eyeIconName } from '@cds/core/icon'; 9 | import { Link } from "react-router-dom"; 10 | 11 | ClarityIcons.addIcons(linkIcon, eyeIcon); 12 | 13 | const WorkerCard = ({ worker }) => { 14 | return 15 |
16 |

{worker.name}

17 | 18 |

19 | Endpoint: {worker.path} 20 |

21 |

22 | Filepath: {worker.filepath} 23 |

24 | 25 |
26 | 27 | 28 | Details 29 | 30 | 31 | 32 | 33 | View 34 | 35 | 36 |
37 |
38 |
39 | }; 40 | 41 | export default WorkerCard; 42 | -------------------------------------------------------------------------------- /crates/panel/client/src/main.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import React from 'react'; 5 | import ReactDOM from 'react-dom/client'; 6 | import { RouterProvider } from 'react-router-dom'; 7 | import router from "./router"; 8 | 9 | import './main.scss'; 10 | 11 | ReactDOM.createRoot(document.getElementById('app')).render( 12 | 13 | 14 | , 15 | ) 16 | -------------------------------------------------------------------------------- /crates/panel/client/src/main.scss: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | @import 'modern-normalize/modern-normalize.css'; 5 | @import '@cds/core/global.min.css'; 6 | @import '@cds/city/css/bundles/default.min.css'; 7 | @import '@cds/core/styles/theme.dark.min.css'; 8 | @import '@cds/core/table/table.min.css'; 9 | 10 | // Layout 11 | #app, 12 | .main-container { 13 | min-height: 100vh; 14 | } 15 | 16 | // Helper methods 17 | ul.clear { 18 | margin: 0; 19 | padding: 0; 20 | } 21 | -------------------------------------------------------------------------------- /crates/panel/client/src/router.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { 5 | Outlet, 6 | createBrowserRouter, 7 | } from "react-router-dom"; 8 | 9 | import App from "./app"; 10 | import Home from "./routes/home"; 11 | import Workers from "./routes/workers"; 12 | import Worker from "./routes/worker"; 13 | 14 | const router = createBrowserRouter([ 15 | { 16 | path: "/_panel/", 17 | element: , 18 | children: [ 19 | { 20 | index: true, 21 | element: , 22 | }, 23 | { 24 | path: "workers", 25 | element: , 26 | children: [ 27 | { 28 | index: true, 29 | element: 30 | }, 31 | { 32 | path: ":id", 33 | element: 34 | } 35 | ] 36 | }, 37 | ] 38 | }, 39 | ]); 40 | 41 | export default router; 42 | -------------------------------------------------------------------------------- /crates/panel/client/src/routes/workers.jsx: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { useEffect, useState } from 'react' 5 | import WorkerCard from "../components/workerCard"; 6 | import { CdsProgressCircle } from "@cds/react/progress-circle"; 7 | 8 | const Workers = () => { 9 | const [result, setResult] = useState(undefined); 10 | 11 | useEffect(() => { 12 | fetch("/_api/v0/workers") 13 | .then(res => res.json()) 14 | .then(json => setResult(json)); 15 | }, []); 16 | 17 | return <> 18 |

Workers

19 | {result === undefined ? ( 20 | 21 | ) : ( 22 |
23 | {result.map((p, i) => ( 24 | 25 | ))} 26 |
27 | )} 28 | 29 | } 30 | 31 | export default Workers; 32 | -------------------------------------------------------------------------------- /crates/panel/client/vite.config.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { defineConfig } from 'vite' 5 | import react from '@vitejs/plugin-react' 6 | 7 | // https://vitejs.dev/config/ 8 | export default defineConfig({ 9 | plugins: [react()], 10 | base: "/_panel/", 11 | server: { 12 | proxy: { 13 | '/_api': 'http://localhost:8080', 14 | } 15 | } 16 | }) 17 | -------------------------------------------------------------------------------- /crates/panel/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | pub mod panel; 2 | -------------------------------------------------------------------------------- /crates/panel/src/handlers/panel.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use actix_web::{ 5 | web::{self}, 6 | HttpResponse, Responder, 7 | }; 8 | use mime_guess::from_path; 9 | use rust_embed::RustEmbed; 10 | 11 | #[derive(RustEmbed)] 12 | #[folder = "client/dist/"] 13 | struct Asset; 14 | 15 | #[actix_web::get("/_panel{_:.*}")] 16 | pub async fn handle_static_panel(path: web::Path) -> impl Responder { 17 | let path = if path.is_empty() { 18 | "index.html" 19 | } else { 20 | path.as_str().strip_prefix('/').unwrap() 21 | }; 22 | 23 | let (content_type, content_data) = Asset::get(path) 24 | .map(|content| { 25 | ( 26 | from_path(path).first_or_octet_stream().to_string(), 27 | content.data.into_owned(), 28 | ) 29 | }) 30 | .unwrap_or_else(|| { 31 | let default_content = Asset::get("index.html").unwrap(); 32 | ( 33 | "text/html; charset=utf-8".to_string(), 34 | default_content.data.into_owned(), 35 | ) 36 | }); 37 | 38 | HttpResponse::Ok() 39 | .content_type(content_type) 40 | .body(content_data) 41 | } 42 | -------------------------------------------------------------------------------- /crates/panel/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use actix_web::web::ServiceConfig; 5 | 6 | mod handlers; 7 | 8 | /// Add the administration panel HTTP handlers to an existing 9 | /// Actix application. 10 | pub fn config_panel_handlers(cfg: &mut ServiceConfig) { 11 | cfg.service(handlers::panel::handle_static_panel); 12 | } 13 | -------------------------------------------------------------------------------- /crates/project/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-project" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | reqwest = { workspace = true } 11 | serde = { workspace = true } 12 | serde_json = { workspace = true } 13 | tokio = { workspace = true } 14 | toml = { workspace = true } 15 | wws-store = { workspace = true } 16 | url = "2.3.1" 17 | sha256 = "1.1.1" 18 | git2 = "0.18" 19 | # Not all platforms require OpenSSL 20 | openssl = { workspace = true, optional = true } 21 | 22 | [features] 23 | vendored-openssl = ["openssl/vendored"] 24 | 25 | [dev-dependencies] 26 | path-slash = { workspace = true } 27 | -------------------------------------------------------------------------------- /crates/project/README.md: -------------------------------------------------------------------------------- 1 | # Wasm Workers Server / Project crate 2 | 3 | The purpose of this create is to prepare the worker project before we proceed identifying the routes and preparing the individual workers. It's in charge of locating the project locally, pulling it from a supported remote and storing it in a place that it's accessible for `wws`. 4 | 5 | It also downloads the required runtimes to run the given project. 6 | -------------------------------------------------------------------------------- /crates/project/src/fetch.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::errors::Result; 5 | use crate::metadata::Checksum; 6 | use reqwest::header::USER_AGENT; 7 | 8 | /// The current wws version 9 | const VERSION: &str = env!("CARGO_PKG_VERSION"); 10 | 11 | /// Fetch the contents of a given file and validates it 12 | /// using the Sha256. 13 | pub async fn fetch>(file: T) -> Result> { 14 | let client = reqwest::Client::new(); 15 | let user_agent_value = format!("Wasm Workers Server/{VERSION}"); 16 | 17 | let body: Vec = client 18 | .get(file.as_ref()) 19 | .header(USER_AGENT, user_agent_value) 20 | .send() 21 | .await? 22 | .bytes() 23 | .await? 24 | .into(); 25 | 26 | Ok(body) 27 | } 28 | 29 | /// Fetch the contents of a given file and validates it 30 | /// using the Sha256. 31 | pub async fn fetch_and_validate>(file: T, checksum: &Checksum) -> Result> { 32 | let body: Vec = fetch(file).await?; 33 | checksum.validate(&body)?; 34 | 35 | Ok(body) 36 | } 37 | -------------------------------------------------------------------------------- /crates/project/src/options.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// Defines the different options to configure the project. 5 | /// Every type has their own options. 6 | #[derive(Default)] 7 | pub struct Options { 8 | /// Options for Git repositories 9 | pub git: Option, 10 | /// Options for local repositories 11 | pub local: Option, 12 | } 13 | 14 | /// For now, we don't have any particular option for this type. 15 | /// I'm keeping it as a placeholder 16 | #[derive(Default)] 17 | pub struct LocalOptions {} 18 | 19 | /// Defines a different reference when cloning the repository 20 | pub enum GitReference { 21 | /// Use a specific commit 22 | Commit(String), 23 | /// Use a specific tag 24 | Tag(String), 25 | /// Use a specific git branch 26 | Branch(String), 27 | } 28 | 29 | /// The different git options you can configure. 30 | #[derive(Default)] 31 | pub struct GitOptions { 32 | pub git_ref: Option, 33 | /// Change the directory to run the workers 34 | pub folder: Option, 35 | } 36 | -------------------------------------------------------------------------------- /crates/project/src/types/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod git; 5 | -------------------------------------------------------------------------------- /crates/project/tests/data/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/project/tests/data/index.js -------------------------------------------------------------------------------- /crates/router/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-router" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [lib] 10 | doctest = false 11 | 12 | [dependencies] 13 | wws-config = { workspace = true } 14 | wws-store = { workspace = true } 15 | wws-project = { workspace = true } 16 | wws-worker = { workspace = true } 17 | lazy_static = "1.4.0" 18 | regex = "1" 19 | 20 | # This commit fixes an issue with Walk::not, and is not yet released 21 | wax = { git = "https://github.com/olson-sean-k/wax.git", rev = "6d66a10" } 22 | 23 | [dev-dependencies] 24 | path-slash = { workspace = true } 25 | -------------------------------------------------------------------------------- /crates/router/tests/data/files/_home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/_home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/_index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/_index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/_internal/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/_internal/index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/_index/home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/_index/home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/_index/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/_index/index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/index/home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/index/home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/index/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/index/index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/index/public/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/index/public/index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/examples/public.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/examples/public.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/index.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/public.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/public.js -------------------------------------------------------------------------------- /crates/router/tests/data/files/public/home.ext: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/public/home.ext -------------------------------------------------------------------------------- /crates/router/tests/data/files/public/index.js: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/crates/router/tests/data/files/public/index.js -------------------------------------------------------------------------------- /crates/runtimes/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-runtimes" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | serde = { workspace = true } 11 | serde_json = { workspace = true } 12 | wasmtime-wasi = { workspace = true } 13 | wws-config = { workspace = true } 14 | wws-store = { workspace = true } 15 | wws-project = { workspace = true } 16 | -------------------------------------------------------------------------------- /crates/runtimes/src/errors.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub type Result = std::result::Result; 5 | 6 | #[derive(Debug)] 7 | pub enum RuntimeError { 8 | CannotReadModule, 9 | InvalidExtension { extension: Option }, 10 | InvalidWrapper, 11 | IOError(std::io::Error), 12 | MissingRuntime { extension: String }, 13 | StoreError(wws_store::errors::StoreError), 14 | WasiContextError { error: String }, 15 | WasiError(Option), 16 | } 17 | 18 | impl From for RuntimeError { 19 | fn from(error: wws_store::errors::StoreError) -> Self { 20 | RuntimeError::StoreError(error) 21 | } 22 | } 23 | 24 | impl From for RuntimeError { 25 | fn from(_error: std::string::FromUtf8Error) -> Self { 26 | RuntimeError::InvalidWrapper 27 | } 28 | } 29 | 30 | impl From for RuntimeError { 31 | fn from(error: std::io::Error) -> Self { 32 | RuntimeError::IOError(error) 33 | } 34 | } 35 | 36 | impl From for RuntimeError { 37 | fn from(error: wasmtime_wasi::Error) -> Self { 38 | RuntimeError::WasiError(Some(error)) 39 | } 40 | } 41 | -------------------------------------------------------------------------------- /crates/runtimes/src/modules/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub(crate) mod external; 5 | pub(crate) mod javascript; 6 | pub(crate) mod native; 7 | -------------------------------------------------------------------------------- /crates/runtimes/src/modules/native.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::errors::Result; 5 | use crate::runtime::Runtime; 6 | 7 | use std::{fs, path::PathBuf}; 8 | 9 | pub struct NativeRuntime { 10 | /// Path of the given module 11 | path: PathBuf, 12 | } 13 | 14 | impl NativeRuntime { 15 | /// Initializes the given runtime 16 | pub fn new(path: PathBuf) -> Self { 17 | Self { path } 18 | } 19 | } 20 | 21 | impl Runtime for NativeRuntime { 22 | /// Returns a reference to the Wasm module that should 23 | /// run this worker. It can be a custom (native) or a 24 | /// shared module (others). 25 | fn module_bytes(&self) -> Result> { 26 | fs::read(&self.path).map_err(|_| crate::errors::RuntimeError::CannotReadModule) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /crates/server/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-server" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | actix-web = { workspace = true } 11 | wws-api-manage = { workspace = true } 12 | wws-data-kv = { workspace = true } 13 | wws-router = { workspace = true } 14 | wws-worker = { workspace = true } 15 | wws-panel = { workspace = true } 16 | actix-files = "0.6.2" 17 | -------------------------------------------------------------------------------- /crates/server/src/errors.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub type Result = std::result::Result; 5 | 6 | #[derive(Debug)] 7 | pub enum ServeError { 8 | InitializeServerError, 9 | } 10 | 11 | impl std::error::Error for ServeError {} 12 | 13 | impl std::fmt::Display for ServeError { 14 | fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { 15 | match self { 16 | ServeError::InitializeServerError => write!(f, "Error initializing server"), 17 | } 18 | } 19 | } 20 | -------------------------------------------------------------------------------- /crates/server/src/handlers/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod assets; 5 | pub mod not_found; 6 | pub mod worker; 7 | -------------------------------------------------------------------------------- /crates/server/src/handlers/not_found.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::AppData; 5 | use actix_files::NamedFile; 6 | use actix_web::{web::Data, HttpRequest, HttpResponse}; 7 | 8 | /// This method tries to render a custom 404 error file from the static 9 | /// folder. If not, it will render an empty 404 10 | pub async fn handle_not_found(req: &HttpRequest) -> HttpResponse { 11 | let root_path = &req 12 | .app_data::>() 13 | .expect("error fetching app data") 14 | .root_path; 15 | let public_404_path = root_path.join("public").join("404.html"); 16 | 17 | if let Ok(file) = NamedFile::open_async(public_404_path).await { 18 | file.into_response(req) 19 | } else { 20 | HttpResponse::NotFound().body("") 21 | } 22 | } 23 | -------------------------------------------------------------------------------- /crates/store/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-store" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [dependencies] 10 | blake3 = "1.3.3" -------------------------------------------------------------------------------- /crates/worker/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wws-worker" 3 | version = { workspace = true } 4 | edition = { workspace = true } 5 | authors = { workspace = true } 6 | license = { workspace = true } 7 | repository = { workspace = true } 8 | 9 | [lib] 10 | doctest = false 11 | 12 | [dependencies] 13 | actix-web = { workspace = true } 14 | reqwest = { workspace = true } 15 | serde = { workspace = true } 16 | serde_json = { workspace = true } 17 | tokio = { workspace = true } 18 | toml = { workspace = true } 19 | wasmparser = { workspace = true } 20 | wasmtime = { workspace = true } 21 | wasmtime-wasi = { workspace = true } 22 | wasmtime-wasi-nn = { workspace = true } 23 | wasi-common = { workspace = true } 24 | wws-config = { workspace = true } 25 | wws-data-kv = { workspace = true } 26 | wws-runtimes = { workspace = true } 27 | # We didn't integrate components yet. For an initial binding implementation, 28 | # we will use the wit-bindgen-wasmtime crate maintained by the Fermyon team. 29 | wit-bindgen-wasmtime = { git = "https://github.com/fermyon/wit-bindgen-backport", rev = "598cd229bb43baceff9616d16930b8a5a3e79d79", features = ["async"] } 30 | base64 = "0.21.0" 31 | sha256 = "1.1.1" 32 | -------------------------------------------------------------------------------- /crates/worker/src/bindings/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod http; 5 | -------------------------------------------------------------------------------- /crates/worker/src/features/data.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::Deserialize; 5 | use wws_data_kv::KVConfigData; 6 | 7 | /// Configure a data plugin for the worker 8 | #[derive(Deserialize, Clone, Default)] 9 | pub struct ConfigData { 10 | /// Creates a Key/Value store associated to the given worker 11 | pub kv: Option, 12 | } 13 | -------------------------------------------------------------------------------- /crates/worker/src/features/folders.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::{Deserialize, Deserializer}; 5 | use std::path::PathBuf; 6 | 7 | /// A folder to mount in the worker 8 | #[derive(Deserialize, Clone, Default)] 9 | pub struct Folder { 10 | /// Local folder 11 | #[serde(deserialize_with = "deserialize_path", default)] 12 | pub from: PathBuf, 13 | /// Mount point 14 | pub to: String, 15 | } 16 | 17 | /// Deserialize a valid path for the given platform. This method checks and 18 | /// split the path by the different separators and join the final path 19 | /// using the current OS requirements. 20 | fn deserialize_path<'de, D>(deserializer: D) -> Result 21 | where 22 | D: Deserializer<'de>, 23 | { 24 | let result: Result = Deserialize::deserialize(deserializer); 25 | 26 | match result { 27 | Ok(value) => { 28 | let split = if value.contains('/') { 29 | // Unix separator 30 | value.split('/') 31 | } else { 32 | // Windows separator 33 | value.split('\\') 34 | }; 35 | 36 | Ok(split.fold(PathBuf::new(), |mut acc, el| { 37 | acc.push(el); 38 | acc 39 | })) 40 | } 41 | Err(err) => Err(err), 42 | } 43 | } 44 | -------------------------------------------------------------------------------- /crates/worker/src/features/http_requests.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use serde::Deserialize; 5 | 6 | #[derive(Deserialize, Clone)] 7 | #[serde(default)] 8 | pub struct HttpRequestsConfig { 9 | /// List of allowed domains to perform the calls 10 | pub allowed_hosts: Vec, 11 | /// List of allowed HTTP methods for the worker 12 | pub allowed_methods: Vec, 13 | /// Allow HTTP requests 14 | pub allow_http: bool, 15 | } 16 | 17 | impl Default for HttpRequestsConfig { 18 | fn default() -> Self { 19 | Self { 20 | allowed_hosts: Vec::default(), 21 | allowed_methods: Vec::from([ 22 | String::from("GET"), 23 | String::from("POST"), 24 | String::from("PUT"), 25 | String::from("PATCH"), 26 | String::from("DELETE"), 27 | ]), 28 | allow_http: false, 29 | } 30 | } 31 | } 32 | -------------------------------------------------------------------------------- /crates/worker/src/features/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod data; 5 | pub mod folders; 6 | pub mod http_requests; 7 | pub mod wasi_nn; 8 | -------------------------------------------------------------------------------- /docs/.gitignore: -------------------------------------------------------------------------------- 1 | # Dependencies 2 | /node_modules 3 | 4 | # Production 5 | /build 6 | 7 | # Generated files 8 | .docusaurus 9 | .cache-loader 10 | 11 | # Misc 12 | .DS_Store 13 | .env.local 14 | .env.development.local 15 | .env.test.local 16 | .env.production.local 17 | 18 | npm-debug.log* 19 | yarn-debug.log* 20 | yarn-error.log* 21 | -------------------------------------------------------------------------------- /docs/README.md: -------------------------------------------------------------------------------- 1 | # Documentation 2 | 3 | The Wasm Workers Server documentation is developed with [Docusaurus](https://docusaurus.io/). 4 | 5 | ## Edit the documentation 6 | 7 | ### Prerequisites 8 | 9 | You will need: 10 | 11 | - [NodeJS](https://nodejs.org/) 12 | 13 | ### Development 14 | 15 | To start the documentation development server, run these commands: 16 | 17 | ```sh 18 | cd docs && \ 19 | npm install && \ 20 | npm start 21 | ``` 22 | 23 | Then, you can access the documentation site at . -------------------------------------------------------------------------------- /docs/babel.config.js: -------------------------------------------------------------------------------- 1 | module.exports = { 2 | presets: [require.resolve('@docusaurus/core/lib/babel/preset')], 3 | }; 4 | -------------------------------------------------------------------------------- /docs/docs/containers.md: -------------------------------------------------------------------------------- 1 | --- 2 | sidebar_position: 5 3 | --- 4 | 5 | # Running in a container 6 | 7 | For convenience we have published a container image that contains Wasm Workers Server. It is available at `ghcr.io/vmware-labs/wws:latest`. Any container that runs it will get the `wws` binary, running and: 8 | 9 | - Looking for workers in the `/app` folder 10 | - Listening on `0.0.0.0:8080` inside the container 11 | 12 | The image is built from `scratch`. It only includes the `wws` binary. The container supports multiple architectures: `linux/amd64` and `linux/arm64` platforms. The image size is just `27MiB`. 13 | 14 | ## Running a local container 15 | 16 | A typical one-liner to run a local container for development purposes would look like: 17 | 18 | ```bash 19 | docker run -v /path/to/workers/on/host:/app -p 8080:8080 \ 20 | ghcr.io/vmware-labs/wws:latest 21 | ``` 22 | 23 | ## Other usages 24 | 25 | Wasm Workers Server is stateless as far as the loaded handers are stateless (i.e. when they don't use the [Key / Value store](./features/key-value.md)). This makes the image very useful if you want to setup your own auto-scaling deployment. 26 | 27 | -------------------------------------------------------------------------------- /docs/docs/features/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Features", 3 | "position": 2, 4 | "link": { 5 | "type": "doc", 6 | "id": "all" 7 | } 8 | } 9 | -------------------------------------------------------------------------------- /docs/docs/get-started/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Wasm Workers Server", 3 | "position": 1, 4 | "collapsed": false, 5 | "collapsible": false 6 | } -------------------------------------------------------------------------------- /docs/docs/languages/_category_.json: -------------------------------------------------------------------------------- 1 | { 2 | "label": "Supported languages", 3 | "position": 3, 4 | "collapsed": false, 5 | "collapsible": false, 6 | "link": { 7 | "type": "doc", 8 | "id": "introduction" 9 | } 10 | } -------------------------------------------------------------------------------- /docs/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "docs", 3 | "version": "0.0.0", 4 | "private": true, 5 | "scripts": { 6 | "clean": "rm -fr ./build", 7 | "docusaurus": "docusaurus", 8 | "start": "docusaurus start", 9 | "build": "docusaurus build", 10 | "swizzle": "docusaurus swizzle", 11 | "deploy": "docusaurus deploy", 12 | "clear": "docusaurus clear", 13 | "serve": "docusaurus serve", 14 | "write-translations": "docusaurus write-translations", 15 | "write-heading-ids": "docusaurus write-heading-ids", 16 | "publish": "npm run clean && npm run build && npx wrangler pages deploy ./build" 17 | }, 18 | "dependencies": { 19 | "@docusaurus/core": "=2.4.1", 20 | "@docusaurus/preset-classic": "=2.4.1", 21 | "@mdx-js/react": "^1.6.22", 22 | "clsx": "^1.2.1", 23 | "got": ">=11.8.5", 24 | "follow-redirects": ">=1.15.4", 25 | "prism-react-renderer": "^1.3.5", 26 | "react": "^17.0.2", 27 | "react-dom": "^17.0.2", 28 | "trim": ">=0.0.3" 29 | }, 30 | "devDependencies": { 31 | "@docusaurus/module-type-aliases": "=2.4.1" 32 | }, 33 | "browserslist": { 34 | "production": [ 35 | ">0.5%", 36 | "not dead", 37 | "not op_mini all" 38 | ], 39 | "development": [ 40 | "last 1 chrome version", 41 | "last 1 firefox version", 42 | "last 1 safari version" 43 | ] 44 | }, 45 | "engines": { 46 | "node": ">=16.14" 47 | } 48 | } 49 | -------------------------------------------------------------------------------- /docs/sidebars.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Creating a sidebar enables you to: 3 | - create an ordered group of docs 4 | - render a sidebar for each doc of that group 5 | - provide next/previous navigation 6 | 7 | The sidebars can be generated from the filesystem, or explicitly defined here. 8 | 9 | Create as many sidebars as you want. 10 | */ 11 | 12 | // @ts-check 13 | 14 | /** @type {import('@docusaurus/plugin-content-docs').SidebarsConfig} */ 15 | const sidebars = { 16 | // By default, Docusaurus generates a sidebar from the docs folder structure 17 | tutorialSidebar: [{type: 'autogenerated', dirName: '.'}], 18 | 19 | // But you can create a sidebar manually 20 | /* 21 | tutorialSidebar: [ 22 | 'intro', 23 | 'hello', 24 | { 25 | type: 'category', 26 | label: 'Tutorial', 27 | items: ['tutorial-basics/create-a-document'], 28 | }, 29 | ], 30 | */ 31 | }; 32 | 33 | module.exports = sidebars; 34 | -------------------------------------------------------------------------------- /docs/src/components/HomepageFeatures/styles.module.css: -------------------------------------------------------------------------------- 1 | .features { 2 | display: flex; 3 | align-items: center; 4 | padding: 2rem 0; 5 | width: 100%; 6 | } 7 | 8 | .featureEmoji { 9 | font-size: 4rem; 10 | } 11 | 12 | .featureDescription { 13 | font-size: 1.2rem; 14 | } 15 | -------------------------------------------------------------------------------- /docs/src/pages/index.module.css: -------------------------------------------------------------------------------- 1 | /** 2 | * CSS files with the .module.css suffix will be treated as CSS modules 3 | * and scoped locally. 4 | */ 5 | 6 | .heroBanner { 7 | padding: 4rem 0; 8 | text-align: center; 9 | position: relative; 10 | overflow: hidden; 11 | } 12 | 13 | @media screen and (max-width: 996px) { 14 | .heroBanner { 15 | padding: 2rem; 16 | } 17 | } 18 | 19 | .buttons { 20 | display: flex; 21 | align-items: center; 22 | justify-content: center; 23 | } 24 | 25 | .codeHero { 26 | margin: 0 auto 4rem; 27 | max-width: 860px; 28 | padding: 1rem; 29 | } 30 | -------------------------------------------------------------------------------- /docs/static/.nojekyll: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/docs/static/.nojekyll -------------------------------------------------------------------------------- /docs/static/_redirects: -------------------------------------------------------------------------------- 1 | /install https://raw.githubusercontent.com/vmware-labs/wasm-workers-server/main/install.sh 307 2 | /quickstart /docs/get-started/quickstart 301 3 | /examples https://github.com/vmware-labs/wasm-workers-server/tree/main/examples 301 4 | /docs/intro /docs/get-started/introduction 301 5 | /docs/intro/ /docs/get-started/introduction 301 6 | /docs/start /docs/get-started/quickstart 301 7 | /docs/start/ /docs/get-started/quickstart 301 8 | /docs/how-it-works /docs/get-started/how-it-works 301 9 | /docs/how-it-works/ /docs/get-started/how-it-works 301 10 | /docs/category/features /docs/features/all/ 301 11 | /docs/category/features/ /docs/features/all/ 301 12 | /docs/tutorials/javascript-workers /docs/languages/javascript 301 13 | /docs/tutorials/javascript-workers/ /docs/languages/javascript 301 14 | /docs/tutorials/rust-workers /docs/languages/rust 301 15 | /docs/tutorials/rust-workers/ /docs/languages/rust 301 16 | -------------------------------------------------------------------------------- /docs/static/img/docs/features/wasi-nn.webp: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/docs/static/img/docs/features/wasi-nn.webp -------------------------------------------------------------------------------- /docs/static/img/languages/js.svg: -------------------------------------------------------------------------------- 1 | 2 | -------------------------------------------------------------------------------- /docs/static/img/languages/zig.svg: -------------------------------------------------------------------------------- 1 | -------------------------------------------------------------------------------- /examples/Makefile: -------------------------------------------------------------------------------- 1 | SUBDIRS = rust-basic rust-fetch rust-kv rust-wasi-nn rust-wasi-nn-preload rust-pdf-create 2 | COMPONENTS = components/rust-basic components/rust-kv 3 | 4 | all: $(SUBDIRS) rust-params $(COMPONENTS) components/rust-params 5 | 6 | .PHONY: $(SUBDIRS) rust-params $(COMPONENTS) components/rust-params js-hono 7 | 8 | $(SUBDIRS): 9 | cd $@ && \ 10 | cargo build --target wasm32-wasi --release && \ 11 | cp target/wasm32-wasi/release/$@.wasm ./$@.wasm 12 | 13 | rust-params: 14 | cd $@ && \ 15 | cargo build --target wasm32-wasi --release && \ 16 | cp target/wasm32-wasi/release/$@.wasm "./[id].wasm" 17 | 18 | js-hono: 19 | cd $@/src && \ 20 | npm install && npm run build 21 | 22 | $(COMPONENTS): 23 | mkdir -p $@ 24 | make $(@:components/%=%) 25 | cp $(@:components/%=%)/$(@:components/%=%).toml $@/ 26 | wasm-tools component new $(@:components/%=%)/$(@:components/%=%).wasm \ 27 | --adapt wasi_snapshot_preview1=components/wasi-component-adapter/wasi_snapshot_preview1-command.wasm \ 28 | -o $@/$(@:components/%=%).wasm 29 | 30 | components/rust-params: 31 | mkdir -p $@ 32 | make rust-params 33 | wasm-tools component new rust-params/[id].wasm \ 34 | --adapt wasi_snapshot_preview1=components/wasi-component-adapter/wasi_snapshot_preview1-command.wasm \ 35 | -o $@/[id].wasm 36 | -------------------------------------------------------------------------------- /examples/README.md: -------------------------------------------------------------------------------- 1 | # Wasm Workers Server examples 2 | 3 | This folder includes several workers examples. They are written in different languages and showcases all the features from Wasm Workers Server. 4 | 5 | Every example includes a `README.md` file with all the instructions. 6 | 7 | ## Documentation 8 | 9 | * [Quickstart](https://workers.wasmlabs.dev/docs/get-started/quickstart) 10 | * [Features](https://workers.wasmlabs.dev/docs/category/features) 11 | 12 | ### Language resources 13 | 14 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 15 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 16 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 17 | * [Ruby documentation](https://workers.wasmlabs.dev/docs/languages/ruby) 18 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 19 | * [Zig documentation](https://workers.wasmlabs.dev/docs/languages/zig) 20 | -------------------------------------------------------------------------------- /examples/components/.gitignore: -------------------------------------------------------------------------------- 1 | /rust-* -------------------------------------------------------------------------------- /examples/components/README.md: -------------------------------------------------------------------------------- 1 | # Component model examples 2 | 3 | This directory contains core module examples found in the parent 4 | directory, adapted with the 5 | [`wasi-component-adapter`](./wasi-component-adapter/README.md) so that they are 6 | converted to WebAssembly components. 7 | -------------------------------------------------------------------------------- /examples/components/wasi-component-adapter/wasi_snapshot_preview1-command.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/components/wasi-component-adapter/wasi_snapshot_preview1-command.wasm -------------------------------------------------------------------------------- /examples/components/wasi-component-adapter/wasi_snapshot_preview1-reactor.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/components/wasi-component-adapter/wasi_snapshot_preview1-reactor.wasm -------------------------------------------------------------------------------- /examples/containers/.gitignore: -------------------------------------------------------------------------------- 1 | /dist -------------------------------------------------------------------------------- /examples/containers/apps-src/tmp/file.txt: -------------------------------------------------------------------------------- 1 | Some contents 2 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/.gitignore: -------------------------------------------------------------------------------- 1 | *.wasm -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vmware-labs/docker-wasm 2 | 3 | go 1.20 4 | 5 | require github.com/vmware-labs/wasm-workers-server v1.4.0 6 | 7 | require ( 8 | github.com/tidwall/gjson v1.14.4 // indirect 9 | github.com/tidwall/match v1.1.1 // indirect 10 | github.com/tidwall/pretty v1.2.1 // indirect 11 | github.com/tidwall/sjson v1.2.5 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | github.com/vmware-labs/wasm-workers-server v1.4.0 h1:dlc0eWc3TdijQ6RxX3Mt5OLPazO/Trmk4mqDt68eDkI= 12 | github.com/vmware-labs/wasm-workers-server v1.4.0/go.mod h1:cigUhoitjUTLsUzR4+q0cz2FymdvJtfrfIS2hYAj69c= 13 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/user-generation-go.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-go" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/gjson/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/gjson/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/gjson/logo.png -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/match/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/match/README.md: -------------------------------------------------------------------------------- 1 | # Match 2 | 3 | [![GoDoc](https://godoc.org/github.com/tidwall/match?status.svg)](https://godoc.org/github.com/tidwall/match) 4 | 5 | Match is a very simple pattern matcher where '*' matches on any 6 | number characters and '?' matches on any one character. 7 | 8 | ## Installing 9 | 10 | ``` 11 | go get -u github.com/tidwall/match 12 | ``` 13 | 14 | ## Example 15 | 16 | ```go 17 | match.Match("hello", "*llo") 18 | match.Match("jello", "?ello") 19 | match.Match("hello", "h*o") 20 | ``` 21 | 22 | 23 | ## Contact 24 | 25 | Josh Baker [@tidwall](http://twitter.com/tidwall) 26 | 27 | ## License 28 | 29 | Redcon source code is available under the MIT [License](/LICENSE). 30 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/pretty/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2017 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/sjson/LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2016 Josh Baker 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy of 6 | this software and associated documentation files (the "Software"), to deal in 7 | the Software without restriction, including without limitation the rights to 8 | use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of 9 | the Software, and to permit persons to whom the Software is furnished to do so, 10 | subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS 17 | FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR 18 | COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER 19 | IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN 20 | CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 21 | 22 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/sjson/logo.png: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/containers/apps-src/user-generation-go/vendor/github.com/tidwall/sjson/logo.png -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/vmware-labs/wasm-workers-server/NOTICE: -------------------------------------------------------------------------------- 1 | Copyright 2022 VMware, Inc. 2 | 3 | This product is licensed to you under the Apache License, V2.0 (the "License"). You may not use this product except in compliance with the License. 4 | 5 | This product may include a number of subcomponents with separate copyright notices and license terms. Your use of these subcomponents is subject to the terms and conditions of the subcomponent's license, as noted in the LICENSE file. -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/github.com/vmware-labs/wasm-workers-server/kits/go/worker/doc.go: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * === Go support for WASM Workers Server === 4 | * 5 | * This package provides a simple way to write WASM workers in Go. It uses the gjson, sjson libraries instead 6 | * of Go's standard encoding/json package due to the following reasons: 7 | * -- as of writing this file, the default Go compiler does not support the WASI backend, 8 | * -- TinyGo (which does support WASI) does not support reflection and hence, we need to rely on a JSON library 9 | * that does not use reflection 10 | * 11 | */ 12 | 13 | package worker 14 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-go/vendor/modules.txt: -------------------------------------------------------------------------------- 1 | # github.com/tidwall/gjson v1.14.4 2 | ## explicit; go 1.12 3 | github.com/tidwall/gjson 4 | # github.com/tidwall/match v1.1.1 5 | ## explicit; go 1.15 6 | github.com/tidwall/match 7 | # github.com/tidwall/pretty v1.2.1 8 | ## explicit; go 1.16 9 | github.com/tidwall/pretty 10 | # github.com/tidwall/sjson v1.2.5 11 | ## explicit; go 1.14 12 | github.com/tidwall/sjson 13 | # github.com/vmware-labs/wasm-workers-server v1.4.0 14 | ## explicit; go 1.20 15 | github.com/vmware-labs/wasm-workers-server/kits/go/worker 16 | github.com/vmware-labs/wasm-workers-server/kits/go/worker/bindings 17 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-js/user-generation-js.js: -------------------------------------------------------------------------------- 1 | const setCache = (key, data) => Cache.set(key, data); 2 | const getCache = key => Cache.get(key); 3 | 4 | const reply = async (request) => { 5 | try { 6 | let res = await fetch("https://random-data-api.com/api/v2/users"); 7 | let res_json = await res.json(); 8 | 9 | let generated_users_counter = getCache("generated_users_counter"); 10 | if (!generated_users_counter) { 11 | generated_users_counter = 1; 12 | } else { 13 | generated_users_counter = parseInt(generated_users_counter, 10) + 1; 14 | } 15 | setCache("generated_users_counter", generated_users_counter.toString()); 16 | 17 | return new Response( 18 | JSON.stringify({ 19 | "user": { 20 | "first_name": res_json.first_name, 21 | "last_name": res_json.last_name, 22 | "username": res_json.username, 23 | "email": res_json.email 24 | }, 25 | "generated_users": generated_users_counter 26 | }), 27 | { 28 | "headers": { 29 | "x-generated-by": "wasm-workers-server" 30 | } 31 | } 32 | ); 33 | } catch (e) { 34 | return new Response(JSON.stringify({ "error": e.toString() }), { "status": 500 }); 35 | } 36 | } 37 | 38 | // Subscribe to the Fetch event 39 | addEventListener("fetch", event => { 40 | return event.respondWith(reply(event.request)); 41 | }); 42 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-js/user-generation-js.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-js" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] 15 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-python/index.py: -------------------------------------------------------------------------------- 1 | import json 2 | from collections import namedtuple 3 | 4 | class User: 5 | def __init__(self, first_name, last_name, username, email): 6 | self.first_name, self.last_name, self.username, self.email = first_name, last_name, username, email 7 | 8 | @staticmethod 9 | def from_json(dict): 10 | return User(dict['first_name'], 11 | dict['last_name'], 12 | dict['username'], 13 | dict['email']) 14 | 15 | def worker(request): 16 | sample_json = """{ 17 | "first_name": "Tracie", 18 | "last_name": "Schroeder", 19 | "username": "tracie.schroeder", 20 | "email": "tracie.schroeder@email.com", 21 | "password": "secret" 22 | }""" 23 | user = json.loads(sample_json, object_hook=User.from_json) 24 | return Response( 25 | json.dumps({ 26 | "user": user.__dict__, 27 | "some_file_contents": open("/tmp/file.txt").read(), 28 | }, separators=(',', ':')) 29 | ) 30 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-python/index.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-python" 2 | version = "1" 3 | 4 | [[folders]] 5 | from = "./tmp" 6 | to = "/tmp" -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-python/tmp: -------------------------------------------------------------------------------- 1 | ../tmp/ -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-ruby/index.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | def allowed_attributes 4 | [:first_name, :last_name, :username, :email] 5 | end 6 | 7 | def worker(req) 8 | sampleJson = <<-JSON 9 | { 10 | "first_name": "Tracie", 11 | "last_name": "Schroeder", 12 | "username": "tracie.schroeder", 13 | "email": "tracie.schroeder@email.com", 14 | "password": "secret" 15 | } 16 | JSON 17 | 18 | user = JSON.parse sampleJson, symbolize_names: true 19 | 20 | user_response = Hash.new 21 | allowed_attributes.each do |attribute| 22 | user_response[attribute] = user[attribute] 23 | end 24 | 25 | res = Response.new({ 26 | "user": user_response, 27 | "some_file_contents": File.read("/tmp/file.txt") 28 | }.to_json) 29 | res.headers["x-generated-by"] = "wasm-workers-server" 30 | res 31 | end 32 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-ruby/index.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-ruby" 2 | version = "1" 3 | 4 | [[folders]] 5 | from = "./tmp" 6 | to = "/tmp" -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-ruby/tmp: -------------------------------------------------------------------------------- 1 | ../tmp/ -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-rust/.cargo/config.toml: -------------------------------------------------------------------------------- 1 | [build] 2 | target = "wasm32-wasi" 3 | rustflags = ["-Cstrip=symbols", "-Copt-level=z", "-Cpanic=abort", "-Cdebuginfo=none"] -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-rust/.gitignore: -------------------------------------------------------------------------------- 1 | /target 2 | -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "user-generation-rust" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1" 8 | serde = { version = "1.0", features = ["derive"] } 9 | serde_json = "1.0.85" 10 | wasm-workers-rs = { git = "https://github.com/vmware-labs/wasm-workers-server/", tag = "v1.4.0" } -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-rust/rust-toolchain.toml: -------------------------------------------------------------------------------- 1 | [toolchain] 2 | targets = ["wasm32-wasi"] -------------------------------------------------------------------------------- /examples/containers/apps-src/user-generation-rust/user-generation-rust.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-rust" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] 15 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-go.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-go" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-js.js: -------------------------------------------------------------------------------- 1 | const setCache = (key, data) => Cache.set(key, data); 2 | const getCache = key => Cache.get(key); 3 | 4 | const reply = async (request) => { 5 | try { 6 | let res = await fetch("https://random-data-api.com/api/v2/users"); 7 | let res_json = await res.json(); 8 | 9 | let generated_users_counter = getCache("generated_users_counter"); 10 | if (!generated_users_counter) { 11 | generated_users_counter = 1; 12 | } else { 13 | generated_users_counter = parseInt(generated_users_counter, 10) + 1; 14 | } 15 | setCache("generated_users_counter", generated_users_counter.toString()); 16 | 17 | return new Response( 18 | JSON.stringify({ 19 | "user": { 20 | "first_name": res_json.first_name, 21 | "last_name": res_json.last_name, 22 | "username": res_json.username, 23 | "email": res_json.email 24 | }, 25 | "generated_users": generated_users_counter 26 | }), 27 | { 28 | "headers": { 29 | "x-generated-by": "wasm-workers-server" 30 | } 31 | } 32 | ); 33 | } catch (e) { 34 | return new Response(JSON.stringify({ "error": e.toString() }), { "status": 500 }); 35 | } 36 | } 37 | 38 | // Subscribe to the Fetch event 39 | addEventListener("fetch", event => { 40 | return event.respondWith(reply(event.request)); 41 | }); 42 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-js.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-js" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] 15 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-python/index.py: -------------------------------------------------------------------------------- 1 | import json 2 | from collections import namedtuple 3 | 4 | class User: 5 | def __init__(self, first_name, last_name, username, email): 6 | self.first_name, self.last_name, self.username, self.email = first_name, last_name, username, email 7 | 8 | @staticmethod 9 | def from_json(dict): 10 | return User(dict['first_name'], 11 | dict['last_name'], 12 | dict['username'], 13 | dict['email']) 14 | 15 | def worker(request): 16 | sample_json = """{ 17 | "first_name": "Tracie", 18 | "last_name": "Schroeder", 19 | "username": "tracie.schroeder", 20 | "email": "tracie.schroeder@email.com", 21 | "password": "secret" 22 | }""" 23 | user = json.loads(sample_json, object_hook=User.from_json) 24 | return Response( 25 | json.dumps({ 26 | "user": user.__dict__, 27 | "some_file_contents": open("/tmp/file.txt").read(), 28 | }, separators=(',', ':')) 29 | ) 30 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-python/index.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-python" 2 | version = "1" 3 | 4 | [[folders]] 5 | from = "./tmp" 6 | to = "/tmp" -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-python/tmp/file.txt: -------------------------------------------------------------------------------- 1 | Some content 2 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-ruby/index.rb: -------------------------------------------------------------------------------- 1 | require 'json' 2 | 3 | def allowed_attributes 4 | [:first_name, :last_name, :username, :email] 5 | end 6 | 7 | def worker(req) 8 | sampleJson = <<-JSON 9 | { 10 | "first_name": "Tracie", 11 | "last_name": "Schroeder", 12 | "username": "tracie.schroeder", 13 | "email": "tracie.schroeder@email.com", 14 | "password": "secret" 15 | } 16 | JSON 17 | 18 | user = JSON.parse sampleJson, symbolize_names: true 19 | 20 | user_response = Hash.new 21 | allowed_attributes.each do |attribute| 22 | user_response[attribute] = user[attribute] 23 | end 24 | 25 | res = Response.new({ 26 | "user": user_response, 27 | "some_file_contents": File.read("/tmp/file.txt") 28 | }.to_json) 29 | res.headers["x-generated-by"] = "wasm-workers-server" 30 | res 31 | end 32 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-ruby/index.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-ruby" 2 | version = "1" 3 | 4 | [[folders]] 5 | from = "./tmp" 6 | to = "/tmp" -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-ruby/tmp/file.txt: -------------------------------------------------------------------------------- 1 | Some content 2 | -------------------------------------------------------------------------------- /examples/containers/apps/root/user-generation-rust.toml: -------------------------------------------------------------------------------- 1 | name = "user-generation-rust" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "generated_users_counter" 7 | 8 | [[folders]] 9 | from = "./tmp" 10 | to = "/tmp" 11 | 12 | [features] 13 | [features.http_requests] 14 | allowed_hosts = ["random-data-api.com"] 15 | -------------------------------------------------------------------------------- /examples/containers/tmp/file.txt: -------------------------------------------------------------------------------- 1 | Mount contents coming from the Docker Host :) 2 | -------------------------------------------------------------------------------- /examples/go-basic/README.md: -------------------------------------------------------------------------------- 1 | # Go basic example 2 | 3 | Compile a Go worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Go](https://go.dev/) 14 | * [TinyGo](https://tinygo.org/getting-started/install/) 15 | 16 | ## Build 17 | 18 | ```shell-session 19 | tinygo build -o index.wasm -target wasi main.go 20 | ``` 21 | 22 | ## Run 23 | 24 | ```shell-session 25 | wws . 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 31 | * [Announcing Go support for Wasm Workers Server](https://wasmlabs.dev/articles/go-support-on-wasm-workers-server/) 32 | -------------------------------------------------------------------------------- /examples/go-basic/go.mod: -------------------------------------------------------------------------------- 1 | module go-basic 2 | 3 | go 1.20 4 | 5 | require github.com/vmware-labs/wasm-workers-server v1.3.0 6 | 7 | require ( 8 | github.com/tidwall/gjson v1.14.4 // indirect 9 | github.com/tidwall/match v1.1.1 // indirect 10 | github.com/tidwall/pretty v1.2.1 // indirect 11 | github.com/tidwall/sjson v1.2.5 // indirect 12 | ) 13 | -------------------------------------------------------------------------------- /examples/go-basic/go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | github.com/vmware-labs/wasm-workers-server v1.3.0 h1:Sm+Ycp327kRIaQIlWDXjKUITnCsaZaEqUDnPQZGPrKk= 12 | github.com/vmware-labs/wasm-workers-server v1.3.0/go.mod h1:cigUhoitjUTLsUzR4+q0cz2FymdvJtfrfIS2hYAj69c= 13 | -------------------------------------------------------------------------------- /examples/go-envs/README.md: -------------------------------------------------------------------------------- 1 | # Go environment variables example 2 | 3 | Compile a Go worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Go](https://go.dev/) 14 | * [TinyGo](https://tinygo.org/getting-started/install/) 15 | 16 | ## Build 17 | 18 | ```shell-session 19 | tinygo build -o envs.wasm -target wasi envs.go 20 | ``` 21 | 22 | ## Run 23 | 24 | ```shell-session 25 | wws . 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [Environment variables](https://workers.wasmlabs.dev/docs/features/environment-variables) 31 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 32 | * [Announcing Go support for Wasm Workers Server](https://wasmlabs.dev/articles/go-support-on-wasm-workers-server/) 33 | -------------------------------------------------------------------------------- /examples/go-envs/envs.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "os" 7 | 8 | "github.com/vmware-labs/wasm-workers-server/kits/go/worker" 9 | ) 10 | 11 | func main() { 12 | worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { 13 | body := fmt.Sprintf("The environment variable value is: %s", os.Getenv("MESSAGE")) 14 | 15 | w.Header().Set("x-generated-by", "wasm-workers-server") 16 | w.Write([]byte(body)) 17 | }) 18 | } 19 | -------------------------------------------------------------------------------- /examples/go-envs/envs.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello! This message comes from an environment variable" -------------------------------------------------------------------------------- /examples/go-fetch/README.md: -------------------------------------------------------------------------------- 1 | # Go fetch example 2 | 3 | Compile a Go worker to WebAssembly and run it in Wasm Workers Server. It performs a POST call to the [JSON placeholder API](https://jsonplaceholder.typicode.com/). 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Go](https://go.dev/) 14 | * [TinyGo](https://tinygo.org/getting-started/install/) 15 | 16 | ## Build 17 | 18 | ```shell-session 19 | tinygo build -o index.wasm -target wasi main.go 20 | ``` 21 | 22 | ## Run 23 | 24 | ```shell-session 25 | wws . 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 31 | * [Announcing Go support for Wasm Workers Server](https://wasmlabs.dev/articles/go-support-on-wasm-workers-server/) 32 | -------------------------------------------------------------------------------- /examples/go-fetch/go.mod: -------------------------------------------------------------------------------- 1 | module go-basic 2 | 3 | go 1.20 4 | 5 | require github.com/vmware-labs/wasm-workers-server v1.3.0 6 | 7 | require ( 8 | github.com/tidwall/gjson v1.14.4 // indirect 9 | github.com/tidwall/match v1.1.1 // indirect 10 | github.com/tidwall/pretty v1.2.1 // indirect 11 | github.com/tidwall/sjson v1.2.5 // indirect 12 | ) 13 | 14 | replace github.com/vmware-labs/wasm-workers-server => ../../ 15 | replace github.com/vmware-labs/wasm-workers-server/kits/go/worker/bindings => ../../kits/go/worker/bindings 16 | -------------------------------------------------------------------------------- /examples/go-fetch/go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | github.com/vmware-labs/wasm-workers-server v1.3.0 h1:Sm+Ycp327kRIaQIlWDXjKUITnCsaZaEqUDnPQZGPrKk= 12 | github.com/vmware-labs/wasm-workers-server v1.3.0/go.mod h1:cigUhoitjUTLsUzR4+q0cz2FymdvJtfrfIS2hYAj69c= 13 | -------------------------------------------------------------------------------- /examples/go-fetch/index.toml: -------------------------------------------------------------------------------- 1 | name = "go-fetch" 2 | version = "1" 3 | 4 | [features] 5 | [features.http_requests] 6 | allowed_hosts = ["jsonplaceholder.typicode.com"] 7 | -------------------------------------------------------------------------------- /examples/go-fetch/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "bytes" 5 | "io" 6 | "net/http" 7 | 8 | "github.com/vmware-labs/wasm-workers-server/kits/go/worker" 9 | 10 | "github.com/tidwall/sjson" 11 | ) 12 | 13 | func main() { 14 | worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { 15 | // Build a JSON body 16 | body, _ := sjson.Set("", "title", "New POST!") 17 | body, _ = sjson.Set(body, "body", "This is the body") 18 | body, _ = sjson.Set(body, "userId", 1) 19 | 20 | url := "https://jsonplaceholder.typicode.com/posts" 21 | 22 | // Create the request 23 | req, err := http.NewRequest(http.MethodPost, url, bytes.NewBufferString(body)) 24 | if err != nil { 25 | panic(err) 26 | } 27 | req.Header.Set("Content-Type", "application/json") 28 | 29 | res, err := worker.SendHttpRequest(req) 30 | if err != nil { 31 | panic(err) 32 | } 33 | 34 | // Read the response 35 | resBody, err := io.ReadAll(res.Body) 36 | if err != nil { 37 | panic(err) 38 | } 39 | res.Body.Close() 40 | 41 | w.Header().Set("x-generated-by", "wasm-workers-server") 42 | w.Write([]byte(resBody)) 43 | }) 44 | } 45 | -------------------------------------------------------------------------------- /examples/go-kv/README.md: -------------------------------------------------------------------------------- 1 | # Go Key / Value store example 2 | 3 | Compile a Go worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Go](https://go.dev/) 14 | * [TinyGo](https://tinygo.org/getting-started/install/) 15 | 16 | ## Build 17 | 18 | ```shell-session 19 | tinygo build -o counter.wasm -target wasi counter.go 20 | ``` 21 | 22 | ## Run 23 | 24 | ```shell-session 25 | wws . 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 31 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 32 | * [Announcing Go support for Wasm Workers Server](https://wasmlabs.dev/articles/go-support-on-wasm-workers-server/) 33 | -------------------------------------------------------------------------------- /examples/go-kv/counter.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | "strconv" 7 | 8 | "github.com/vmware-labs/wasm-workers-server/kits/go/worker" 9 | ) 10 | 11 | func main() { 12 | worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { 13 | cache, _ := r.Context().Value(worker.CacheKey).(map[string]string) 14 | 15 | var countNum uint32 16 | 17 | if count, ok := cache["counter"]; ok { 18 | n, _ := strconv.ParseUint(count, 10, 32) 19 | countNum = uint32(n) 20 | } 21 | 22 | body := fmt.Sprintf(""+ 23 | ""+ 24 | "

Key / Value store in Go

"+ 25 | "

Counter: %d

"+ 26 | "

This page was generated by a Wasm module built from Go.

"+ 27 | "", countNum) 28 | 29 | cache["counter"] = fmt.Sprintf("%d", countNum+1) 30 | 31 | w.Header().Set("x-generated-by", "wasm-workers-server") 32 | w.Write([]byte(body)) 33 | }) 34 | } 35 | -------------------------------------------------------------------------------- /examples/go-kv/counter.toml: -------------------------------------------------------------------------------- 1 | name = "counter" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "counter" -------------------------------------------------------------------------------- /examples/go-params/README.md: -------------------------------------------------------------------------------- 1 | # Go dynamic routes example 2 | 3 | Compile a Go worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Go](https://go.dev/) 14 | * [TinyGo](https://tinygo.org/getting-started/install/) 15 | 16 | ## Build 17 | 18 | ```shell-session 19 | tinygo build -o [id].wasm -target wasi main.go 20 | ``` 21 | 22 | ## Run 23 | 24 | ```shell-session 25 | wws . 26 | ``` 27 | 28 | ## Resources 29 | 30 | * [Dynamic routes](https://workers.wasmlabs.dev/docs/features/dynamic-routes) 31 | * [Go documentation](https://workers.wasmlabs.dev/docs/languages/go) 32 | * [Announcing Go support for Wasm Workers Server](https://wasmlabs.dev/articles/go-support-on-wasm-workers-server/) 33 | -------------------------------------------------------------------------------- /examples/go-params/main.go: -------------------------------------------------------------------------------- 1 | package main 2 | 3 | import ( 4 | "fmt" 5 | "net/http" 6 | 7 | "github.com/vmware-labs/wasm-workers-server/kits/go/worker" 8 | ) 9 | 10 | func main() { 11 | worker.ServeFunc(func(w http.ResponseWriter, r *http.Request) { 12 | params, _ := r.Context().Value(worker.ParamsKey).(map[string]string) 13 | id := "the value is not available" 14 | 15 | if val, ok := params["id"]; ok { 16 | id = val 17 | } 18 | 19 | body := fmt.Sprintf(""+ 20 | ""+ 21 | "Wasm Workers Server"+ 22 | ""+ 23 | ""+ 24 | ""+ 25 | ""+ 26 | ""+ 27 | ""+ 28 | "
"+ 29 | "

Hello from Wasm Workers Server 👋

"+ 30 | "

"+ 31 | "This is a dynamic route! The [id].wasm worker, written in Go, is replying this URL."+ 32 | "The id parameter value is: %s"+ 33 | "

"+ 34 | "

Read more about dynamic routes in the documentation

"+ 35 | "
"+ 36 | "", id) 37 | 38 | w.Header().Set("x-generated-by", "wasm-workers-server") 39 | w.Write([]byte(body)) 40 | }) 41 | } 42 | -------------------------------------------------------------------------------- /examples/go-params/public/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 1000px; 3 | } 4 | 5 | main { 6 | margin: 5rem 0; 7 | } 8 | 9 | h1, 10 | p { 11 | text-align: center; 12 | } 13 | 14 | h1 { 15 | margin-bottom: 2rem; 16 | } 17 | 18 | pre { 19 | font-size: .9rem; 20 | } 21 | 22 | pre>code { 23 | padding: 2rem; 24 | } 25 | 26 | p { 27 | margin-top: 2rem; 28 | } -------------------------------------------------------------------------------- /examples/js-async/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript async worker example 2 | 3 | Run a JavaScript that uses an async function in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-async" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-basic/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript basic example 2 | 3 | Run a JavaScript that uses `addEventListener` in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-basic" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-catchall/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript catch-all example 2 | 3 | This worker showcases how catch-all routes can be used by your workers. 4 | 5 | 6 | ## Prerequisites 7 | 8 | * Wasm Workers Server (wws): 9 | 10 | ```shell-session 11 | curl -fsSL https://workers.wasmlabs.dev/install | bash 12 | ``` 13 | 14 | ## Run 15 | 16 | ```shell-session 17 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-catchall" 18 | ``` 19 | 20 | ## Resources 21 | 22 | * [Catch-all routes](https://workers.wasmlabs.dev/docs/features/catch-all-routes) 23 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 24 | -------------------------------------------------------------------------------- /examples/js-fetch/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript fetch example 2 | 3 | Run a JavaScript that uses `fetch` in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-fetch" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-fetch/index.toml: -------------------------------------------------------------------------------- 1 | name = "js-fetch" 2 | version = "1" 3 | 4 | [features] 5 | [features.http_requests] 6 | allowed_hosts = ["jsonplaceholder.typicode.com"] 7 | -------------------------------------------------------------------------------- /examples/js-hono/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Hono example 2 | 3 | Run a JavaScript application that uses the [HonoJS framework](https://hono.dev/) in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-hono/dist" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-hono/src/index.js: -------------------------------------------------------------------------------- 1 | import { Hono } from 'hono' 2 | 3 | const app = new Hono() 4 | 5 | app.get('/', (c) => { 6 | return c.text('Hello from Hono running in Wasm Workers Server!') 7 | }); 8 | 9 | app.get('/hello', (c) => { 10 | return c.text('You can get a custom hello message by accessing /hello/your-name') 11 | }); 12 | 13 | app.get('/hello/:name', (c) => { 14 | const name = c.req.param('name'); 15 | return c.text(`Hello ${name}! This app is running in Wasm Workers Server`) 16 | }); 17 | 18 | app.notFound((c) => { 19 | return c.text('Awww! This page is missing', 404) 20 | }) 21 | 22 | export default app; 23 | -------------------------------------------------------------------------------- /examples/js-hono/src/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "wws-hono-sample", 3 | "version": "1.0.0", 4 | "description": "", 5 | "private": "true", 6 | "main": "index.js", 7 | "keywords": [], 8 | "author": "Wasm Labs ", 9 | "license": "Apache-2.0", 10 | "scripts": { 11 | "build": "esbuild index.js --bundle --minify --format=esm --outfile=../dist/[...app].js" 12 | }, 13 | "dependencies": { 14 | "esbuild": "^0.19.4", 15 | "hono": "^3.11.8" 16 | } 17 | } 18 | -------------------------------------------------------------------------------- /examples/js-json/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript environment variables example 2 | 3 | Run a JavaScript that returns a JSON output based on an environment variable. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-json" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Environment variables](https://workers.wasmlabs.dev/docs/features/environment-variables) 22 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 23 | -------------------------------------------------------------------------------- /examples/js-json/handler.js: -------------------------------------------------------------------------------- 1 | const JSON_CONTENT_TYPE = "application/json;charset=UTF-8"; 2 | 3 | /** 4 | * Builds a reply to the given request. In this case, 5 | * this reply method returns a JSON response 6 | */ 7 | const reply = (request) => { 8 | if (request.method != "GET") { 9 | // Don't allow other methods. 10 | // Here you can see how to return a custom status 11 | const errorResponse = JSON.stringify({ 12 | success: false, 13 | error: "Method not allowed" 14 | }); 15 | 16 | return new Response(errorResponse, { 17 | status: 405, 18 | headers: { 19 | "content-type": JSON_CONTENT_TYPE 20 | } 21 | }); 22 | } 23 | 24 | // Body response 25 | const body = JSON.stringify({ 26 | success: true, 27 | message: MESSAGE 28 | }, null, 2); 29 | 30 | // Build a new response 31 | let response = new Response(body, { 32 | headers: { 33 | "content-type": JSON_CONTENT_TYPE, 34 | "x-generated-by": "wasm-workers-server" 35 | } 36 | }); 37 | 38 | return response; 39 | } 40 | 41 | // Subscribe to the Fetch event 42 | addEventListener("fetch", event => { 43 | return event.respondWith(reply(event.request)); 44 | }); -------------------------------------------------------------------------------- /examples/js-json/handler.toml: -------------------------------------------------------------------------------- 1 | name = "test" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello 👋! This message comes from an environment variable" -------------------------------------------------------------------------------- /examples/js-json/public/robots.txt: -------------------------------------------------------------------------------- 1 | User-agent: * 2 | Disallow: / 3 | -------------------------------------------------------------------------------- /examples/js-modules/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript modules example 2 | 3 | Run a JavaScript that exports the application in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-modules" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-modules/index.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request 3 | */ 4 | export default { 5 | async fetch(request) { 6 | // Body response 7 | const body = ` 8 | 9 | Wasm Workers Server 10 | 11 | 12 | 13 | 22 | 23 | 24 |
25 |

Hello from Wasm Workers Server 👋

26 |
Replying to ${request.url}
27 |   Method: ${request.method}
28 |   User Agent: ${request.headers.get("user-agent")}
29 |   Payload: ${request.body || "-"}
30 |

31 | This page was generated by a JavaScript (module) file running in WebAssembly. 32 |

33 |
34 | `; 35 | 36 | // Build a new response 37 | let response = new Response(body); 38 | 39 | // Add a new header 40 | response.headers.set("x-generated-by", "wasm-workers-server"); 41 | 42 | return response; 43 | }, 44 | }; 45 | -------------------------------------------------------------------------------- /examples/js-params/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript dynamic routes example 2 | 3 | Run a JavaScript project that include several dynamic routes. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-params" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Dynamic routes](https://workers.wasmlabs.dev/docs/features/dynamic-routes) 22 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 23 | -------------------------------------------------------------------------------- /examples/js-params/[id].js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request 3 | */ 4 | const reply = (req) => { 5 | // Body response 6 | const body = ` 7 | 8 | Wasm Workers Server 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Hello from Wasm Workers Server 👋

17 |

18 | This is a dynamic route! The [id].js worker is replying this URL. 19 | The id parameter value is: ${req.params?.id} 20 |

21 |

Read more about dynamic routes in the documentation

22 |
23 | `; 24 | 25 | return new Response(body); 26 | } 27 | 28 | // Subscribe to the Fetch event 29 | addEventListener("fetch", event => { 30 | return event.respondWith(reply(event.request)); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/js-params/[id]/fixed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request 3 | */ 4 | const reply = (req) => { 5 | // Body response 6 | const body = ` 7 | 8 | Wasm Workers Server 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Hello from Wasm Workers Server 👋

17 |

18 | This is a dynamic route! The [id]/fixed.js worker is replying this URL. 19 | The id parameter value is: ${req.params?.id} 20 |

21 |

Read more about dynamic routes in the documentation

22 |
23 | `; 24 | 25 | return new Response(body); 26 | } 27 | 28 | // Subscribe to the Fetch event 29 | addEventListener("fetch", event => { 30 | return event.respondWith(reply(event.request)); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/js-params/fixed.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request 3 | */ 4 | const reply = () => { 5 | // Body response 6 | const body = ` 7 | 8 | Wasm Workers Server 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Hello from Wasm Workers Server 👋

17 |

18 | This is a fixed route. There isn't any parameter here. 19 |

20 |

Read more about dynamic routes in the documentation

21 |
22 | `; 23 | 24 | return new Response(body); 25 | } 26 | 27 | // Subscribe to the Fetch event 28 | addEventListener("fetch", event => { 29 | return event.respondWith(reply(event.request)); 30 | }); 31 | -------------------------------------------------------------------------------- /examples/js-params/public/main.css: -------------------------------------------------------------------------------- 1 | /* This is just a comment for testing purposes */ 2 | body { 3 | max-width: 1000px; 4 | } 5 | 6 | main { 7 | margin: 5rem 0; 8 | } 9 | 10 | h1, 11 | p { 12 | text-align: center; 13 | } 14 | 15 | h1 { 16 | margin-bottom: 2rem; 17 | } 18 | 19 | pre { 20 | font-size: .9rem; 21 | } 22 | 23 | pre>code { 24 | padding: 2rem; 25 | } 26 | 27 | p { 28 | margin-top: 2rem; 29 | } 30 | -------------------------------------------------------------------------------- /examples/js-params/sub/[id].js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request 3 | */ 4 | const reply = (req) => { 5 | // Body response 6 | const body = ` 7 | 8 | Wasm Workers Server 9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 |

Hello from Wasm Workers Server 👋

17 |

18 | This is a dynamic route! The sub/[id].js worker is replying this URL. 19 | The id parameter value is: ${req.params?.id} 20 |

21 |

Read more about dynamic routes in the documentation

22 |
23 | `; 24 | 25 | return new Response(body); 26 | } 27 | 28 | // Subscribe to the Fetch event 29 | addEventListener("fetch", event => { 30 | return event.respondWith(reply(event.request)); 31 | }); 32 | -------------------------------------------------------------------------------- /examples/js-redirect/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript redirect example 2 | 3 | Run a JavaScript that redirects users to a different URL via custom HTTP Headers and status. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-redirect" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 22 | -------------------------------------------------------------------------------- /examples/js-redirect/handler.js: -------------------------------------------------------------------------------- 1 | /** 2 | * Builds a reply to the given request. In this case, 3 | * this reply method returns a redirect 4 | */ 5 | const reply = (request) => { 6 | if (request.method != "GET") { 7 | // Don't allow other methods. 8 | // Here you can see how to return a custom status 9 | return new Response("Method not allowed", { 10 | status: 405, 11 | }); 12 | } 13 | 14 | // Build a redirect response 15 | let response = Response.redirect("https://example.com", 301); 16 | 17 | return response; 18 | } 19 | 20 | // Subscribe to the Fetch event 21 | addEventListener("fetch", event => { 22 | return event.respondWith(reply(event.request)); 23 | }); -------------------------------------------------------------------------------- /examples/js-tictactoe/README.md: -------------------------------------------------------------------------------- 1 | # JavaScript Tic Tac Toe example 2 | 3 | A complete Tic Tac Toe example in JavaScript. It uses the K/V store to save the information. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/js-tictactoe" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 22 | * [JavaScript documentation](https://workers.wasmlabs.dev/docs/languages/javascript) 23 | -------------------------------------------------------------------------------- /examples/js-tictactoe/handler.toml: -------------------------------------------------------------------------------- 1 | name = "tictactoe" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "tictactoe" 7 | -------------------------------------------------------------------------------- /examples/protomaps/.gitignore: -------------------------------------------------------------------------------- 1 | # Python cache 2 | __pycache__ 3 | 4 | # Ignore maps 5 | _maps/planet.pmtiles -------------------------------------------------------------------------------- /examples/protomaps/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217-1" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3-1/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "74d10132b0577a39e4ea30002d4605b7cdfb8f39abca327a45c8b313de7ea304" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3-1/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/protomaps/Dockerfile: -------------------------------------------------------------------------------- 1 | FROM bitnami/minideb:bullseye as builder 2 | 3 | # Download the map 4 | RUN install_packages curl 5 | RUN curl -kL --output /planet.pmtiles https://pub-9288c68512ed46eca46ddcade307709b.r2.dev/protomaps-sample-datasets/protomaps_vector_planet_odbl_z10.pmtiles 6 | 7 | FROM ghcr.io/vmware-labs/wws:preview 8 | 9 | COPY . /app 10 | COPY --from=builder /planet.pmtiles /app/_maps/ -------------------------------------------------------------------------------- /examples/protomaps/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: all build-image 2 | 3 | download-planet: 4 | curl -kL --output ./_maps/map.pmtiles \ 5 | https://pub-9288c68512ed46eca46ddcade307709b.r2.dev/protomaps-sample-datasets/protomaps_vector_planet_odbl_z10.pmtiles 6 | 7 | install: 8 | wws runtimes install 9 | 10 | run: 11 | wws . 12 | 13 | build-image: 14 | docker build -t wws-maps:latest . 15 | 16 | planet: download-planet install run 17 | all: install run 18 | -------------------------------------------------------------------------------- /examples/protomaps/[z]/[x]/[y]/index.py: -------------------------------------------------------------------------------- 1 | import sys 2 | sys.path.append("/src/libs") 3 | import os 4 | 5 | from reader import Reader 6 | 7 | # Provide the specific tile from the file 8 | def worker(request): 9 | path = "/src/maps/{name}.pmtiles".format( 10 | name=os.environ.get("MAP_FILE") 11 | ) 12 | map_file = open(path, mode="rb") 13 | reader = Reader(map_file) 14 | 15 | x = int(request.params["x"]) 16 | y = int(request.params["y"]) 17 | z = int(request.params["z"]) 18 | 19 | point = reader.get(z, x , y) 20 | 21 | if point != None: 22 | return Response(point) 23 | else: 24 | return Response("Tile not found") -------------------------------------------------------------------------------- /examples/protomaps/[z]/[x]/[y]/index.toml: -------------------------------------------------------------------------------- 1 | version = "1" 2 | 3 | [vars] 4 | MAP_FILE = "map" 5 | 6 | [[folders]] 7 | from = "../../../_libs" 8 | to = "/src/libs" 9 | 10 | [[folders]] 11 | from = "../../../_maps" 12 | to = "/src/maps" -------------------------------------------------------------------------------- /examples/protomaps/_libs/__init__.py: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/protomaps/_libs/__init__.py -------------------------------------------------------------------------------- /examples/protomaps/_maps/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/protomaps/_maps/.keep -------------------------------------------------------------------------------- /examples/protomaps/_maps/map.pmtiles: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/protomaps/_maps/map.pmtiles -------------------------------------------------------------------------------- /examples/protomaps/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Protomaps + Wasm Workers Server 4 | 5 | 6 | 7 | 16 | 17 | 18 |
19 | 28 | 29 | -------------------------------------------------------------------------------- /examples/python-basic/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "2027b73556ca02155f026cee751ab736985917d2f28bbcad5aac928c719e1112" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/python-basic/README.md: -------------------------------------------------------------------------------- 1 | # Python basic example 2 | 3 | Run a Python worker in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/python-basic" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 22 | -------------------------------------------------------------------------------- /examples/python-basic/index.py: -------------------------------------------------------------------------------- 1 | def worker(req): 2 | # Body response 3 | body = '''\ 4 | 5 | 6 | Wasm Workers Server 7 | 8 | 9 | 10 | 19 | 20 | 21 |
22 |

Hello from Wasm Workers Server 👋

23 |
Replying to {url}
24 | Method: {method}
25 | Host header: {host}
26 |

27 | This page was generated by a Python script 28 |

29 |
30 | 31 | '''.format( 32 | url=req.url, 33 | method=req.method, 34 | host=req.headers["host"] 35 | ) 36 | 37 | # Build a new response 38 | res = Response(body) 39 | 40 | # Add a new header 41 | res.headers["x-generated-by"] = "wasm-workers-server" 42 | 43 | return res -------------------------------------------------------------------------------- /examples/python-envs/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "2027b73556ca02155f026cee751ab736985917d2f28bbcad5aac928c719e1112" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/python-envs/README.md: -------------------------------------------------------------------------------- 1 | # Python environment variables example 2 | 3 | Run a Python worker that uses environment variables in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/python-envs" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Environment variables](https://workers.wasmlabs.dev/docs/features/environment-variables) 22 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 23 | -------------------------------------------------------------------------------- /examples/python-envs/envs.py: -------------------------------------------------------------------------------- 1 | import os 2 | 3 | def worker(req): 4 | # Body response 5 | body = "The environment variable value is: {message}".format( 6 | message=os.getenv("MESSAGE") 7 | ) 8 | 9 | return Response(body) -------------------------------------------------------------------------------- /examples/python-envs/envs.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello! This message comes from an environment variable" -------------------------------------------------------------------------------- /examples/python-kv/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "2027b73556ca02155f026cee751ab736985917d2f28bbcad5aac928c719e1112" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/python-kv/README.md: -------------------------------------------------------------------------------- 1 | # Python Key / Value store example 2 | 3 | Run a Python worker that uses a Key / Value store in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/python-kv" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 22 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 23 | -------------------------------------------------------------------------------- /examples/python-kv/counter.py: -------------------------------------------------------------------------------- 1 | CACHE_KEY = "counter" 2 | 3 | def worker(request): 4 | count = Cache.get(CACHE_KEY) 5 | 6 | if count is None: 7 | count = 0 8 | else: 9 | count = int(count) 10 | 11 | # Body response 12 | body = '''\ 13 | The counter value is: {count} 14 | '''.format( 15 | count=count 16 | ) 17 | 18 | # Build a new response 19 | res = Response(body) 20 | 21 | # Update the counter 22 | Cache.set(CACHE_KEY, count + 1) 23 | 24 | return res -------------------------------------------------------------------------------- /examples/python-kv/counter.toml: -------------------------------------------------------------------------------- 1 | name = "counter" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "counter" -------------------------------------------------------------------------------- /examples/python-libs/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217-1" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3-1/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "74d10132b0577a39e4ea30002d4605b7cdfb8f39abca327a45c8b313de7ea304" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3-1/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/python-libs/README.md: -------------------------------------------------------------------------------- 1 | # Python + libraries example 2 | 3 | Run a Python worker that uses a Python library in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * Clone the repository: 14 | 15 | ```shell-session 16 | git clone https://github.com/vmware-labs/wasm-workers-server.git && 17 | cd ./wasm-workers-server/examples/python-libs 18 | ``` 19 | 20 | * Install the Python libraries 21 | 22 | ```shell-session 23 | pip3 install -r requirements.txt -t ./_libs 24 | ``` 25 | 26 | ## Run 27 | 28 | This example runs from the previously cloned repository (See [Prerequisites](#prerequisites)). Make sure you followed all the steps and you're in the `examples/python-libs` folder: 29 | 30 | ```shell-session 31 | wws . 32 | ``` 33 | 34 | ## Resources 35 | 36 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 37 | -------------------------------------------------------------------------------- /examples/python-libs/_libs/.gitignore: -------------------------------------------------------------------------------- 1 | !.gitignore 2 | **/ 3 | -------------------------------------------------------------------------------- /examples/python-libs/index.py: -------------------------------------------------------------------------------- 1 | from bs4 import BeautifulSoup 2 | 3 | html_doc = """ 4 | 5 | Wasm Workers Server 6 | 7 | 8 | 9 | 10 |
11 |

Hello from Wasm Workers Server

12 |

13 | This page was generated by a Python file running in WebAssembly. 14 |

15 |
16 | 17 | """ 18 | 19 | def worker(req): 20 | soup = BeautifulSoup(html_doc, 'html.parser') 21 | 22 | res = Response(soup.get_text("

", True)) 23 | res.headers["x-generated-by"] = "wasm-workers-server" 24 | 25 | return res 26 | -------------------------------------------------------------------------------- /examples/python-libs/index.toml: -------------------------------------------------------------------------------- 1 | name = "libs" 2 | version = "1" 3 | 4 | [vars] 5 | PYTHONPATH = "/opt/python/libs" 6 | 7 | [[folders]] 8 | from = "./_libs" 9 | to = "/opt/python/libs" 10 | -------------------------------------------------------------------------------- /examples/python-libs/requirements.txt: -------------------------------------------------------------------------------- 1 | beautifulsoup4 2 | -------------------------------------------------------------------------------- /examples/python-mount/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "python" 9 | version = "3.11.1+20230217" 10 | tags = [ 11 | "latest", 12 | "3.11", 13 | "3.11.1", 14 | ] 15 | status = "active" 16 | extensions = ["py"] 17 | args = [ 18 | "--", 19 | "/src/index.py", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/python%2F3.11.1%2B20230217-15dfbed/python-3.11.1.wasm" 24 | filename = "python.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "66589b289f76bd716120f76f234e4dd663064ed5b6256c92d441d84e51d7585d" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/poly.py" 32 | filename = "poly.py" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "2027b73556ca02155f026cee751ab736985917d2f28bbcad5aac928c719e1112" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/python/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "cf1edc5b1427180ec09d18f4d169580379f1b12001f30e330759f9a0f8745357" 45 | -------------------------------------------------------------------------------- /examples/python-mount/README.md: -------------------------------------------------------------------------------- 1 | # Python mount folders example 2 | 3 | Run a Python worker that uses data from a mounted folder in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/python-mount" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Mount folders](https://workers.wasmlabs.dev/docs/features/mount-folders) 22 | * [Python documentation](https://workers.wasmlabs.dev/docs/languages/python) 23 | -------------------------------------------------------------------------------- /examples/python-mount/_assets/index.html: -------------------------------------------------------------------------------- 1 |

This page was loaded from a mounted file!

-------------------------------------------------------------------------------- /examples/python-mount/index.py: -------------------------------------------------------------------------------- 1 | # Read a mounted file and return it 2 | def worker(request): 3 | s = "" 4 | with open("/src/assets/index.html") as f: 5 | s = f.read() 6 | 7 | return Response(s) -------------------------------------------------------------------------------- /examples/python-mount/index.toml: -------------------------------------------------------------------------------- 1 | version = "1" 2 | 3 | [[folders]] 4 | from = "./_assets" 5 | to = "/src/assets" 6 | -------------------------------------------------------------------------------- /examples/ruby-basic/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "ruby" 9 | version = "3.2.0+20230215-1" 10 | tags = [ 11 | "latest", 12 | "3.2", 13 | "3.2.0", 14 | ] 15 | status = "active" 16 | extensions = ["rb"] 17 | args = [ 18 | "--", 19 | "/src/index.rb", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230215-1349da9/ruby-3.2.0.wasm" 24 | filename = "ruby.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "abe348fba157a756f86194be445c77c99e8ed64ca76495ea07ed984f09eb66ae" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3-1/poly.rb" 32 | filename = "poly.rb" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "449855a5d315879ab0ad830aa6a3f689e68fed4490617ea03efc77c9da64f630" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3-1/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" 45 | -------------------------------------------------------------------------------- /examples/ruby-basic/README.md: -------------------------------------------------------------------------------- 1 | # Ruby basic example 2 | 3 | Run a Ruby worker in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/ruby-basic" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Ruby documentation](https://workers.wasmlabs.dev/docs/languages/ruby) 22 | -------------------------------------------------------------------------------- /examples/ruby-basic/index.rb: -------------------------------------------------------------------------------- 1 | # My ruby worker 2 | def worker(req) 3 | # Body response 4 | body = %{ 5 | 6 | 7 | Wasm Workers Server 8 | 9 | 10 | 11 | 20 | 21 | 22 |
23 |

Hello from Wasm Workers Server 👋

24 |
Replying to #{req.url}
25 | Method: #{req.method}
26 | Host header: #{req.headers["host"]}
27 |

28 | This page was generated by a Ruby script 29 |

30 |
31 | 32 | } 33 | 34 | # Build a new response 35 | res = Response.new(body) 36 | 37 | # Add a new header 38 | res.headers["x-generated-by"] = "wasm-workers-server" 39 | 40 | res 41 | end 42 | -------------------------------------------------------------------------------- /examples/ruby-envs/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "ruby" 9 | version = "3.2.0+20230215" 10 | tags = [ 11 | "latest", 12 | "3.2", 13 | "3.2.0", 14 | ] 15 | status = "active" 16 | extensions = ["rb"] 17 | args = [ 18 | "--", 19 | "/src/index.rb", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230215-1349da9/ruby-3.2.0.wasm" 24 | filename = "ruby.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "abe348fba157a756f86194be445c77c99e8ed64ca76495ea07ed984f09eb66ae" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3/poly.rb" 32 | filename = "poly.rb" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "044b0d4bde7d3a9b0f275821fb5b67cc2e382267904df2516a23dbec1fae6bae" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" 45 | -------------------------------------------------------------------------------- /examples/ruby-envs/README.md: -------------------------------------------------------------------------------- 1 | # Ruby environment variables example 2 | 3 | Run a Ruby worker that uses environment variables in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/ruby-envs" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Environment variables](https://workers.wasmlabs.dev/docs/features/environment-variables) 22 | * [Ruby documentation](https://workers.wasmlabs.dev/docs/languages/ruby) 23 | -------------------------------------------------------------------------------- /examples/ruby-envs/envs.rb: -------------------------------------------------------------------------------- 1 | # Read an environment variable in Ruby 2 | def worker(request) 3 | Response.new( 4 | "The environment variable value is: #{ENV.fetch('MESSAGE')}" 5 | ) 6 | end -------------------------------------------------------------------------------- /examples/ruby-envs/envs.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello! This message comes from an environment variable" -------------------------------------------------------------------------------- /examples/ruby-kv/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "ruby" 9 | version = "3.2.0+20230215" 10 | tags = [ 11 | "latest", 12 | "3.2", 13 | "3.2.0", 14 | ] 15 | status = "active" 16 | extensions = ["rb"] 17 | args = [ 18 | "--", 19 | "/src/index.rb", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230215-1349da9/ruby-3.2.0.wasm" 24 | filename = "ruby.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "abe348fba157a756f86194be445c77c99e8ed64ca76495ea07ed984f09eb66ae" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3/poly.rb" 32 | filename = "poly.rb" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "044b0d4bde7d3a9b0f275821fb5b67cc2e382267904df2516a23dbec1fae6bae" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://workers.wasmlabs.dev/repository/v1/files/ruby/3/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" 45 | -------------------------------------------------------------------------------- /examples/ruby-kv/README.md: -------------------------------------------------------------------------------- 1 | # Ruby Key / Value store example 2 | 3 | Run a Ruby worker that uses a Key / Value store in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/ruby-kv" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 22 | * [Ruby documentation](https://workers.wasmlabs.dev/docs/languages/ruby) 23 | -------------------------------------------------------------------------------- /examples/ruby-kv/counter.rb: -------------------------------------------------------------------------------- 1 | CACHE_KEY = "counter"; 2 | 3 | def worker(request) 4 | # Prepare the body 5 | count = Cache.get(CACHE_KEY).to_i || 0 6 | body = "The counter value is: #{count}" 7 | 8 | # Update the counter 9 | count += 1 10 | Cache.set(CACHE_KEY, count) 11 | 12 | # Return the response 13 | Response.new(body) 14 | end -------------------------------------------------------------------------------- /examples/ruby-kv/counter.toml: -------------------------------------------------------------------------------- 1 | name = "counter" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "counter" -------------------------------------------------------------------------------- /examples/ruby-mount/.wws.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[repositories]] 4 | name = "wasmlabs" 5 | url = "https://workers.wasmlabs.dev/repository/v1/index.toml" 6 | 7 | [[repositories.runtimes]] 8 | name = "ruby" 9 | version = "3.2.0+20230215-1" 10 | tags = [ 11 | "latest", 12 | "3.2", 13 | "3.2.0", 14 | ] 15 | status = "active" 16 | extensions = ["rb"] 17 | args = [ 18 | "--", 19 | "/src/index.rb", 20 | ] 21 | 22 | [repositories.runtimes.binary] 23 | url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230215-1349da9/ruby-3.2.0.wasm" 24 | filename = "ruby.wasm" 25 | 26 | [repositories.runtimes.binary.checksum] 27 | type = "sha256" 28 | value = "abe348fba157a756f86194be445c77c99e8ed64ca76495ea07ed984f09eb66ae" 29 | 30 | [repositories.runtimes.polyfill] 31 | url = "https://raw.githubusercontent.com/vmware-labs/wasm-workers-server/109-improve-python-polyfill/metadata/repository/v1/files/ruby/3-1/poly.rb" 32 | filename = "poly.rb" 33 | 34 | [repositories.runtimes.polyfill.checksum] 35 | type = "sha256" 36 | value = "449855a5d315879ab0ad830aa6a3f689e68fed4490617ea03efc77c9da64f630" 37 | 38 | [repositories.runtimes.wrapper] 39 | url = "https://raw.githubusercontent.com/vmware-labs/wasm-workers-server/109-improve-python-polyfill/metadata/repository/v1/files/ruby/3-1/wrapper.txt" 40 | filename = "wrapper.txt" 41 | 42 | [repositories.runtimes.wrapper.checksum] 43 | type = "sha256" 44 | value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" 45 | -------------------------------------------------------------------------------- /examples/ruby-mount/README.md: -------------------------------------------------------------------------------- 1 | # Ruby mount folders example 2 | 3 | Run a Ruby worker that uses data from a mounted folder in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | ## Run 14 | 15 | ```shell-session 16 | wws https://github.com/vmware-labs/wasm-workers-server.git -i --git-folder "examples/ruby-mount" 17 | ``` 18 | 19 | ## Resources 20 | 21 | * [Mount folders](https://workers.wasmlabs.dev/docs/features/mount-folders) 22 | * [Ruby documentation](https://workers.wasmlabs.dev/docs/languages/ruby) 23 | -------------------------------------------------------------------------------- /examples/ruby-mount/image.rb: -------------------------------------------------------------------------------- 1 | # Read an environment variable in Ruby 2 | def worker(request) 3 | img = IO.read("/src/images/ruby.svg", mode: "rb") 4 | 5 | res = Response.new(img) 6 | res.headers["Content-Type"] = "image/svg+xml" 7 | 8 | res 9 | end -------------------------------------------------------------------------------- /examples/ruby-mount/image.toml: -------------------------------------------------------------------------------- 1 | version = "1" 2 | 3 | [[folders]] 4 | from = "./_images" 5 | to = "/src/images" -------------------------------------------------------------------------------- /examples/ruby-mount/public/css/styles.css: -------------------------------------------------------------------------------- 1 | body { 2 | text-align: center; 3 | } 4 | 5 | img { 6 | margin: 4rem 0 2rem; 7 | width: 250px; 8 | } -------------------------------------------------------------------------------- /examples/ruby-mount/public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | Ruby + Wasm Workers Server 4 | 5 | 6 | 7 | The ruby logo 8 |

This image is served by Wasm Workers Server

9 | 10 | -------------------------------------------------------------------------------- /examples/rust-basic/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-basic" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.63" 8 | wasm-workers-rs = { path = "../../kits/rust" } 9 | -------------------------------------------------------------------------------- /examples/rust-basic/README.md: -------------------------------------------------------------------------------- 1 | # Rust basic example 2 | 3 | Compile a Rust worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Install Rust with rustup](https://www.rust-lang.org/tools/install) 14 | * Install the `wasm32-wasi` target: 15 | 16 | ```shell-session 17 | rustup target add wasm32-wasi 18 | ``` 19 | 20 | ## Build 21 | 22 | ```shell-session 23 | cargo build --target wasm32-wasi --release && \ 24 | cp target/wasm32-wasi/release/rust-basic.wasm ./basic.wasm 25 | ``` 26 | 27 | ## Run 28 | 29 | ```shell-session 30 | wws . 31 | ``` 32 | 33 | ## Resources 34 | 35 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 36 | -------------------------------------------------------------------------------- /examples/rust-basic/rust-basic.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello from Wasm Workers Server!" -------------------------------------------------------------------------------- /examples/rust-fetch/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-fetch" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.63" 8 | wasm-workers-rs = { path = "../../kits/rust" } 9 | serde = { version = "1.0", features = ["derive"] } 10 | serde_json = "1.0.85" 11 | -------------------------------------------------------------------------------- /examples/rust-fetch/README.md: -------------------------------------------------------------------------------- 1 | # Rust fetch example 2 | 3 | Compile a Rust worker that can retrieve data from a remote endpoint (via HTTP bindings). You can run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Install Rust with rustup](https://www.rust-lang.org/tools/install) 14 | * Install the `wasm32-wasi` target: 15 | 16 | ```shell-session 17 | rustup target add wasm32-wasi 18 | ``` 19 | 20 | ## Build 21 | 22 | ```shell-session 23 | cargo build --target wasm32-wasi --release && \ 24 | cp target/wasm32-wasi/release/rust-fetch.wasm ./index.wasm 25 | ``` 26 | 27 | ## Run 28 | 29 | ```shell-session 30 | wws . 31 | ``` 32 | 33 | ## Resources 34 | 35 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 36 | -------------------------------------------------------------------------------- /examples/rust-fetch/index.toml: -------------------------------------------------------------------------------- 1 | name = "rust-fetch" 2 | version = "1" 3 | 4 | [features] 5 | [features.http_requests] 6 | allowed_hosts = ["jsonplaceholder.typicode.com"] 7 | -------------------------------------------------------------------------------- /examples/rust-kv/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-kv" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.63" 8 | wasm-workers-rs = { path = "../../kits/rust" } 9 | -------------------------------------------------------------------------------- /examples/rust-kv/README.md: -------------------------------------------------------------------------------- 1 | # Rust Key / Value example 2 | 3 | Compile a Rust worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Install Rust with rustup](https://www.rust-lang.org/tools/install) 14 | * Install the `wasm32-wasi` target: 15 | 16 | ```shell-session 17 | rustup target add wasm32-wasi 18 | ``` 19 | 20 | ## Build 21 | 22 | ```shell-session 23 | cargo build --target wasm32-wasi --release && \ 24 | cp target/wasm32-wasi/release/rust-kv.wasm ./kv.wasm 25 | ``` 26 | 27 | ## Run 28 | 29 | ```shell-session 30 | wws . 31 | ``` 32 | 33 | ## Resources 34 | 35 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 36 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 37 | -------------------------------------------------------------------------------- /examples/rust-kv/rust-kv.toml: -------------------------------------------------------------------------------- 1 | name = "counter" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "counter" 7 | 8 | [vars] -------------------------------------------------------------------------------- /examples/rust-kv/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use wasm_workers_rs::{ 3 | http::{self, Request, Response}, 4 | worker, Cache, Content, 5 | }; 6 | 7 | #[worker(cache)] 8 | fn handler(_req: Request, cache: &mut Cache) -> Result> { 9 | // Applied changes here to use the Response method. This requires changes 10 | // on signature and how it returns the data. 11 | let count = cache.get("counter"); 12 | let count_num = match count { 13 | Some(count_str) => count_str.parse::().unwrap_or(0), 14 | None => 0, 15 | }; 16 | 17 | let response = format!( 18 | " 19 | 20 |

Key / Value store in Rust

21 |

Counter: {}

22 |

This page was generated by a Wasm modules built from Rust.

23 | ", 24 | count_num 25 | ); 26 | 27 | cache.insert("counter".to_string(), (count_num + 1).to_string()); 28 | 29 | Ok(http::Response::builder() 30 | .status(200) 31 | .header("x-generated-by", "wasm-workers-server") 32 | .body(response.into())?) 33 | } 34 | -------------------------------------------------------------------------------- /examples/rust-params/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-params" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.63" 8 | wasm-workers-rs = { path = "../../kits/rust" } 9 | -------------------------------------------------------------------------------- /examples/rust-params/README.md: -------------------------------------------------------------------------------- 1 | # Rust dynamic routes example 2 | 3 | Compile a Rust worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Install Rust with rustup](https://www.rust-lang.org/tools/install) 14 | * Install the `wasm32-wasi` target: 15 | 16 | ```shell-session 17 | rustup target add wasm32-wasi 18 | ``` 19 | 20 | ## Build 21 | 22 | ```shell-session 23 | cargo build --target wasm32-wasi --release && \ 24 | cp target/wasm32-wasi/release/rust-params.wasm ./[id].wasm 25 | ``` 26 | 27 | ## Run 28 | 29 | ```shell-session 30 | wws . 31 | ``` 32 | 33 | ## Resources 34 | 35 | * [Dynamic routes](https://workers.wasmlabs.dev/docs/features/dynamic-routes) 36 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 37 | -------------------------------------------------------------------------------- /examples/rust-params/public/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 1000px; 3 | } 4 | 5 | main { 6 | margin: 5rem 0; 7 | } 8 | 9 | h1, 10 | p { 11 | text-align: center; 12 | } 13 | 14 | h1 { 15 | margin-bottom: 2rem; 16 | } 17 | 18 | pre { 19 | font-size: .9rem; 20 | } 21 | 22 | pre>code { 23 | padding: 2rem; 24 | } 25 | 26 | p { 27 | margin-top: 2rem; 28 | } -------------------------------------------------------------------------------- /examples/rust-params/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use std::collections::HashMap; 3 | use wasm_workers_rs::{ 4 | http::{self, Request, Response}, 5 | worker, Content, 6 | }; 7 | 8 | #[worker(params)] 9 | fn reply(_req: Request, params: &HashMap) -> Result> { 10 | let unknown_id = String::from("the value is not available"); 11 | let response = format!( 12 | " 13 | 14 | Wasm Workers Server 15 | 16 | 17 | 18 | 19 | 20 | 21 |
22 |

Hello from Wasm Workers Server 👋

23 |

24 | This is a dynamic route! The [id]/fixed.js worker is replying this URL. 25 | The id parameter value is: {} 26 |

27 |

Read more about dynamic routes in the documentation

28 |
29 | ", 30 | params.get("id").unwrap_or_else(|| &unknown_id) 31 | ); 32 | 33 | Ok(http::Response::builder() 34 | .status(200) 35 | .header("x-generated-by", "wasm-workers-server") 36 | .body(response.into())?) 37 | } 38 | -------------------------------------------------------------------------------- /examples/rust-pdf-create/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-pdf-create" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | [dependencies] 7 | anyhow = "1.0.63" 8 | wasm-workers-rs = { path = "../../kits/rust" } 9 | printpdf = "0.5.3" 10 | -------------------------------------------------------------------------------- /examples/rust-pdf-create/README.md: -------------------------------------------------------------------------------- 1 | # Rust PDF example 2 | 3 | Compile a Rust worker to WebAssembly and run it in Wasm Workers Server. This worker generates a PDF based on the request body. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Install Rust with rustup](https://www.rust-lang.org/tools/install) 14 | * Install the `wasm32-wasi` target: 15 | 16 | ```shell-session 17 | rustup target add wasm32-wasi 18 | ``` 19 | 20 | ## Build 21 | 22 | ```shell-session 23 | cargo build --target wasm32-wasi --release && \ 24 | cp target/wasm32-wasi/release/rust-pdf-create.wasm ./index.wasm 25 | ``` 26 | 27 | ## Run 28 | 29 | ```shell-session 30 | wws . 31 | ``` 32 | 33 | ## Resources 34 | 35 | * [Rust documentation](https://workers.wasmlabs.dev/docs/languages/rust) 36 | -------------------------------------------------------------------------------- /examples/rust-pdf-create/src/main.rs: -------------------------------------------------------------------------------- 1 | use anyhow::Result; 2 | use printpdf::*; 3 | use std::io::BufWriter; 4 | use wasm_workers_rs::{ 5 | http::{self, Request, Response}, 6 | worker, Content, 7 | }; 8 | 9 | #[worker] 10 | fn handler(req: Request) -> Result> { 11 | let mut buf = BufWriter::new(Vec::new()); 12 | 13 | let (doc, page1, layer1) = PdfDocument::new("My Quote", Mm(247.0), Mm(210.0), "Layer 1"); 14 | let current_layer = doc.get_page(page1).get_layer(layer1); 15 | let font = doc.add_builtin_font(BuiltinFont::TimesRoman).unwrap(); 16 | 17 | current_layer.use_text("Your Quote", 24.0, Mm(20.0), Mm(190.0), &font); 18 | current_layer.use_text(req.body(), 18.0, Mm(20.0), Mm(170.0), &font); 19 | current_layer.use_text( 20 | "Created by a Wasm module in Wasm Workers Server", 21 | 12.0, 22 | Mm(20.0), 23 | Mm(20.0), 24 | &font, 25 | ); 26 | 27 | doc.save(&mut buf)?; 28 | 29 | let bytes = buf.into_inner()?; 30 | 31 | Ok(http::Response::builder() 32 | .status(200) 33 | .header("Content-Disposition", "attachment; filename=\"quote.pdf\"") 34 | .header("Content-Type", "application/pdf") 35 | .header("x-generated-by", "wasm-workers-server") 36 | .body(bytes.into())?) 37 | } 38 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/.gitignore: -------------------------------------------------------------------------------- 1 | _images/image.jpg 2 | _models/**/*.bin 3 | _models/**/*.xml 4 | !inference.wasm 5 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-wasi-nn-preload" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | wasi-nn = "0.6.0" 10 | anyhow = "1.0.63" 11 | image2tensor = "0.2.0" 12 | wasm-workers-rs = { path = "../../kits/rust" } 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0.85" 15 | base64 = "0.21.2" 16 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/_images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/rust-wasi-nn-preload/_images/.gitkeep -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/_models/mobilenet/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/rust-wasi-nn-preload/_models/mobilenet/.gitkeep -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/inference.toml: -------------------------------------------------------------------------------- 1 | name = "wasi-nn-mobilenet-preload" 2 | version = "1" 3 | 4 | [[features.wasi_nn.preload_models]] 5 | backend = "openvino" 6 | provider = { type = "local", dir = "./_models/mobilenet/" } 7 | 8 | [[folders]] 9 | from = "./_data" 10 | to = "/tmp/data" 11 | 12 | [[folders]] 13 | from = "./_images" 14 | to = "/tmp/images" 15 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/inference.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/rust-wasi-nn-preload/inference.wasm -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MODEL_GITHUB=https://github.com/intel/openvino-rs/tree/main/crates/openvino/tests/fixtures/mobilenet 4 | MODEL=https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/mobilenet 5 | 6 | echo "Downloading the model from ${MODEL_GITHUB}" 7 | 8 | wget --no-clobber $MODEL/mobilenet.bin --output-document=_models/mobilenet/model.bin 9 | wget --no-clobber $MODEL/mobilenet.xml --output-document=_models/mobilenet/model.xml 10 | 11 | echo "Finished!" 12 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/public/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 1000px; 3 | } 4 | 5 | main { 6 | margin: 5rem 0; 7 | } 8 | 9 | h1, 10 | p { 11 | text-align: center; 12 | } 13 | 14 | h1 { 15 | margin-bottom: 2rem; 16 | } 17 | 18 | pre { 19 | font-size: .9rem; 20 | } 21 | 22 | pre>code { 23 | padding: 2rem; 24 | } 25 | 26 | p { 27 | margin-top: 2rem; 28 | } 29 | 30 | input { 31 | margin: 0 auto; 32 | width: auto; 33 | } 34 | 35 | .image { 36 | width: 500px; 37 | height: 224px; 38 | border-radius: 5px; 39 | background-color: #151f27; 40 | margin: 2rem auto 1rem; 41 | text-align: center; 42 | } 43 | 44 | #image { 45 | display: inline-block; 46 | height: calc(224px - 2rem); 47 | border-radius: 5px; 48 | margin: 1rem; 49 | width: auto; 50 | } 51 | 52 | .results { 53 | margin: 2rem auto; 54 | width: 500px; 55 | } 56 | 57 | .result { 58 | margin-top: 1.25rem; 59 | } 60 | 61 | .result_progress { 62 | --progress: 0%; 63 | position: relative; 64 | height: 5px; 65 | border-radius: 5px; 66 | width: 100%; 67 | background-color: #151f27; 68 | } 69 | 70 | .result_progress::after { 71 | background-color: blueviolet; 72 | content: ""; 73 | border-radius: 5px; 74 | height: 5px; 75 | width: var(--progress); 76 | position: absolute; 77 | top: 0; 78 | left: 0; 79 | } 80 | 81 | .result_label { 82 | margin-top: .5rem; 83 | font-style: italic; 84 | } 85 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn-preload/public/main.js: -------------------------------------------------------------------------------- 1 | document.getElementById('file') 2 | .addEventListener('change', getFile) 3 | 4 | function getFile(event) { 5 | const input = event.target 6 | if ('files' in input && input.files.length > 0) { 7 | runInference(input.files[0]) 8 | } 9 | } 10 | 11 | function runInference(file) { 12 | readFileContent(file).then(content => { 13 | let result = btoa(content); 14 | 15 | // Set the image 16 | document 17 | .getElementById("image") 18 | .src = `data:image/jpeg;base64,${result}`; 19 | 20 | fetch("/inference", { 21 | method: "POST", 22 | body: result 23 | }).then(res => res.json()) 24 | .then(json => setResults(json)); 25 | 26 | }).catch(error => console.log(error)) 27 | } 28 | 29 | function setResults(json) { 30 | for (let i = 0; i < 5; i++) { 31 | let value = json.data[i]; 32 | let res = document.getElementById(`result-${i}`); 33 | let progress = res.querySelector(".result_progress"); 34 | let label = res.querySelector(".result_label"); 35 | 36 | label.textContent = value[0]; 37 | progress.style.setProperty("--progress", `${Math.max(value[1] * 100, 1)}%`); 38 | } 39 | } 40 | 41 | function readFileContent(file) { 42 | const reader = new FileReader() 43 | return new Promise((resolve, reject) => { 44 | reader.onload = event => resolve(event.target.result) 45 | reader.onerror = error => reject(error) 46 | reader.readAsBinaryString(file) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn/.gitignore: -------------------------------------------------------------------------------- 1 | _images/image.jpg 2 | _models/*.bin 3 | _models/*.xml 4 | !inference.wasm -------------------------------------------------------------------------------- /examples/rust-wasi-nn/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "rust-wasi-nn" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | wasi-nn = "0.4.0" 10 | anyhow = "1.0.63" 11 | image2tensor = "0.2.0" 12 | wasm-workers-rs = { path = "../../kits/rust" } 13 | serde = { version = "1.0", features = ["derive"] } 14 | serde_json = "1.0.85" 15 | base64 = "0.21.2" 16 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn/_images/.gitkeep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/rust-wasi-nn/_images/.gitkeep -------------------------------------------------------------------------------- /examples/rust-wasi-nn/inference.toml: -------------------------------------------------------------------------------- 1 | name = "wasi-nn-mobilenet" 2 | version = "1" 3 | 4 | [vars] 5 | MODEL = "model" 6 | 7 | [features] 8 | [features.wasi_nn] 9 | allowed_backends = ["openvino"] 10 | 11 | [[folders]] 12 | from = "./_models" 13 | to = "/tmp/model" 14 | 15 | [[folders]] 16 | from = "./_images" 17 | to = "/tmp/images" 18 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn/inference.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/examples/rust-wasi-nn/inference.wasm -------------------------------------------------------------------------------- /examples/rust-wasi-nn/prepare.sh: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env bash 2 | 3 | MODEL_GITHUB=https://github.com/intel/openvino-rs/tree/main/crates/openvino/tests/fixtures/mobilenet 4 | MODEL=https://github.com/intel/openvino-rs/raw/main/crates/openvino/tests/fixtures/mobilenet 5 | 6 | echo "Downloading the model from ${MODEL_GITHUB}" 7 | 8 | wget --no-clobber $MODEL/mobilenet.bin --output-document=_models/model.bin 9 | wget --no-clobber $MODEL/mobilenet.xml --output-document=_models/model.xml 10 | 11 | echo "Finished!" 12 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn/public/main.css: -------------------------------------------------------------------------------- 1 | body { 2 | max-width: 1000px; 3 | } 4 | 5 | main { 6 | margin: 5rem 0; 7 | } 8 | 9 | h1, 10 | p { 11 | text-align: center; 12 | } 13 | 14 | h1 { 15 | margin-bottom: 2rem; 16 | } 17 | 18 | pre { 19 | font-size: .9rem; 20 | } 21 | 22 | pre>code { 23 | padding: 2rem; 24 | } 25 | 26 | p { 27 | margin-top: 2rem; 28 | } 29 | 30 | input { 31 | margin: 0 auto; 32 | width: auto; 33 | } 34 | 35 | .image { 36 | width: 500px; 37 | height: 224px; 38 | border-radius: 5px; 39 | background-color: #151f27; 40 | margin: 2rem auto 1rem; 41 | text-align: center; 42 | } 43 | 44 | #image { 45 | display: inline-block; 46 | height: calc(224px - 2rem); 47 | border-radius: 5px; 48 | margin: 1rem; 49 | width: auto; 50 | } 51 | 52 | .results { 53 | margin: 2rem auto; 54 | width: 500px; 55 | } 56 | 57 | .result { 58 | margin-top: 1.25rem; 59 | } 60 | 61 | .result_progress { 62 | --progress: 0%; 63 | position: relative; 64 | height: 5px; 65 | border-radius: 5px; 66 | width: 100%; 67 | background-color: #151f27; 68 | } 69 | 70 | .result_progress::after { 71 | background-color: blueviolet; 72 | content: ""; 73 | border-radius: 5px; 74 | height: 5px; 75 | width: var(--progress); 76 | position: absolute; 77 | top: 0; 78 | left: 0; 79 | } 80 | 81 | .result_label { 82 | margin-top: .5rem; 83 | font-style: italic; 84 | } 85 | -------------------------------------------------------------------------------- /examples/rust-wasi-nn/public/main.js: -------------------------------------------------------------------------------- 1 | document.getElementById('file') 2 | .addEventListener('change', getFile) 3 | 4 | function getFile(event) { 5 | const input = event.target 6 | if ('files' in input && input.files.length > 0) { 7 | runInference(input.files[0]) 8 | } 9 | } 10 | 11 | function runInference(file) { 12 | readFileContent(file).then(content => { 13 | let result = btoa(content); 14 | 15 | // Set the image 16 | document 17 | .getElementById("image") 18 | .src = `data:image/jpeg;base64,${result}`; 19 | 20 | fetch("/inference", { 21 | method: "POST", 22 | body: result 23 | }).then(res => res.json()) 24 | .then(json => setResults(json)); 25 | 26 | }).catch(error => console.log(error)) 27 | } 28 | 29 | function setResults(json) { 30 | for (let i = 0; i < 5; i++) { 31 | let value = json.data[i]; 32 | let res = document.getElementById(`result-${i}`); 33 | let progress = res.querySelector(".result_progress"); 34 | let label = res.querySelector(".result_label"); 35 | 36 | label.textContent = value[0]; 37 | progress.style.setProperty("--progress", `${Math.max(value[1] * 100, 1)}%`); 38 | } 39 | } 40 | 41 | function readFileContent(file) { 42 | const reader = new FileReader() 43 | return new Promise((resolve, reject) => { 44 | reader.onload = event => resolve(event.target.result) 45 | reader.onerror = error => reject(error) 46 | reader.readAsBinaryString(file) 47 | }) 48 | } 49 | -------------------------------------------------------------------------------- /examples/zig-basic/README.md: -------------------------------------------------------------------------------- 1 | # Basic example 2 | 3 | Compile a Zig worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Zig](https://ziglang.org/download/) `0.11.0` 14 | 15 | ## Build 16 | 17 | All specific build confiugrations are in `build.zig` file. 18 | 19 | ```shell-session 20 | zig build 21 | ``` 22 | 23 | ## Run 24 | 25 | ```shell-session 26 | wws ./zig-out/bin/ 27 | ``` 28 | 29 | ## Resources 30 | 31 | * [Zig documentation](https://workers.wasmlabs.dev/docs/languages/zig) 32 | * [Announcing Zig support for Wasm Workers Server](https://wasmlabs.dev/articles/Zig-support-on-wasm-workers-server/) 33 | -------------------------------------------------------------------------------- /examples/zig-basic/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const examples = [1][]const u8{ "basic" }; 4 | 5 | pub fn build(b: *std.Build) !void { 6 | const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" }); 7 | const optimize = b.standardOptimizeOption(.{}); 8 | 9 | const worker_module = b.createModule(.{ 10 | .source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" }, 11 | }); 12 | 13 | inline for (examples) |example| { 14 | const exe = b.addExecutable(.{ 15 | .name = example, 16 | .root_source_file = .{ .path = "src/" ++ example ++ ".zig" }, 17 | .target = target, 18 | .optimize = optimize, 19 | }); 20 | 21 | exe.wasi_exec_model = .reactor; 22 | exe.addModule("worker", worker_module); 23 | 24 | b.installArtifact(exe); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-envs/README.md: -------------------------------------------------------------------------------- 1 | # Zig environment variables example 2 | 3 | Compile a Zig worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Zig](https://ziglang.org/download/) `0.11.0` 14 | 15 | ## Build 16 | 17 | All specific build configurations are in `build.zig` file. 18 | 19 | ```shell-session 20 | zig build 21 | ``` 22 | 23 | ## Run 24 | 25 | ```shell-session 26 | wws ./zig-out/bin/ 27 | ``` 28 | 29 | ## Resources 30 | 31 | * [Environment variables](https://workers.wasmlabs.dev/docs/features/environment-variables) 32 | * [Zig documentation](https://workers.wasmlabs.dev/docs/languages/zig) 33 | * [Announcing Zig support for Wasm Workers Server](https://wasmlabs.dev/articles/Zig-support-on-wasm-workers-server/) 34 | -------------------------------------------------------------------------------- /examples/zig-envs/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const examples = [1][]const u8{ "envs" }; 4 | 5 | pub fn build(b: *std.Build) !void { 6 | const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" }); 7 | const optimize = b.standardOptimizeOption(.{}); 8 | 9 | const worker_module = b.createModule(.{ 10 | .source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" }, 11 | }); 12 | 13 | inline for (examples) |example| { 14 | const exe = b.addExecutable(.{ 15 | .name = example, 16 | .root_source_file = .{ .path = "src/" ++ example ++ ".zig" }, 17 | .target = target, 18 | .optimize = optimize, 19 | }); 20 | 21 | exe.wasi_exec_model = .reactor; 22 | exe.addModule("worker", worker_module); 23 | 24 | b.installArtifact(exe); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-envs/src/envs.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const worker = @import("worker"); 3 | 4 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 5 | const allocator = arena.allocator(); 6 | 7 | fn requestFn(resp: *worker.Response, r: *worker.Request) void { 8 | _ = r; 9 | 10 | const envvar = std.process.getEnvVarOwned(allocator, "MESSAGE") catch ""; 11 | defer allocator.free(envvar); 12 | 13 | const s = 14 | \\The environment variable value is: {s} 15 | ; 16 | 17 | var body = std.fmt.allocPrint(allocator, s, .{ envvar }) catch undefined; // add useragent 18 | 19 | _ = &resp.headers.append("x-generated-by", "wasm-workers-server"); 20 | _ = &resp.writeAll(body); 21 | } 22 | 23 | pub fn main() !void { 24 | worker.ServeFunc(requestFn); 25 | } 26 | -------------------------------------------------------------------------------- /examples/zig-envs/zig-out/bin/envs.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [vars] 5 | MESSAGE = "Hello! This message comes from an environment variable" -------------------------------------------------------------------------------- /examples/zig-kv/README.md: -------------------------------------------------------------------------------- 1 | # Key/Value example 2 | 3 | Compile a Zig worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Zig](https://ziglang.org/download/) `0.11.0` 14 | 15 | ## Build 16 | 17 | All specific build confiugrations are in `build.zig` file. 18 | 19 | ```shell-session 20 | zig build 21 | ``` 22 | 23 | ## Run 24 | 25 | ```shell-session 26 | wws ./zig-out/bin/ 27 | ``` 28 | 29 | ## Resources 30 | 31 | * [Key / Value store](https://workers.wasmlabs.dev/docs/features/key-value) 32 | * [Zig documentation](https://workers.wasmlabs.dev/docs/languages/zig) 33 | * [Announcing Zig support for Wasm Workers Server](https://wasmlabs.dev/articles/Zig-support-on-wasm-workers-server/) 34 | -------------------------------------------------------------------------------- /examples/zig-kv/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const examples = [1][]const u8{ "worker-kv" }; 4 | 5 | pub fn build(b: *std.Build) !void { 6 | const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" }); 7 | const optimize = b.standardOptimizeOption(.{}); 8 | 9 | const worker_module = b.createModule(.{ 10 | .source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" }, 11 | }); 12 | 13 | inline for (examples) |example| { 14 | const exe = b.addExecutable(.{ 15 | .name = example, 16 | .root_source_file = .{ .path = "src/" ++ example ++ ".zig" }, 17 | .target = target, 18 | .optimize = optimize, 19 | }); 20 | 21 | exe.wasi_exec_model = .reactor; 22 | exe.addModule("worker", worker_module); 23 | 24 | b.installArtifact(exe); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-kv/zig-out/bin/worker-kv.toml: -------------------------------------------------------------------------------- 1 | name = "workerkv" 2 | version = "1" 3 | 4 | [data] 5 | [data.kv] 6 | namespace = "workerkv" -------------------------------------------------------------------------------- /examples/zig-mount/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const examples = [1][]const u8{ "mount" }; 4 | 5 | pub fn build(b: *std.Build) !void { 6 | const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" }); 7 | const optimize = b.standardOptimizeOption(.{}); 8 | 9 | const worker_module = b.createModule(.{ 10 | .source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" }, 11 | }); 12 | 13 | inline for (examples) |example| { 14 | const exe = b.addExecutable(.{ 15 | .name = example, 16 | .root_source_file = .{ .path = "src/" ++ example ++ ".zig" }, 17 | .target = target, 18 | .optimize = optimize, 19 | }); 20 | 21 | exe.wasi_exec_model = .reactor; 22 | exe.addModule("worker", worker_module); 23 | 24 | b.installArtifact(exe); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-mount/src/mount.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const worker = @import("worker"); 3 | 4 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 5 | const allocator = arena.allocator(); 6 | 7 | fn requestFn(resp: *worker.Response, r: *worker.Request) void { 8 | _ = r; 9 | 10 | const file = std.fs.Dir.openFileWasi( 11 | std.fs.cwd(), "zig.svg", .{ 12 | .mode = std.fs.File.OpenMode.read_only, 13 | .lock = std.fs.File.Lock.none, 14 | }) catch unreachable; 15 | defer file.close(); 16 | 17 | const mb = (1 << 10) << 10; 18 | const file_contents = file.readToEndAlloc(allocator, mb) catch ""; 19 | 20 | _ = &resp.headers.append("x-generated-by", "wasm-workers-server"); 21 | _ = &resp.writeAll(file_contents); 22 | } 23 | 24 | pub fn main() !void { 25 | worker.ServeFunc(requestFn); 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-mount/zig-out/bin/mount.toml: -------------------------------------------------------------------------------- 1 | name = "envs" 2 | version = "1" 3 | 4 | [[folders]] 5 | from = "./_images" 6 | to = "/src/images" -------------------------------------------------------------------------------- /examples/zig-params/README.md: -------------------------------------------------------------------------------- 1 | # Params example 2 | 3 | Compile a Zig worker to WebAssembly and run it in Wasm Workers Server. 4 | 5 | ## Prerequisites 6 | 7 | * Wasm Workers Server (wws): 8 | 9 | ```shell-session 10 | curl -fsSL https://workers.wasmlabs.dev/install | bash 11 | ``` 12 | 13 | * [Zig](https://ziglang.org/download/) `0.11.0` 14 | 15 | ## Build 16 | 17 | All specific build confiugrations are in `build.zig` file. 18 | 19 | ```shell-session 20 | zig build 21 | ``` 22 | 23 | ## Run 24 | 25 | ```shell-session 26 | wws ./zig-out/bin/ 27 | ``` 28 | 29 | ## Resources 30 | 31 | * [Dynamic routes](https://workers.wasmlabs.dev/docs/features/dynamic-routes) 32 | * [Zig documentation](https://workers.wasmlabs.dev/docs/languages/zig) 33 | * [Announcing Zig support for Wasm Workers Server](https://wasmlabs.dev/articles/Zig-support-on-wasm-workers-server/) 34 | -------------------------------------------------------------------------------- /examples/zig-params/build.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | 3 | const examples = [1][]const u8{ "worker-params" }; 4 | 5 | pub fn build(b: *std.Build) !void { 6 | const target = try std.zig.CrossTarget.parse(.{ .arch_os_abi = "wasm32-wasi" }); 7 | const optimize = b.standardOptimizeOption(.{}); 8 | 9 | const worker_module = b.createModule(.{ 10 | .source_file = .{ .path = "../../kits/zig/worker/src/worker.zig" }, 11 | }); 12 | 13 | inline for (examples) |example| { 14 | const exe = b.addExecutable(.{ 15 | .name = example, 16 | .root_source_file = .{ .path = "src/" ++ example ++ ".zig" }, 17 | .target = target, 18 | .optimize = optimize, 19 | }); 20 | 21 | exe.wasi_exec_model = .reactor; 22 | exe.addModule("worker", worker_module); 23 | 24 | b.installArtifact(exe); 25 | } 26 | } 27 | -------------------------------------------------------------------------------- /examples/zig-params/src/worker-params.zig: -------------------------------------------------------------------------------- 1 | const std = @import("std"); 2 | const worker = @import("worker"); 3 | 4 | var arena = std.heap.ArenaAllocator.init(std.heap.page_allocator); 5 | const allocator = arena.allocator(); 6 | 7 | fn requestFn(resp: *worker.Response, r: *worker.Request) void { 8 | var params = r.context.params; 9 | 10 | var id: []const u8 = "the value is not available"; 11 | 12 | var v = params.get("id"); 13 | 14 | if (v) |val| { 15 | id = val; 16 | } 17 | 18 | const s = 19 | \\Hey! The parameter is: {s} 20 | ; 21 | 22 | var body = std.fmt.allocPrint(allocator, s, .{ id }) catch undefined; // add useragent 23 | 24 | _ = &resp.headers.append("x-generated-by", "wasm-workers-server"); 25 | _ = &resp.writeAll(body); 26 | } 27 | 28 | pub fn main() !void { 29 | worker.ServeFunc(requestFn); 30 | } 31 | -------------------------------------------------------------------------------- /go.mod: -------------------------------------------------------------------------------- 1 | module github.com/vmware-labs/wasm-workers-server 2 | 3 | go 1.20 4 | 5 | require ( 6 | github.com/tidwall/gjson v1.14.4 7 | github.com/tidwall/sjson v1.2.5 8 | ) 9 | 10 | require ( 11 | github.com/tidwall/match v1.1.1 // indirect 12 | github.com/tidwall/pretty v1.2.1 // indirect 13 | ) 14 | -------------------------------------------------------------------------------- /go.sum: -------------------------------------------------------------------------------- 1 | github.com/tidwall/gjson v1.14.2/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 2 | github.com/tidwall/gjson v1.14.4 h1:uo0p8EbA09J7RQaflQ1aBRffTR7xedD2bcIVSYxLnkM= 3 | github.com/tidwall/gjson v1.14.4/go.mod h1:/wbyibRr2FHMks5tjHJ5F8dMZh3AcwJEMf5vlfC0lxk= 4 | github.com/tidwall/match v1.1.1 h1:+Ho715JplO36QYgwN9PGYNhgZvoUSc9X2c80KVTi+GA= 5 | github.com/tidwall/match v1.1.1/go.mod h1:eRSPERbgtNPcGhD8UCthc6PmLEQXEWd3PRB5JTxsfmM= 6 | github.com/tidwall/pretty v1.2.0/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 7 | github.com/tidwall/pretty v1.2.1 h1:qjsOFOWWQl+N3RsoF5/ssm1pHmJJwhjlSbZ51I6wMl4= 8 | github.com/tidwall/pretty v1.2.1/go.mod h1:ITEVvHYasfjBbM0u2Pg8T2nJnzm8xPwvNhhsoaGGjNU= 9 | github.com/tidwall/sjson v1.2.5 h1:kLy8mja+1c9jlljvWTlSazM7cKDRfJuR/bOJhcY5NcY= 10 | github.com/tidwall/sjson v1.2.5/go.mod h1:Fvgq9kS/6ociJEDnK0Fk1cpYF4FIW6ZF7LAe+6jwd28= 11 | -------------------------------------------------------------------------------- /image/Dockerfile: -------------------------------------------------------------------------------- 1 | # Build wasm_runtime in release mode 2 | 3 | 4 | FROM --platform=$TARGETPLATFORM rust:1.71.0-slim as build-wws 5 | ARG WWS_BUILD_DIR=/usr/src/wws 6 | ARG TARGETPLATFORM 7 | ARG BUILDPLATFORM 8 | WORKDIR $WWS_BUILD_DIR 9 | COPY ./ $WWS_BUILD_DIR/ 10 | RUN echo "Installing build prerequisites" 11 | RUN apt-get update && \ 12 | apt-get install -y --no-install-recommends build-essential 13 | RUN echo "Running on ${BUILDPLATFORM}, building for ${TARGETPLATFORM}" 14 | RUN set -eux; \ 15 | ls -l .; \ 16 | case "${TARGETPLATFORM}" in \ 17 | linux/amd64) bldArch='x86_64-unknown-linux-gnu' ;; \ 18 | linux/arm64) bldArch='aarch64-unknown-linux-gnu' ;; \ 19 | *) echo >&2 "unsupported architecture: $BUILDPLATFORM"; exit 1 ;; \ 20 | esac; \ 21 | rustup target add $bldArch; \ 22 | cargo build --release --features vendored-openssl --target=$bldArch; \ 23 | mkdir ./build; \ 24 | cp ./target/$bldArch/release/wws ./build/wws 25 | 26 | 27 | FROM --platform=$TARGETPLATFORM debian:bullseye-slim 28 | ARG WWS_BUILD_DIR=/usr/src/wws 29 | RUN apt-get update && \ 30 | apt-get install -y --no-install-recommends ca-certificates 31 | RUN mkdir -p /app 32 | RUN mkdir -p /opt 33 | COPY --from=build-wws ${WWS_BUILD_DIR}/build/wws /opt 34 | ENTRYPOINT ["/opt/wws"] 35 | CMD ["/app/", "--host", "0.0.0.0"] 36 | -------------------------------------------------------------------------------- /image/Prebuilt.dockerfile: -------------------------------------------------------------------------------- 1 | # In this case, the binaries should be already created. This Dockerfile 2 | # is mainly used to build the preview / release container images in 3 | # GitHub actions 4 | 5 | # Retrieve the certificates to install runtimes later on. 6 | FROM --platform=$TARGETPLATFORM bitnami/minideb:latest AS sysroot 7 | RUN mkdir -p /target/app /target/opt 8 | RUN install_packages ca-certificates 9 | 10 | # Build the final image 11 | FROM --platform=$TARGETPLATFORM scratch 12 | ARG TARGETPLATFORM 13 | ARG TARGETARCH 14 | LABEL org.opencontainers.image.source=https://github.com/vmware-labs/wasm-workers-server 15 | LABEL org.opencontainers.image.description="Wasm Workers Server is a blazing-fast self-contained server that routes HTTP requests to workers in your filesystem. Everything run in a WebAssembly sandbox." 16 | LABEL org.opencontainers.image.licenses="Apache-2.0" 17 | 18 | COPY --from=sysroot /target/app /app 19 | COPY --from=sysroot /target/opt /opt 20 | COPY --from=sysroot /etc/ssl/certs/ca-certificates.crt /etc/ssl/certs/ca-certificates.crt 21 | COPY --chmod=755 ./wws-$TARGETARCH /opt/wws 22 | 23 | ENTRYPOINT ["/opt/wws"] 24 | CMD ["/app/", "--host", "0.0.0.0"] 25 | -------------------------------------------------------------------------------- /kits/go/worker/bindings/bindings_component_type.o: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/kits/go/worker/bindings/bindings_component_type.o -------------------------------------------------------------------------------- /kits/go/worker/doc.go: -------------------------------------------------------------------------------- 1 | /** 2 | * 3 | * === Go support for WASM Workers Server === 4 | * 5 | * This package provides a simple way to write WASM workers in Go. It uses the gjson, sjson libraries instead 6 | * of Go's standard encoding/json package due to the following reasons: 7 | * -- as of writing this file, the default Go compiler does not support the WASI backend, 8 | * -- TinyGo (which does support WASI) does not support reflection and hence, we need to rely on a JSON library 9 | * that does not use reflection 10 | * 11 | */ 12 | 13 | package worker 14 | -------------------------------------------------------------------------------- /kits/javascript/.gitignore: -------------------------------------------------------------------------------- 1 | node_modules 2 | dist 3 | package-lock.json 4 | 5 | !*.wasm 6 | -------------------------------------------------------------------------------- /kits/javascript/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-workers-quick-js-engine" 3 | version = "0.1.0" 4 | edition = "2021" 5 | 6 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 7 | 8 | [dependencies] 9 | anyhow = "1.0" 10 | javy = { version = "2.0.0", features = ["json"] } 11 | regex = "1.10.1" 12 | # Use an old version until we add support for components. 13 | wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" } 14 | once_cell = "1.18.0" 15 | -------------------------------------------------------------------------------- /kits/javascript/Makefile: -------------------------------------------------------------------------------- 1 | .PHONY: build build-src 2 | 3 | build-src: 4 | cargo build --target wasm32-wasi --release 5 | 6 | build: build-src 7 | wizer --allow-wasi --wasm-bulk-memory true -o ./wasm-workers-quick-js-engine.wasm ./target/wasm32-wasi/release/wasm-workers-quick-js-engine.wasm 8 | -------------------------------------------------------------------------------- /kits/javascript/README.md: -------------------------------------------------------------------------------- 1 | # Use it with JavaScript 2 | 3 | The project already includes the compiled QuickJS engine. To simplify the usage of JS workers, the tool will automatically load this engine and will pass the source code with the request data. 4 | 5 | This project is based on the [quickjs-wasm-rs](https://github.com/Shopify/javy/tree/main/crates/quickjs-wasm-rs) crate from Shopify. 6 | 7 | Check our [examples](/examples) folders to see different workers using this kit. 8 | -------------------------------------------------------------------------------- /kits/javascript/shims/package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "shims", 3 | "version": "1.0.0", 4 | "private": "true", 5 | "main": "index.js", 6 | "scripts": { 7 | "build": "esbuild --bundle ./index.js --tree-shaking=false --outdir=dist --platform=node" 8 | }, 9 | "dependencies": { 10 | "@sinonjs/text-encoding": "^0.7.2", 11 | "@ungap/url-search-params": "^0.2.2", 12 | "esbuild": "0.18.11", 13 | "http-status": "^1.6.2" 14 | } 15 | } 16 | -------------------------------------------------------------------------------- /kits/javascript/shims/types/cache.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Key / Value store from Wasm Workers Server 5 | const Cache = { 6 | state: {}, 7 | init(state) { 8 | this.state = state; 9 | }, 10 | get(key) { 11 | return this.state[key]; 12 | }, 13 | set(key, value) { 14 | this.state[key] = value; 15 | } 16 | }; 17 | 18 | export { Cache }; 19 | -------------------------------------------------------------------------------- /kits/javascript/shims/types/headers.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Define a set of headers. It includes multiple method 5 | // to access and edit them. 6 | class Headers { 7 | constructor(initialHeaders) { 8 | let headers = {}; 9 | 10 | // Initialize the headers 11 | for (const key in initialHeaders) { 12 | let value = initialHeaders[key]; 13 | 14 | // Allow only string values 15 | if (typeof value === "string") { 16 | headers[key] = value; 17 | } 18 | } 19 | 20 | this.headers = headers; 21 | } 22 | 23 | append(key, value) { 24 | this.headers[key] = value; 25 | return value; 26 | } 27 | 28 | set(key, value) { 29 | this.append(key, value); 30 | return value; 31 | } 32 | 33 | delete(key) { 34 | let dropValue = delete this.headers[key]; 35 | return dropValue; 36 | } 37 | 38 | get(key) { 39 | return this.headers[key]; 40 | } 41 | 42 | toJSON() { 43 | return this.headers; 44 | } 45 | } 46 | 47 | export { Headers }; 48 | -------------------------------------------------------------------------------- /kits/javascript/shims/types/index.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // Import the different types. 5 | export { Headers } from "./headers"; 6 | export { Request } from "./request"; 7 | export { Response } from "./response"; 8 | export { Cache } from "./cache"; 9 | -------------------------------------------------------------------------------- /kits/javascript/shims/types/request.js: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | import { Headers } from "./headers"; 5 | 6 | // A request that comes from Wasm Workers Server. 7 | // It contains all the required data. 8 | class Request { 9 | constructor(input) { 10 | this.url = input.url; 11 | this.method = input.method; 12 | this.headers = new Headers(input.headers || {}); 13 | this.body = input.body; 14 | this.params = input.params || {}; 15 | } 16 | 17 | text() { 18 | return this.body; 19 | } 20 | } 21 | 22 | export { Request }; 23 | -------------------------------------------------------------------------------- /kits/javascript/src/error.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | /// List of runtime errors 5 | #[derive(Debug)] 6 | pub enum RuntimeError { 7 | InvalidBinding { invalid_export: String }, 8 | } 9 | -------------------------------------------------------------------------------- /kits/javascript/wasm-workers-quick-js-engine.wasm: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/kits/javascript/wasm-workers-quick-js-engine.wasm -------------------------------------------------------------------------------- /kits/rust/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "wasm-workers-rs" 3 | homepage = "https://workers.wasmlabs.dev/" 4 | documentation = "https://workers.wasmlabs.dev/docs/intro" 5 | version = { workspace = true } 6 | edition = { workspace = true } 7 | authors = { workspace = true } 8 | license = { workspace = true } 9 | repository = { workspace = true } 10 | 11 | [lib] 12 | path = "src/lib.rs" 13 | 14 | [dependencies] 15 | anyhow = "1.0.63" 16 | http = "0.2.8" 17 | worker = { path = "./worker" } 18 | serde = { version = "1.0", features = ["derive"] } 19 | serde_json = "1.0.85" 20 | base64 = "0.21.0" 21 | # Use an old version until we add support for components. 22 | wit-bindgen-rust = { git = "https://github.com/bytecodealliance/wit-bindgen", rev = "cb871cfa1ee460b51eb1d144b175b9aab9c50aba" } 23 | -------------------------------------------------------------------------------- /kits/rust/src/cache.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::collections::HashMap; 5 | 6 | /// A cache system based on snapshots. 7 | pub type Cache = HashMap; 8 | -------------------------------------------------------------------------------- /kits/rust/src/content.rs: -------------------------------------------------------------------------------- 1 | use base64::{engine::general_purpose, Engine as _}; 2 | 3 | /// Identifies the content of a response. In other words, the body. 4 | /// We need this intermediate entity in Rust to be able to expose 5 | /// an array of bytes as response. 6 | /// 7 | /// Note that Wasm Workers Server interacts with modules via 8 | /// serialized UTF-8 JSONs. An array of bytes response may include 9 | /// bytes that cannot be represented as UTF-8. To avoid this 10 | /// limitation, Content is able to encode them as base64. Then, 11 | /// wws will ensure to decode them before sending the bytes to the 12 | /// client. 13 | pub enum Content { 14 | Text(String), 15 | Base64(String), 16 | } 17 | 18 | impl From> for Content { 19 | fn from(s: Vec) -> Content { 20 | Content::Base64(general_purpose::STANDARD.encode(s)) 21 | } 22 | } 23 | 24 | impl From for Content { 25 | fn from(s: String) -> Content { 26 | Content::Text(s) 27 | } 28 | } 29 | -------------------------------------------------------------------------------- /kits/rust/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | mod cache; 5 | mod content; 6 | 7 | pub use cache::Cache; 8 | pub use content::Content; 9 | pub mod io; 10 | 11 | pub use worker::worker; 12 | // Re-export http 13 | pub use http; 14 | 15 | // Bindings! 16 | pub mod bindings; 17 | -------------------------------------------------------------------------------- /kits/rust/worker/Cargo.toml: -------------------------------------------------------------------------------- 1 | [package] 2 | name = "worker" 3 | homepage = "https://workers.wasmlabs.dev/" 4 | documentation = "https://workers.wasmlabs.dev/docs/intro" 5 | version = { workspace = true } 6 | edition = { workspace = true } 7 | authors = { workspace = true } 8 | license = { workspace = true } 9 | repository = { workspace = true } 10 | 11 | # See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html 12 | [lib] 13 | proc-macro = true 14 | path = "src/lib.rs" 15 | 16 | [dependencies] 17 | quote = "1.0.21" 18 | syn = { version = "1.0.99", features = ["full"] } 19 | serde = { version = "1.0", features = ["derive"] } 20 | serde_json = "1.0.85" 21 | http = "0.2.8" 22 | anyhow = "1.0.63" 23 | wasi = "0.11.0" 24 | -------------------------------------------------------------------------------- /kits/rust/worker/src/args.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use std::collections::HashSet; 5 | use syn::parse::{Parse, ParseStream, Result}; 6 | use syn::{punctuated::Punctuated, Ident, Token}; 7 | 8 | /// Parse valid arguments for the worker 9 | pub struct Args { 10 | idents: HashSet, 11 | } 12 | 13 | impl Args { 14 | pub fn has_cache(&self) -> bool { 15 | self.idents.iter().any(|i| *i == "cache") 16 | } 17 | 18 | pub fn has_params(&self) -> bool { 19 | self.idents.iter().any(|i| *i == "params") 20 | } 21 | } 22 | 23 | impl Parse for Args { 24 | fn parse(args: ParseStream) -> Result { 25 | let vars = Punctuated::::parse_terminated(args)?; 26 | Ok(Args { 27 | idents: vars.into_iter().collect(), 28 | }) 29 | } 30 | } 31 | -------------------------------------------------------------------------------- /kits/rust/worker/src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | mod args; 5 | mod expand; 6 | 7 | use proc_macro::TokenStream; 8 | 9 | // General worker entrypoint. It will bind the input 10 | // with Request and Response objects 11 | #[proc_macro_attribute] 12 | pub fn worker(attr: TokenStream, item: TokenStream) -> TokenStream { 13 | expand::expand_macro(attr, item) 14 | } 15 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/python/3-1/poly.py: -------------------------------------------------------------------------------- 1 | import sys, json, base64 2 | 3 | class Cache: 4 | store = {} 5 | 6 | @classmethod 7 | def init(cls, kv): 8 | cls.store = kv 9 | 10 | @classmethod 11 | def dump(cls): 12 | return cls.store 13 | 14 | @classmethod 15 | def get(cls, key): 16 | return cls.store.get(key) 17 | 18 | @classmethod 19 | def set(cls, key, value): 20 | cls.store[key] = str(value) 21 | 22 | class Request: 23 | def __init__(self, input): 24 | self.method = input["method"] 25 | self.url = input["url"] 26 | self.body = input["body"] 27 | self.headers = input["headers"] 28 | self.params = input["params"] 29 | 30 | # Init the cache 31 | Cache.init(input["kv"]) 32 | 33 | class Response: 34 | def __init__(self, body): 35 | self.body = body 36 | self.status_code = 200 37 | self.headers = {} 38 | 39 | def to_json(self): 40 | content = self.body 41 | encoded = False 42 | 43 | if type(self.body) is bytes: 44 | content = base64.b64encode(self.body).decode('utf-8') 45 | encoded = True 46 | 47 | res = { 48 | 'data': content, 49 | 'status': self.status_code, 50 | 'headers': self.headers, 51 | 'kv': Cache.dump(), 52 | 'base64': encoded 53 | } 54 | 55 | return json.dumps(res) 56 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/python/3-1/wrapper.txt: -------------------------------------------------------------------------------- 1 | from poly import * 2 | 3 | {source} 4 | 5 | res = worker(Request(json.loads(sys.stdin.read()))) 6 | print(res.to_json()) 7 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/python/3/poly.py: -------------------------------------------------------------------------------- 1 | import sys, json; 2 | 3 | class Cache: 4 | store = {} 5 | 6 | @classmethod 7 | def init(cls, kv): 8 | cls.store = kv 9 | 10 | @classmethod 11 | def dump(cls): 12 | return cls.store 13 | 14 | @classmethod 15 | def get(cls, key): 16 | return cls.store.get(key) 17 | 18 | @classmethod 19 | def set(cls, key, value): 20 | cls.store[key] = str(value) 21 | 22 | class Request: 23 | def __init__(self, input): 24 | self.method = input["method"] 25 | self.url = input["url"] 26 | self.body = input["body"] 27 | self.headers = input["headers"] 28 | self.params = input["params"] 29 | 30 | # Init the cache 31 | Cache.init(input["kv"]) 32 | 33 | class Response: 34 | def __init__(self, body): 35 | self.body = body 36 | self.status_code = 200 37 | self.headers = {} 38 | 39 | def to_json(self): 40 | res = { 41 | 'data': self.body, 42 | 'status': self.status_code, 43 | 'headers': self.headers, 44 | 'kv': Cache.dump() 45 | } 46 | return json.dumps(res) 47 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/python/3/wrapper.txt: -------------------------------------------------------------------------------- 1 | from poly import * 2 | 3 | {source} 4 | 5 | res = worker(Request(json.loads(sys.stdin.read()))) 6 | print(res.to_json()) 7 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/ruby/3-1/wrapper.txt: -------------------------------------------------------------------------------- 1 | require_relative "./poly"; 2 | 3 | {source} 4 | 5 | puts "#{worker(json_to_request($stdin.gets.to_s))}" 6 | -------------------------------------------------------------------------------- /metadata/repository/v1/files/ruby/3/wrapper.txt: -------------------------------------------------------------------------------- 1 | require_relative "./poly"; 2 | 3 | {source} 4 | 5 | puts "#{worker(json_to_request($stdin.gets.to_s))}" 6 | -------------------------------------------------------------------------------- /src/commands/main.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use super::runtimes::Runtimes; 5 | use clap::Subcommand; 6 | 7 | /// Available subcommands in the CLI 8 | #[derive(Subcommand, Debug)] 9 | pub enum Main { 10 | #[clap(name = "runtimes")] 11 | Runtimes(Runtimes), 12 | } 13 | -------------------------------------------------------------------------------- /src/commands/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2022 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | // The different commands for the `wws` CLI. 5 | pub(crate) mod main; 6 | pub(crate) mod runtimes; 7 | -------------------------------------------------------------------------------- /src/lib.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | #[cfg(feature = "wws_config")] 5 | pub use wws_config; 6 | #[cfg(feature = "wws_router")] 7 | pub use wws_router; 8 | #[cfg(feature = "wws_server")] 9 | pub use wws_server; 10 | -------------------------------------------------------------------------------- /src/utils/mod.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | pub mod errors; 5 | pub mod options; 6 | pub mod runtimes; 7 | -------------------------------------------------------------------------------- /src/utils/options.rs: -------------------------------------------------------------------------------- 1 | // Copyright 2023 VMware, Inc. 2 | // SPDX-License-Identifier: Apache-2.0 3 | 4 | use crate::Args; 5 | use wws_project::options::{GitOptions, GitReference, Options}; 6 | 7 | /// Create the project options from the CLI arguments 8 | pub fn build_project_options(args: &Args) -> Options { 9 | Options { 10 | local: None, 11 | git: Some(build_git_options(args)), 12 | } 13 | } 14 | 15 | /// Create the Git options from the CLI arguments 16 | pub fn build_git_options(args: &Args) -> GitOptions { 17 | let mut git_opts = GitOptions::default(); 18 | 19 | // This conditional is prioritized: commit > tag > branch 20 | if let Some(commit) = args.git_commit.as_ref() { 21 | git_opts.git_ref = Some(GitReference::Commit(commit.clone())); 22 | } else if let Some(tag) = args.git_tag.as_ref() { 23 | git_opts.git_ref = Some(GitReference::Tag(tag.clone())); 24 | } else if let Some(branch) = args.git_branch.as_ref() { 25 | git_opts.git_ref = Some(GitReference::Branch(branch.clone())); 26 | } 27 | 28 | if let Some(folder) = args.git_folder.as_ref() { 29 | git_opts.folder = Some(folder.clone()); 30 | } 31 | 32 | git_opts 33 | } 34 | -------------------------------------------------------------------------------- /tests/data/metadata/repository.toml: -------------------------------------------------------------------------------- 1 | version = 1 2 | 3 | [[runtimes]] 4 | name = "ruby" 5 | version = "3.2.0+20230118-8aec06d" 6 | status = "active" 7 | args = [ "--", "/src/index.rb" ] 8 | binary = { filename = "ruby.wasm", url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230118-8aec06d/ruby-3.2.0.wasm", checksum = { type = "sha256", value = "e2d91cff05ec59ed9c88aadbd3b477842092054bf24c5d944d5ad6dbafdd3b32" } } 9 | extensions = [ "rb" ] 10 | polyfill = { filename = "poly.rb", url = "https://raw.githubusercontent.com/Angelmmiguel/wws-index-test/main/ruby/poly.rb", checksum = { type = "sha256", value = "2ba09117ed20a05480615b2aaaf6c7cd7f61fa06f4919777d773df2fcbc736cf" } } 11 | template = { filename = "template.txt", url = "https://raw.githubusercontent.com/Angelmmiguel/wws-index-test/main/ruby/template.txt", checksum = { type = "sha256", value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" } } -------------------------------------------------------------------------------- /tests/data/metadata/runtime.toml: -------------------------------------------------------------------------------- 1 | name = "ruby" 2 | version = "3.2.0+20230118-8aec06d" 3 | status = "active" 4 | args = [ "--", "/src/index.rb" ] 5 | binary = { url = "https://github.com/vmware-labs/webassembly-language-runtimes/releases/download/ruby%2F3.2.0%2B20230118-8aec06d/ruby-3.2.0.wasm", filename = "ruby.wasm", checksum = { type = "sha256", value = "e2d91cff05ec59ed9c88aadbd3b477842092054bf24c5d944d5ad6dbafdd3b32" } } 6 | extensions = [ "rb" ] 7 | polyfill = { url = "https://raw.githubusercontent.com/Angelmmiguel/wws-index-test/main/ruby/poly.rb", filename = "poly.rb", checksum = { type = "sha256", value = "2ba09117ed20a05480615b2aaaf6c7cd7f61fa06f4919777d773df2fcbc736cf" } } 8 | template = { url = "https://raw.githubusercontent.com/Angelmmiguel/wws-index-test/main/ruby/template.txt", filename = "template.txt", checksum = { type = "sha256", value = "6d808b4747cf30f82665a38a47e1176513bbdd6ad558c09db03d719e33ad2da0" } } -------------------------------------------------------------------------------- /tests/data/params/[id].wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/[id]/fixed.wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/[id]/sub.wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/fixed.wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/sub/[...all].wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/sub/[id].wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/params/sub/sub/[...all].wasm: -------------------------------------------------------------------------------- 1 | asm -------------------------------------------------------------------------------- /tests/data/public/.keep: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/tests/data/public/.keep -------------------------------------------------------------------------------- /tests/data/public/about/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/tests/data/public/about/index.html -------------------------------------------------------------------------------- /tests/data/public/index.html: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/tests/data/public/index.html -------------------------------------------------------------------------------- /tests/data/public/main.css: -------------------------------------------------------------------------------- https://raw.githubusercontent.com/webassemblylabs/wasm-workers-server/ba965ceff2fd66317767d2fc3e7e4b4c7199e6af/tests/data/public/main.css -------------------------------------------------------------------------------- /wit/core/http-types.wit: -------------------------------------------------------------------------------- 1 | // URI 2 | type uri = string 3 | 4 | // HTTP Status 5 | type http-status = u16 6 | 7 | // Header 8 | type http-header = tuple 9 | type http-headers = list 10 | 11 | // Methods 12 | enum http-method { 13 | get, 14 | post, 15 | put, 16 | patch, 17 | delete, 18 | options, 19 | head 20 | } 21 | 22 | // URL params 23 | type http-param = tuple 24 | type http-params = list 25 | 26 | // The body content 27 | type http-body = list 28 | 29 | // A complete HTTP request 30 | record http-request { 31 | body: option, 32 | headers: http-headers, 33 | method: http-method, 34 | params: http-params, 35 | uri: uri, 36 | } 37 | 38 | // Return information about a failed request 39 | record http-request-error { 40 | error: http-error, 41 | message: string 42 | } 43 | 44 | // A complete HTTP response 45 | record http-response { 46 | body: option, 47 | headers: http-headers, 48 | status: http-status, 49 | } 50 | 51 | // The list of errors 52 | enum http-error { 53 | invalid-request, 54 | invalid-request-body, 55 | invalid-response-body, 56 | not-allowed, 57 | internal-error, 58 | timeout, 59 | redirect-loop, 60 | } 61 | -------------------------------------------------------------------------------- /wit/core/http.wit: -------------------------------------------------------------------------------- 1 | use * from http-types 2 | 3 | // Send a HTTP request from inside the worker. 4 | send-http-request: func(request: http-request) -> expected 5 | -------------------------------------------------------------------------------- /wit/go-ephemeral/http-types.wit: -------------------------------------------------------------------------------- 1 | default interface http-types { 2 | // URI 3 | type uri = string 4 | 5 | // HTTP Status 6 | type http-status = u16 7 | 8 | // Header 9 | type http-header = tuple 10 | type http-headers = list 11 | 12 | // Methods 13 | enum http-method { 14 | get, 15 | post, 16 | put, 17 | patch, 18 | delete, 19 | options, 20 | head 21 | } 22 | 23 | // URL params 24 | type http-param = tuple 25 | type http-params = list 26 | 27 | // The body content 28 | type http-body = list 29 | 30 | // A complete HTTP request 31 | record http-request { 32 | body: option, 33 | headers: http-headers, 34 | method: http-method, 35 | params: http-params, 36 | uri: uri, 37 | } 38 | 39 | // Return information about a failed request 40 | record http-request-error { 41 | error: http-error, 42 | message: string 43 | } 44 | 45 | // A complete HTTP response 46 | record http-response { 47 | body: option, 48 | headers: http-headers, 49 | status: http-status, 50 | } 51 | 52 | // The list of errors 53 | enum http-error { 54 | invalid-request, 55 | invalid-request-body, 56 | invalid-response-body, 57 | not-allowed, 58 | internal-error, 59 | timeout, 60 | redirect-loop, 61 | } 62 | } 63 | -------------------------------------------------------------------------------- /wit/go-ephemeral/http.wit: -------------------------------------------------------------------------------- 1 | interface http-interface { 2 | use pkg.http-types.{http-request,http-response,http-request-error} 3 | 4 | // Send a HTTP request from inside the worker. 5 | send-http-request: func(request: http-request) -> result 6 | } 7 | 8 | default world bindings { 9 | // Send a HTTP request from inside the worker. 10 | import http: self.http-interface 11 | } 12 | --------------------------------------------------------------------------------