Building a hello-world http app using TinyGo + wasip2

Rajat Jindal

Aug 13th 2024, 09:30AM

In this blog, we will walk through how to implement a simple http handler using WebAssembly and TinyGo.

Prerequisites

In the previous blog, we walked through how to implement a simple hello world app using WebAssembly and TinyGo. Now, we will extend the app to implement a http handler, and serve it using wasmtime.

To start, lets add github.com/rajatjindal/wasi-go-sdk as our dependency. This sdk provides an easy to use interface on top of wasi's generated bindings.

Note: This SDK will likely be deprecated in favor of spin-go-sdk once the support for wasip2 is merged.

go mod init
go get github.com/rajatjindal/wasi-go-sdk
go mod tidy

Now, we can modify our main.go to initialize a http-handler:

package main

import (
    "fmt"
    "net/http"

    "github.com/rajatjindal/wasi-go-sdk/pkg/wasihttp"
)

func init() {
    wasihttp.Handle(func(w http.ResponseWriter, r *http.Request) {
        w.Header().Add("x-wasi-rocks", "true")
        w.WriteHeader(http.StatusOK)
        fmt.Fprint(w, "Hello Wasi !!")
    })
}

func main() {}

and then build it using TinyGo:

tinygo build -target=wasip2 \
    --wit-package $(go list -mod=readonly -m -f '{{.Dir}}' github.com/rajatjindal/wasi-go-sdk)/wit \
    --wit-world sdk \
    -o main.wasm main.go

There are a few differences between the build commands we used in Hello World app, and this http-handler:

  • We explicitly provide argument --wit-world sdk. This is required because by default TinyGo targets the wit-world cli, which is useful for building cli applications. The sdk wit-world is defined here
  • We provide argument --wit-package with a weird looking string as value. That weird looking string actually is a subcommand to fetch the WIT files from the sdk repo. This is required for building components using TinyGo.

and now we are ready run it using wasmtime

> wasmtime serve -Scli main.wasm
Serving HTTP on http://0.0.0.0:8080/

We need to provide -Scli because we import wasi:cli/environment@0.2.0 in the SDK, and using this option, the wasmtime runtime is configured to link the implementation.

From a different terminal, run the curl:

curl -v http://0.0.0.0:8080/
*   Trying 0.0.0.0:8080...
* Connected to 0.0.0.0 (127.0.0.1) port 8080
> GET / HTTP/1.1
> Host: 0.0.0.0:8080
> User-Agent: curl/8.4.0
> Accept: */*
> 
< HTTP/1.1 200 OK
< x-wasi-rocks: true
< transfer-encoding: chunked
< date: Tue, 13 Aug 2024 03:52:46 GMT
< 

Hello Wasi !!

Congratulations !! We just executed our first http handler using WebAssembly + TinyGo + Wasmtime.