WebAssembly modules that use Azure services

Overview

WAGI samples using Azure services

This is an experimental repository containing WebAssembly modules running on top of WAGI (WebAssembly Gateway Interface, which allows you to run WebAssembly WASI binaries as HTTP handlers) and using Azure services.

Note that this repository is built on experimental code, and it is not guaranteed to be maintained or supported.

What do the examples do?

There are currently two examples in this repository, handler and webhook:

  • handler - this module reads the request body and creates a new blob in Azure Blob Storage, based on the container and blob name from the request's query string. Then, it creates a new message in Azure EventGrid with the blob information (container and blob name).

  • webhook - this module acts as a webhook event subscription for the Azure EventGrid topic. It receives the event that the handler created, reads the event data containing the blob and container name, reads the blob from the storage account, then creates a new Azure Cosmos DB collection using the blob bytes.

  • tf - this is a separate example that performs computer vision inferencing using the MobileNetV2 model, run using the Sonos Tract crate. The module reads the image data from the request body, and first checks the configured Azure Cosmos DB collection if the image's content digest has already been classified previously. If so, it returns the result from the cache. Otherwise, it will run the TensorFlow model on the incoming image, write the result to the cache, then return it.

Building and running

The following tools are required to build and run the samples:

  • wagi, built from this branch
  • just
  • Rust and Cargo, with the wasm32-wasi target configured
  • wasm-opt from Binaryen
  • wasmtime 0.26+ (for compiling the modules to the current platform - this step is optional)
$ rustup target add wasm32-wasi
$ just build
cargo build --release --target wasm32-wasi --bin handler
    Finished release [optimized] target(s) in 0.09s
cargo build --release --target wasm32-wasi --bin webhook
    Finished release [optimized] target(s) in 0.09s
wasm-opt target/wasm32-wasi/release/handler.wasm -O4 -o target/wasm32-wasi/release/handler.wasm
wasm-opt target/wasm32-wasi/release/webhook.wasm -O4 -o target/wasm32-wasi/release/webhook.wasm
wasmtime compile -O target/wasm32-wasi/release/handler.wasm -o target/wasm32-wasi/release/handler.wasmc
wasmtime compile -O target/wasm32-wasi/release/webhook.wasm -o target/wasm32-wasi/release/webhook.wasmc

