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をインポートするように指示しています。
//go:wasmimport wasi_snapshot_preview1 sock_listen //go:noescape func sock_listen(fd int32, backlog int32) syscall.Errno