I’m working on a prototype of wasi-http for Go, starting with TinyGo, that adapts the Go stdlib net/http semantics to wasi-http APIs.
Currently, the wasip2 target in TinyGo targets the wasi:cli/command world, and various parts of the runtime, os, and syscall packages depend on WASI packages imported by wasi:cli/command. One challenge implementing wasi:http/proxy is the lack of certain packages that the stdlib depends on, such as wasi:cli/environment.
The Go net/http package that defines the standard HTTP interfaces imports the os package (among others) that when initialized, make calls that are implemented by WASI packages that are not included in the wasi:http/proxy world.
Fixing this is tricky, and requires potentially invasive surgery to the Go stdlib, or would require Go programmers to not reach for packages they’re familiar with in order to use WASI. Given the tradeoffs, is there a role for wasm-tools or the Component Model standard to address this?
Some options:
net/http or any other stdlib package that imports APIs unimplemented in wasi:http/proxy. I consider this a nonstarter, as Go programmers can and should expect to import stdlib packages with familiar interfaces, and reimplementing them in a third-party package would result in costly duplication of effort, and feature/fix/security gaps.wasi-http as another GOOS target, e.g. GOOS=wasip2-http. This would effectively "freeze" wasi-http support into the stdlib and toolchain, but doesn’t scale—adding a new GOOS has initial and ongoing maintenance costs in Go, and wouldn’t be flexible to support other WASI worlds.wasi:http/proxy, along the lines of the wasi_snapshot_preview_1 adapter.wasm-tools to stub missing imports as no-ops when creating a component, or allow a component to specify that it can survive with missing or unimplemented imports.wasi:http/proxy world (in say, version 0.2.2) to import a "core" set of WASI packages that are, by convention, present in all official WASI worlds, and recommended to be present in vendor-specific worlds. Likely wasi:cli/{environment,stdin,stdout,stderr}, wasi:clocks, wasi:random, wasi:io, and potentially a stubbed/empty wasi:filesystem.Approach 5 is more or less what composing with wasi-virt is for
Have you looked into that?
I’ll take a look at wasi-virt, thanks!
Why was wasi:cli/environment excluded from wasi:http/proxy?
Asking because the Go standard library uses a number of environment variables like GODEBUG for additional telemetry or runtime configuration like GC settings. Removing these would be a challenge (if possible at all), and would further distance WASI from other Go targets.
cc @Luke Wagner you might be able to answer wasi:cli/environment not being in wasi:http/proxy
In general I think we'd prefer that toolchains not target specific worlds but rather just import what a particular program needs. That's a bit hairy for wasi:cli/environment in particular since many language runtimes parse environ unconditionally at init time.
Though looking at Go I think that only applies to unix, so maybe syscall.Getenv could still work with that approach
I guess that still leaves a large number of libraries including the Go stdlib that are always checking env anyway.
The arguments and CWD parts of wasi:cli/environment aren't really meaningful in an HTTP proxy. The env vars could potentially make sense for exposing configuration, but wasi:config/runtime is the better match there, so the idea is to add that once wasi:config/runtime has sufficiently advanced phase, and then let env vars be virtualized in terms of wasi:config/runtime.
Also, at some point in the future, I think the ergonomics of wasi:cli/command would be much-improved to have the currently-imported arguments and CWD be made parameters of the main/run function export so that command components can be imported (e.g., from CPython or Node) and their main called like a function passing arguments as arguments without shenanigans.
For common stuff like time/random/config, though, one idea we've talked about is in the short term is defining a wasi:io/core world that contains the intersection between all the other WASI worlds that toolchains can depend on without knowing the actual target world. Longer-term, I think each of these is a strong candidate for building into the C-M directly, with wasi:io ultimately disappearing so that there are no ubiquitous WASI imports, so wasi:io/core would be considered transitional.
In terms of future features I would expect defaulted value import to be a good fit for something like GODEBUG
Something like wasi:io/core seems reasonable. For Go (and other languages) with libraries or packages that expose knobs via environment variables, having environment variables accessible via wasi:http/proxy and other worlds makes sense.
I was surprised that CWD and args were part of environment too!
fwiw, I have a working implementation of http serving here: https://github.com/dev-wasm/dev-wasm-go/blob/main/webserver/wasi-http/main.go it uses net/http and it doesn't seem to encounter the issues you are running into.
run: main_0_2_0.component.wasm ; WASMTIME_BACKTRACE_DETAILS=1 wasmtime serve -Scommon -Dlogging=y main_0_2_0.component.wasm the -Scommon (or -Scli) is the magic
Last updated: Dec 06 2025 at 06:05 UTC