github.com
wasip1ではネットワーク関連の機能が一部しかサポートされてないので使えないと思っていたがstealthrocket/netを使うことでできる模様。
こんな感じのDockerfileを用意しておく。このライブラリではWasmEdgeをサポートしているらしいのでそちらをインストール
FROM golang:1.21.4-bookworm
RUN curl -sSf https://raw.githubusercontent.com/WasmEdge/WasmEdge/master/utils/install.sh | bash
COPY main.wasm /main.wasm
あとはGoでhttpサーバを動かす際にライブラリを指定することで実行できるようになっている。ライブラリではWASI環境でソケット操作を行うための関数群を定義されていてそちらを通してWASMランタイムの機能を呼び出してソケット操作をすることで実現しているようです。
package main
import (
"net/http"
"github.com/stealthrocket/net/wasip1"
)
func main() {
listener, err := wasip1.Listen("tcp", "127.0.0.1:3000")
if err != nil {
panic(err)
}
server := &http.Server{
Handler: http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
w.Write([]byte("Hello, World!"))
w.WriteHeader(http.StatusOK)
}),
}
if err := server.Serve(listener); err != nil {
panic(err)
}
}
中身を見る
listenの先を見るとこんな実装がされています。sock_listen()を呼び出してerrnoをチェックしています。
func listen(fd int, backlog int) error {
if errno := sock_listen(int32(fd), int32(backlog)); errno != 0 {
return errno
}
return nil
}
sock_listen()は以下のような実装になっていました。go:wasmimport wasi_snapshot_preview1 sock_listen
はWASMモジュール内でWASIのwasi_snapshot_preview1モジュールからsock_listenをインポートするように指示しています。
func sock_listen(fd int32, backlog int32) syscall.Errno