quarkus-quinoa
quarkus-quinoa copied to clipboard
Handle websocket in dev-mode or document that it is not forwarded (HMR)
Some NodeJS dev-server don't allow to set the websocket port for for hot reload. Currently those websocket connection are not forwarded by Quinoa.
Some other dev-server like Vite allow to change the HMR port, then http is sent and forwarded by Quinoa and HMR is sent to the frontend dev-server (which works great).
When stopping the dev mode, it might end up with an exception:
022-05-30 13:52:08,679 INFO [io.qua.qui.dep.PackageManager] (Thread-40) Stopping Quinoa package manager live coding as a dev service.
2022-05-30 13:52:08,698 ERROR [io.ver.cor.net.imp.ConnectionBase] (vert.x-eventloop-thread-2) Connection reset
2022-05-30 13:52:08,699 ERROR [io.qua.qui.QuinoaDevProxyHandler] (vert.x-eventloop-thread-2) Quinoa failed to forward request, see logs.: java.net.SocketException: Connection reset
at java.base/sun.nio.ch.SocketChannelImpl.throwConnectionReset(SocketChannelImpl.java:394)
at java.base/sun.nio.ch.SocketChannelImpl.read(SocketChannelImpl.java:426)
at io.netty.buffer.PooledByteBuf.setBytes(PooledByteBuf.java:258)
at io.netty.buffer.AbstractByteBuf.writeBytes(AbstractByteBuf.java:1132)
at io.netty.channel.socket.nio.NioSocketChannel.doReadBytes(NioSocketChannel.java:350)
at io.netty.channel.nio.AbstractNioByteChannel$NioByteUnsafe.read(AbstractNioByteChannel.java:151)
at io.netty.channel.nio.NioEventLoop.processSelectedKey(NioEventLoop.java:722)
at io.netty.channel.nio.NioEventLoop.processSelectedKeysOptimized(NioEventLoop.java:658)
at io.netty.channel.nio.NioEventLoop.processSelectedKeys(NioEventLoop.java:584)
at io.netty.channel.nio.NioEventLoop.run(NioEventLoop.java:496)
at io.netty.util.concurrent.SingleThreadEventExecutor$4.run(SingleThreadEventExecutor.java:986)
at io.netty.util.internal.ThreadExecutorMap$2.run(ThreadExecutorMap.java:74)
at io.netty.util.concurrent.FastThreadLocalRunnable.run(FastThreadLocalRunnable.java:30)
at java.base/java.lang.Thread.run(Thread.java:833)
@cescoffier any idea on how we could listen/forward websocket events?
Did you look at https://vertx.io/docs/vertx-core/java/#_websockets?
Did you look at vertx.io/docs/vertx-core/java/#_websockets?
@cescoffier yes I did. But here are my issues:
- How to know if I should handle a given event or not (what if there is a Quarkus Websocket server also)
- How to send event the npm server from Vertx (client in the doc is JS)
- The Quarkus Vertx http server is not accessible from an extension and there is no BuildItem for it. I am not sure it's a good idea to create another one?
I don't understand your first point. Web sockets are not a publish/subscribe thing, it's end to end. I believe you can receive the request and upgrade to a web socket.
About the second point, do you have a channel of communication? A web socket maybe?
About the third point, yes, but a simple route upgrading the connection to a web socket is generally much better.
@cescoffier maybe you can help here. We receive a WebSocket request on 8080 but we need to forward it to 3000 (NextJS).
if (headers.get("Connection").contains("Upgrade")) {
LOG.infof("Quinoa is forwarding web socket: '%s'", request.uri());
Future<ServerWebSocket> fut = request.toWebSocket();
fut.onSuccess(serverWs -> {
LOG.infof("Quinoa is forwarded web socket: '%s'", request.uri());
WebSocketConnectOptions options = new WebSocketConnectOptions()
.setHost(request.localAddress().host())
.setPort(port)
.setURI(uri)
.setAllowOriginHeader(false);
httpClient.webSocket(options, res -> {
WebSocket clientWs = res.result();
clientWs.pipeTo(serverWs);
serverWs.pipeTo(clientWs);
LOG.infof("Connected! ");
});
});
But essentially the goal is we are trying to forward and 8080 WebSocket to 3000 and keep it open for two way communication.
I can see the Next ping-pong but something still isn't working.

OK I think I found the issue. when running raw Next the event.data is a JSON string.

When receiving it from VertX it is a Blob not a string and its breaking Next.

So I am wondering how to have VertX send strings back instead of Blobs?
I got it all working for both NextJS and Vite. PR on the way...