Photo by Markus Winkler on Unsplash
Writing Wasm MicroServices with Node.js and Extism
How to write a host application with Node.js
With the help of Extism, writing a host application (i.e. an application capable of running WebAssembly plugins) is relatively easy. We have seen in a previous article how to do it in Go. Today we will do it with Node.js. You will know that it is straightforward, but this example will allow us to go further and discover how to write host functions (in a future article).
This HTTP server application will serve the WebAssembly plugin as a MicroService. And we will use the WebAssembly plugin developed with TinyGo that we did in a previous article.
Prerequisites
You will need
Go (v1.20) and TinyGo (v0.28.1) to compile the plugins
Extism 0.4.0: Install Extism
Node.js (v19.9.0) (this is the version I use)
Creating the application
Installing dependencies
In a directory, create a file package.json
with the following content:
{
"dependencies": {
"@extism/extism": "^0.4.0",
"fastify": "^4.20.0"
},
"type": "module"
}
Fastify is a Node.js project that allows you to develop web application servers (server-side), like Express.js. But you can use whatever you want.
Then, type the command below to install the necessary dependencies:
npm install
Developing the application
Create a file server.js
with the following content:
import Fastify from 'fastify'
import process from "node:process"
import { Context } from '@extism/extism'
import { readFileSync } from 'fs'
let wasmFile = "../01-simple-go-plugin/simple.wasm"
let functionName = "say_hello"
let httpPort = 7070
let wasm = readFileSync(wasmFile) // 1️⃣
const fastify = Fastify({
logger: true
})
const opts = {}
// 2️⃣
let ctx = new Context()
let plugin = ctx.plugin(wasm, true, [])
// Create and start the HTTP server
const start = async () => {
fastify.post('/', opts, async (request, reply) => { // 3️⃣
// 4️⃣
let buf = await plugin.call(functionName, request.body);
let result = buf.toString()
return result
})
try { // 5️⃣
await fastify.listen({ port: httpPort, host: '0.0.0.0'})
} catch (err) {
fastify.log.error(err)
process.exit(1)
}
}
start().then(r => console.log("😄 started"))
1: load the WebAssembly plugin file.
2: create an Extism context and use it to initialize the Wasm plugin.
3: define a route (endpoint) of the HTTP server. The code will be executed on each HTTP POST call of
http://localhost:7070
.4: call the function of the module with as parameters the name of the function (
say_hello
) and the data posted by the HTTP request, and return the result.5: start the HTTP server.
Start the HTTP server
Simply use this command:
node server.js
Call the MicroService
To call the MicroService, use this simple curl
command:
curl -X POST http://localhost:7070 \
-H 'Content-Type: text/plain; charset=utf-8' \
-d 'Jane Doe'
And you will get:
👋 Hello Jane Doe
😍 You see that with the plugin system proposed by Extism, it becomes effortless to write polyglot MicroServices and to offer them using Node.js. You are not far from having the basics to write a FaaS (but that will be another story, probably later 😉). I'll let you experiment with what we've seen today.
The following article will reuse this example, and I will remind the concept of host functions and how to write them to bring additional features to WebAssembly plugins.