Skip to content

NetworkError caused by WebSocketStream cannot be caught? #22165

Closed

Description

@masx200

Version: Deno 1.40.1

const listener = Deno.listen({ port: 9000, transport: "tcp" });

try {
    for await (const conn of listener) {
        (async () => {
            const ws = new WebSocketStream("ws://loca99999999999lhost:8000", {
                headers: {
                    "x-Protocol": "Transmission Control",
                    "X-Destination-Address": "www.ba99999999999idu.com",
                    "X-Destination-Port": "80",
                },
            });
            // console.log(ws);
            try {
                const webConn = await ws.opened; //.catch(console.error);
                // console.log(webConn);
                conn.readable.pipeTo(webConn.writable).catch(function (e) {
                    try {
                        ws.close();
                        conn.close();
                    } catch (e) {
                        console.error(e);
                    }

                    return console.error(e);
                });
                webConn.readable.pipeTo(conn.writable).catch(function (e) {
                    try {
                        ws.close();
                        conn.close();
                    } catch (e) {
                        console.error(e);
                    }
                    return console.error(e);
                });
            } catch (error) {
                console.error(error);
                try {
                    ws.close();
                    conn.close();
                } catch (e) {
                    console.error(e);
                }
            }
        })().catch(console.error);
    }
} catch (error) {
    console.error(error);
}
deno run --unstable -A ./client.ts
⚠️  The `--unstable` flag is deprecated and will be removed in Deno 2.0. Use granular `--unstable-*` flags instead.
Learn more at: https://docs.deno.com/runtime/manual/tools/unstable_flags
DOMException: failed to connect to WebSocket: 不知道这样的主机。 (os error 11001)
    at new DOMException (ext:deno_web/01_dom_exception.js:116:20)
    at DOMExceptionNetworkError (ext:runtime_main/js/99_main.js:391:12)
    at ext:core/00_infra.js:200:34
    at eventLoopTick (ext:core/01_core.js:59:7)
error: Uncaught (in promise) NetworkError: failed to connect to WebSocket: 不知道这样的主机。 (os error 11001)
curl -I -v localhost:9000 -H host:www.baidu.com
*   Trying [::1]:9000...
*   Trying 127.0.0.1:9000...
* Connected to localhost (127.0.0.1) port 9000
> HEAD / HTTP/1.1
> Host:www.baidu.com
> User-Agent: curl/8.4.0
> Accept: */*
>
* Empty reply from server
* Closing connection
curl: (52) Empty reply from server

Activity

  1. kt3k commented on Jan 29, 2024

    @kt3k
    Contributor

    It looks like you also need to await ws.closed to avoid uncaught error:

     const listener = Deno.listen({ port: 9000, transport: "tcp" });
    
     try {
        for await (const conn of listener) {
            (async () => {
                const ws = new WebSocketStream("ws://loca99999999999lhost:8000", {
                    headers: {
                        "x-Protocol": "Transmission Control",
                        "X-Destination-Address": "www.ba99999999999idu.com",
                        "X-Destination-Port": "80",
                    },
                });
                // console.log(ws);
                try {
                    const webConn = await ws.opened; //.catch(console.error);
                    // console.log(webConn);
                    conn.readable.pipeTo(webConn.writable).catch(function (e) {
                        try {
                            ws.close();
                            conn.close();
                        } catch (e) {
                            console.error(e);
                        }
    
                        return console.error(e);
                    });
                    webConn.readable.pipeTo(conn.writable).catch(function (e) {
                        try {
                            ws.close();
                            conn.close();
                        } catch (e) {
                            console.error(e);
                        }
                        return console.error(e);
                    });
                } catch (error) {
                    console.error(error);
                    try {
                        ws.close();
                        conn.close();
    +                   await ws.closed;
                    } catch (e) {
                        console.error(e);
                    }
                }
            })().catch(console.error);
        }
     } catch (error) {
        console.error(error);
     }
  2. masx200 commented on Jan 29, 2024

    @masx200
    Author

    While this can be solved, can we design a better WebSocketStream api?
    It's too hard to use

  3. masx200 commented on Jan 29, 2024

    @masx200
    Author
    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();
                },
            });
        }
    }
  4. kt3k commented on Jan 29, 2024

    @kt3k
    Contributor

    WebSocketStream is designed based on Web Standard proposal whatwg/websockets#48 It's not a good idea to design it in our own way.

    ref: #8831

  5. kt3k commented on Jan 30, 2024

    @kt3k
    Contributor

    Closing as the original issue is solved and nothing is actionable further.

    While this can be solved, can we design a better WebSocketStream api?
    It's too hard to use

    You are encouraged to create 3rd party module to address those pain points

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions