coder / websocket

Minimal and idiomatic WebSocket library for Go
ISC License
3.95k stars 297 forks source link

WASM: support DialOptions.HTTPClient #373

Open d-z-m opened 1 year ago

d-z-m commented 1 year ago

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.

nhooyr commented 1 year ago

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 1 year ago

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 1 year ago

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 .

nhooyr commented 1 year ago

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 1 year ago

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.)

nhooyr commented 1 year ago

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

nhooyr commented 1 year ago

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.

nhooyr commented 1 year ago

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 1 year ago

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

nhooyr commented 1 year ago

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 1 year ago

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.

nhooyr commented 1 year ago

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

Hoodie-Kang commented 1 year ago

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

nhooyr commented 1 year ago

In the release after the next yes.

flimzy commented 3 months ago

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.

flimzy commented 3 months ago

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