Stream: wasi

Topic: wasi:http/proxy with partial wasi:cli


view this post on Zulip Randy Reddig (Sep 01 2024 at 15:00):

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:

  1. Require that Go programmers do not import 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.
  2. Implement 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.
  3. Ring-fence use of certain WASI packages (outside of the common set like clocks, random, etc.) in the stdlib using Go build tags. This is workable, but introduces yet another layer of complexity to an already complex build process that WASI and the Component Model mandates.
  4. Implement an adapter for Go binaries that stubs out WASI packages not present in wasi:http/proxy, along the lines of the wasi_snapshot_preview_1 adapter.
  5. Add an option to 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.
  6. Update 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.

view this post on Zulip Pat Hickey (Sep 01 2024 at 16:36):

Approach 5 is more or less what composing with wasi-virt is for

view this post on Zulip Pat Hickey (Sep 01 2024 at 16:37):

Have you looked into that?

view this post on Zulip Randy Reddig (Sep 01 2024 at 22:02):

I’ll take a look at wasi-virt, thanks!

view this post on Zulip Randy Reddig (Sep 01 2024 at 22:13):

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.

view this post on Zulip Alex Crichton (Sep 03 2024 at 14:49):

cc @Luke Wagner you might be able to answer wasi:cli/environment not being in wasi:http/proxy

view this post on Zulip Lann Martin (Sep 03 2024 at 15:09):

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.

view this post on Zulip Lann Martin (Sep 03 2024 at 15:11):

Though looking at Go I think that only applies to unix, so maybe syscall.Getenv could still work with that approach

view this post on Zulip Lann Martin (Sep 03 2024 at 15:12):

I guess that still leaves a large number of libraries including the Go stdlib that are always checking env anyway.

view this post on Zulip Luke Wagner (Sep 03 2024 at 15:12):

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.

Contribute to WebAssembly/wasi-runtime-config development by creating an account on GitHub.
Reading configuration seems like a pretty common use case in the context of HTTP proxies. Now that wasi-runtime-config has made a bunch of progress, we should consider adding import wasi:config/run...

view this post on Zulip Lann Martin (Sep 03 2024 at 15:14):

In terms of future features I would expect defaulted value import to be a good fit for something like GODEBUG

view this post on Zulip Randy Reddig (Sep 03 2024 at 15:24):

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.

view this post on Zulip Randy Reddig (Sep 03 2024 at 15:25):

I was surprised that CWD and args were part of environment too!

view this post on Zulip Brendan Burns (Sep 04 2024 at 20:06):

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.

Simple devcontainer for Golang + WASM development. Contribute to dev-wasm/dev-wasm-go development by creating an account on GitHub.

view this post on Zulip Randy Reddig (Sep 04 2024 at 22:54):

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 23 2024 at 12:05 UTC