Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

upgradeWebSocket could return a WebSocketStream #14064

Open
MarkTiedemann opened this issue Mar 21, 2022 · 8 comments · May be fixed by #20287
Open

upgradeWebSocket could return a WebSocketStream #14064

MarkTiedemann opened this issue Mar 21, 2022 · 8 comments · May be fixed by #20287
Labels
ext/http related to ext/http suggestion suggestions for new features (yet to be agreed)

Comments

@MarkTiedemann
Copy link
Contributor

Currently, Deno.upgradeWebSocket returns a WebSocket. It could return a WebSocketStream, too, for example:

const conn = await Deno.listen({ port: 80 });
const httpConn = Deno.serveHttp(await conn.accept());
const e = await httpConn.nextRequest();
if (e) {
  const { stream, response } = Deno.upgradeWebSocket(e.request);
  const [_, { writable, readable }] = await Promise.all([
    e.respondWith(response),
    stream.connection,
  ]);
  // Use writable and/or readable
}
@crowlKats
Copy link
Member

crowlKats commented Mar 21, 2022

Yes, this is the plan longterm, and was actually the plan originally to some degree (for both statements, its rather not alongside, but instead of), however, the idea is that the server side and client side use the same API for a smoother experience, but since browsers do not have WebSocketStream yet, this isnt exactly the case

@danopia
Copy link
Contributor

danopia commented May 20, 2023

I'm looking forward to this feature as well 😃 I have Deno programs as both the client and the server, so I get to do the nice W3C streams stuff on the client side, just to deal with the classic WebSocket callbacks on the server side.

@bartlomieju
Copy link
Member

I discussed it with @crowlKats recently and the fact that there's still no spec makes it quite hard to ship in Deno.

@crowlKats anything changed since we spoke about it?

@crowlKats
Copy link
Member

Sadly no, there has been no progress from what I am aware

@korkje
Copy link

korkje commented Aug 24, 2023

Could it make sense to, at least while WebSocketStream is getting all spec'ed and ready, provide an experimental/unstable upgradeWebSocketStream alternative alongside upgradeWebSocket? Would prevent any breaking changes for users, while also letting users choose their preferred API.

@korkje korkje linked a pull request Aug 25, 2023 that will close this issue
@korkje
Copy link

korkje commented Aug 25, 2023

Tried my hand at a PR taking some inspiration from, and trying to improve upon, the earlier PR (#16732) by @crowlKats.

@masx200
Copy link

masx200 commented Jan 29, 2024

export class WebSocketStream {
    public socket: WebSocket;
    public readable: ReadableStream<Uint8Array>;
    public writable: WritableStream<Uint8Array>;

    constructor(socket: WebSocket) {
        this.socket = socket;
        this.readable = new ReadableStream({
            start(controller) {
                socket.onmessage = function ({ data }) {
                    // console.log(data);
                    return controller.enqueue(new Uint8Array(data));
                };
                socket.onerror = (e) => controller.error(e);
                socket.onclose = (/* e */) => controller.close(/* e */);
            },
            cancel(/* reason */) {
                socket.close();
            },
        });
        this.writable = new WritableStream({
            start(controller) {
                socket.onerror = (e) => controller.error(e);
            },
            write(chunk) {
                // console.log(chunk);
                socket.send(chunk);
            },
            close() {
                socket.close();
            },
            abort(e) {
                console.error(e);
                socket.close();
            },
        });
    }
}

@rikka0w0
Copy link

rikka0w0 commented Feb 29, 2024

export class WebSocketStream {

One important feature of the WebSocketStream is the backpressure handling, and this simple wrapper does not support backpressure at all. It is possible to implement backpressure on the outgoing stream via WebSocket: bufferedAmount, but not possible on the incoming stream. Missing the backpressure support can overwhelm the receiver and potentially cause out-of-memory.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
ext/http related to ext/http suggestion suggestions for new features (yet to be agreed)
Projects
None yet
7 participants