Hey there,
im have implemented a websocket server in my Fastify Backend running separatly from nuxt in a diffrent docker container on same host. I already got endpoint /api/[...].ts up running which proxies everything to backend:
import { joinURL } from 'ufo'
export default defineEventHandler(async (event) => {
const apiUrl = useRuntimeConfig().apiUrl as string
const target = joinURL(apiUrl, event.path)
return proxyRequest(event, target)
})
Now i noticed that this doesnt work with websockets and even if i enable experimental websocket support in nitro. If i enable the experimental websocket support nitro will boot up and websocket but not proxy it to my backend.
I know that this is an old topic which came up multiple times in the past, however i tried to find a solution to this topic using ChatGPT and Github Copilot which suggested that i build a websocket server using defineWebSocketHandler and put that into <PROJECT_ROOT>/server/api/ws.ts (Route is currently /api/ws on both frontend and backend). However using the following code peice, i get only errors, because the websocket just reconnects without sending any messages.
I got the frontend logic in browser working which sends messages to the nitro server, but the code doesnt send it to the backend.
IMPORTANT: Im in the dev envoirment currently in Jetbrains Webstorm
In Console i get WebSocket Connectet several thousand times over a span of 5 minutes.
import WebSocket from 'ws';
export default defineWebSocketHandler({
open(peer) {
const backend = new WebSocket(peer.request.url);
const queue:string[] = [];
backend.on("open", () => {
console.log("WebSocket opened");
for(const msg of queue) {
backend.send(msg);
}
})
// forward backend messages → client
backend.on('message', (data) => peer.send(data));
peer.websocket.onmessage = (msg) => {
if(backend.readyState !== WebSocket.OPEN) {
queue.push(msg.data as string);
return;
}
console.log("<" + msg.data);
backend.send(msg.data);
}
backend.on('close', () => peer.close());
peer.websocket.onclose = () => backend.close()
},
});
i added the queue because when i send on the frontend, i dont know if the connection to backend is established.
Websocket service connection code:
websocket.requestUpdate(["teams", "status"]);
websocket.requestTeamsList();
websocket.on("*", (message: WebsocketMessage) => {
if(message.type === 'error' && message.data){
error.value = message.data.message;
}
else {
useWebsocketRequestHandler(message);
}
})
onMounted(async () => {
// some other logic
websocket.connect(useAuth().findAccessToken()?.token ?? '');
})
(websocket service in message below)
Nuxt info:
- Operating System:
Windows_NT - Node Version:
v22.19.0 - Nuxt Version:
3.17.5 - CLI Version:
3.25.1 - Nitro Version:
2.11.12 - Package Manager:
npm@10.9.3 - Builder:
- - User Config:
modules,ssr,devtools,site,spaLoadingTemplate,runtimeConfig,build,routeRules,devServer,future,compatibilityDate,vite,typescript,eslint,i18n,image,pwa,security,umami - Runtime Modules:
nuxt-security@2.2.0,@nuxtjs/i18n@9.5.5,@pinia/nuxt@0.11.1,nuxt-umami@3.2.0,@galaxybotweb/components@1.0.133,@nuxt/eslint@1.4.1,@nuxt/image@1.10.0,nuxt-tiptap-editor@2.2.1,@vite-pwa/nuxt@1.0.3,@nuxtjs/robots@5.2.10 - Build Modules:
-