coder/websocket

WASM: support DialOptions.HTTPClient

d-z-m opened this issue · 16 comments

d-z-m commented

Support configuring a custom http.Client for use in a Wasm deployment.

This would support making websocket connections through something like gvisor netstack.

An example of such an http.Client is here.

For Wasm deployment, you cannot pass in a custom http.Client because we use the JS WebSocket API directly and it doesn't let you tunnel websocket connections through things like that. You'd have to wrap the WebSocket itself rather than wrap the WebSocket in something or use a reverse proxy.

d-z-m commented

For Wasm deployment, you cannot pass in a custom http.Client because we use the JS WebSocket API directly and it doesn't let you tunnel websocket connections through things like that.

I had thought you would simply use the http.Client's dial functions to make the websocket connection. Is that not the case?

d-z-m commented

In this case, I don't need the browser API at all, and would like it to behave just like it would in dial.go .

I had thought you would simply use the http.Client's dial functions to make the websocket connection. Is that not the case?

I can't make it any clearer.
Give this file a read https://github.com/nhooyr/websocket/blob/master/ws_js.go to understand what's going on.

d-z-m commented

I understand that to make this library work in a Wasm environment, you hook into the JS WebSocket API directly.

The issue I'm dealing with is: I would like to use the library to make WebSocket connections over a virtual network connection. E.g. an http.Client with a custom http.Transport.

I understand that the golang Wasm http.DefaultClient uses the Fetch API under the hood. However, http.Client still supports custom http.Transports when compiling to Wasm.

Ideally, this library would just sit on top of that, and negotiate the websocket in the normal way it would when compiling for linux x86 (i.e. invoking the http.Client's Dial and DialContext, etc.)

Fair enough, let me look into it. It's been a few years since I wrote the Wasm code.

Ah ok I understand your request now. I'll change things such that *http.Client is an accepted field but ignored with clear documentation if it doesn't have a custom transport.

Or hold on actually so you're compiling not for browsers but for javascript in general. I'm not sure if I should support such a usecase. Then I need to add Accept support too.

d-z-m commented

Ah ok I understand your request now. I'll change things such that *http.Client is an accepted field but ignored with clear documentation if it doesn't have a custom transport.

Nice, this is what I was thinking.

Or hold on actually so you're compiling not for browsers but for javascript in general.

I'm not sure exactly what you mean by this, can you elaborate? I am compiling for browsers, i.e. GOOS=js GOARCH=wasm

I'm not sure exactly what you mean by this, can you elaborate? I am compiling for browsers, i.e. GOOS=js GOARCH=wasm

How could you have a custom transport in a browser? Unless it was through another WebSocket? Or I guess maybe over WebRTC?

d-z-m commented

How could you have a custom transport in a browser? Unless it was through another WebSocket? Or I guess maybe over WebRTC?

You got it, it would be another WebSocket. I.e. your library, but in two different contexts.

Imagine something like Tailscale's web-based ssh client, but instead of ssh, its a WebSocket client.

Alright sounds good, that's a fair use case I should support.

@nhooyr So is this in progress?
I really hope it supports WASM

nhooyr commented

In the release after the next yes.

I would like to second this request, and expand it to use identical DialOptions structs for WASM and non-WASM, with the understanding that certain options are ignored in WASM.

Having different APIs for different build targets makes it very difficult to support multiple platforms. It puts an extra burden on every third-party library that uses this one, regardless of whether or not the third-party library author cares about WASM support.

In particular, https://github.com/stackrox/go-grpc-http1 does not have any special handling for WASM build targets, so when using that library, it fails to compile for WASM.

I'd also like to point out that WASM does not imply that the code is running in the browser.