Before running the sample, the modules, the following have to be configured (create a new wagi.toml file with the values below):

  • the Storage, EventGrid, and Cosmos DB keys and accounts
  • the proper allowed hosts where the modules are allowed to make outbound requests to - these have to be the URL of Azure services (if no allowed hosts are defined for a given module, it is not allowed to make any outbound request).
  • the webhook module has to be publicly available, so that EventGrid can send requests. Then, its endpoint (https:///eventgrid-webhook) has to be configured as a webhook subscription for the EventGrid topic where the handler sends messages (a tutorial on how to configure them through the portal can be found here).
.blob.core.windows.net", "https://..eventgrid.azure.net"] [[module]] # host = "public host" route = "/eventgrid-webhook" module = "target/wasm32-wasi/release/webhook.wasm" environment = { STORAGE_ACCOUNT = "", STORAGE_MASTER_KEY = "", COSMOS_MASTER_KEY= "", COSMOS_ACCOUNT= "", COSMOS_DATABASE = "", COSMOS_COLLECTION = "" } allowed_hosts = ["https://.blob.core.windows.net", "https://.documents.azure.com"] ">
[[module]]
# host = "public host"
route = "/handler"
module = "target/wasm32-wasi/release/handler.wasm"
environment = { STORAGE_ACCOUNT = "", STORAGE_MASTER_KEY = "", TOPIC_HOST_NAME = "", TOPIC_KEY = "" }
allowed_hosts = ["https://.blob.core.windows.net", "https://..eventgrid.azure.net"]


[[module]]
# host = "public host"
route = "/eventgrid-webhook"
module = "target/wasm32-wasi/release/webhook.wasm"
environment = { STORAGE_ACCOUNT = "", STORAGE_MASTER_KEY = "", COSMOS_MASTER_KEY= "", COSMOS_ACCOUNT= "", COSMOS_DATABASE = "", COSMOS_COLLECTION = "" }
allowed_hosts = ["https://.blob.core.windows.net", "https://.documents.azure.com"]

Note that the public endpoint can be temporarily configured through a service like Ngrok.

If Wasmtime was used to compile the modules for the current platform, the extension for the modules in the WAGI config has to be changed to .wasmc (this is to distinguish the modules compiled for the current platform, and is totally optional and non-standard).

Start the server:

$ just run
wagi --config wagi.toml

Then, from another terminal instance:

$ curl '/handler?container=&blob=' -X POST -d 'Some string data'

Writing 16 bytes.
Sent message to host https://.westus2-1.eventgrid.azure.net

This will execute handler module, which creates the blob in storage and sends the message on the configured topic, which generates a new webhook handled by the webhook module, which reads the event data, reads the blob bytes, then creates a new collection in the database.

If everything worked properly, a new collection should have been created in Azure Cosmos DB containing the request data:

{
  "id": "1619945329548",
  "value": "Some string data"
}

The image inferencing sample

Note that this is just an example. The performance and latency seen here can be improved by a wide range of options, such as not waiting to write the cache before returning the result (potentially writing a message to EventGrid so its handler can write the cache).

This sample requires that the Cosmos DB account, key, database, and collection environment variables be set in wagi.toml:

.documents.azure.com"] volumes = { "/" = "./data" } ">
[[module]]
route = "infer"
module = "target/wasm32-wasi/release/tf.wasmc"
environment = { COSMOS_MASTER_KEY= "", COSMOS_ACCOUNT= "", COSMOS_DATABASE = "", COSMOS_COLLECTION = "" }
allowed_hosts = ["https://.documents.azure.com"]
volumes = { "/" = "./data" }

Then, after starting the server, new images can be classified by making requests to the /infer endpoint:

$ time curl -X POST --data-binary "@golden-retriever.jpeg" localhost:3000/infer
The image represents a golden retriever, with 72.71024% accuracy
curl -X POST --data-binary "@golden-retriever.jpeg" localhost:3000/infer  0.00s user 0.00s system 0% cpu 0.945 total

The first time an image content digest is encountered, the inferencing is performed locally, the result written to the cache, then returned. Subsequent requests with the same image data are served directly from the cache:

$ time curl -X POST --data-binary "@golden-retriever.jpeg" localhost:3000/infer
The image represents a golden retriever, with 72.71024% accuracy
curl -X POST --data-binary "@golden-retriever.jpeg" localhost:3000/infer  0.00s user 0.00s system 2% cpu 0.189 total

How does this work?

WAGI uses Wasmtime to instantiate modules that are targeting the WebAssembly System Interface (i.e. wasm32-wasi). Additionally, WAGI also uses the wasi-experimental-http crate to enable outbound HTTP requests. Finally, the samples are using a branch of the Azure Rust SDK that is compilable to WASI.

You might also like...
Simple file sharing with client-side encryption, powered by Rust and WebAssembly
Simple file sharing with client-side encryption, powered by Rust and WebAssembly

Hako Simple file sharing with client-side encryption, powered by Rust and WebAssembly Not feature-packed, but basic functionalities are just working.

bn.js bindings for Rust & WebAssembly with primitive-types support

bn.rs bn.js bindings for Rust & WebAssembly with primitive-types support Write Rust code that uses BN use std::str::FromStr; use primitive_types::{H1

A handy calculator, based on Rust and WebAssembly.
A handy calculator, based on Rust and WebAssembly.

qubit 💥 Visit Website To Use Calculator Example 💥 Visit Website To Use Calculator 2 + 2

A simple compile-to-WebAssembly language rewritten in Rust

chasm A very simple compile-to-WebAssembly language You can play with chasm online. This is a rewrite in Rust of the compiler for the language chasm.

Webassembly binding for Hora Approximate Nearest Neighbor Search Library
Webassembly binding for Hora Approximate Nearest Neighbor Search Library

hora-wasm [Homepage] [Document] [Examples] [Hora] Javascript bidding for the Hora Approximate Nearest Neighbor Search, in WebAssembly way. Features Pe

Stylist is a CSS-in-Rust styling solution for WebAssembly Applications.

Stylist Stylist is a CSS-in-Rust styling solution for WebAssembly Applications. This is a fork of css-in-rust. Install Add the following to your Cargo

A template project to demonstrate how to run WebAssembly functions as sidecar microservices in dapr
A template project to demonstrate how to run WebAssembly functions as sidecar microservices in dapr

Demo and tutorials Live Demo | Tutorial article | Tutorial video 1. Introduction DAPR is a portable, event-driven runtime that makes it easy for any d

A curly-braces infix language that compiles to WebAssembly

CurlyWas CurlyWas is a (still WIP) curly-braces, infix synatx for WebAssembly. The goal is to have as to a 1:1 mapping to the resulting wasm instructi

WebAssembly wrapper for JohnnyMorganz's StyLua

WebAssembly wrapper for JohnnyMorganz's StyLua

Sealed boxes implementation for Rust/WebAssembly.

Sealed boxes for Rust/WebAssembly This Rust crate provides libsodium sealed boxes for WebAssembly. Usage: // Recipient: create a new key pair let reci

Frank Denis 16 Aug 28, 2022
WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies.

WebAssembly Tour WebAssembly on Rust is a bright future in making application runs at the Edge or on the Serverless technologies. We spend a lot of ti

Thang Chung 129 Dec 28, 2022
WebAssembly Service Porter

WebAssembly Service Porter.

henrylee2cn 12 Dec 12, 2022
🚀Wasmer is a fast and secure WebAssembly runtime that enables super lightweight containers to run anywhere

Wasmer is a fast and secure WebAssembly runtime that enables super lightweight containers to run anywhere: from Desktop to the Cloud, Edge and IoT devices.

Wasmer 14.1k Jan 8, 2023
WAGI: WebAssembly Gateway Interface

Write HTTP handlers in WebAssembly with a minimal amount of work

null 724 Jan 6, 2023
A console and web-based Gomoku written in Rust and WebAssembly

?? rust-gomoku A console and web-based Gomoku written in Rust and WebAssembly Getting started with cargo & npm Install required program, run # install

namkyu1999 2 Jan 4, 2022
WebAssembly development with Trunk & Vite.js

Trunk & Vite.js Demo Trunk is a WASM web application bundler for Rust, and Vite.js is next Generation Frontend Tooling. Ok, they are together now for

Libing Chen 6 Nov 24, 2021
darkforest is a console and web-based Roguelike written in Rust and WebAssembly.

darkforest darkforest is a console and web-based Roguelike written in Rust and WebAssembly. Key Features TBA Quick Start TBA How To Contribute Contrib

Chris Ohk 5 Oct 5, 2021
WebAssembly to Lua translator, with runtime

This is a WIP (read: absolutely not ready for serious work) tool for translating WebAssembly into Lua. Support is specifically for LuaJIT, with the se

null 43 Dec 31, 2022
A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly

ESP Stack Trace Decoder A Rust ESP stack trace decoder that can also runs in your browser thanks to WebAssembly. It is composed of a ⌨️ Rust library,

Maxime BORGES 20 Oct 5, 2022