From 91e7edf4bf9705b67e344142824eea5a0a0f23f9 Mon Sep 17 00:00:00 2001
From: sapphi-red <49056869+sapphi-red@users.noreply.github.com>
Date: Fri, 4 Oct 2024 17:30:34 +0900
Subject: [PATCH] fix: error on wss listening but server not listening

---
 packages/vite/src/node/server/ws.ts | 19 ++++++++++++++++---
 1 file changed, 16 insertions(+), 3 deletions(-)

diff --git a/packages/vite/src/node/server/ws.ts b/packages/vite/src/node/server/ws.ts
index ee6fe8e33b6cfa..c379d76ede6b6c 100644
--- a/packages/vite/src/node/server/ws.ts
+++ b/packages/vite/src/node/server/ws.ts
@@ -159,14 +159,27 @@ export function createWebSocketServer(
       })
       res.end(body)
     }) as Parameters<typeof createHttpServer>[1]
+    // vite dev server in middleware mode
+    // need to call ws listen manually
     if (httpsOptions) {
       wsHttpServer = createHttpsServer(httpsOptions, route)
     } else {
       wsHttpServer = createHttpServer(route)
     }
-    // vite dev server in middleware mode
-    // need to call ws listen manually
-    wss = new WebSocketServerRaw({ server: wsHttpServer })
+    wss = new WebSocketServerRaw({ noServer: true })
+    wsHttpServer.on('upgrade', (req, socket, head) => {
+      const protocol = req.headers['sec-websocket-protocol']!
+      if (protocol === 'vite-ping' && server && !server.listening) {
+        // reject connection to tell the vite/client that the server is not ready
+        // if the http server is not listening
+        // because the ws server listens before the http server listens
+        req.destroy()
+        return
+      }
+      wss.handleUpgrade(req, socket as Socket, head, (ws) => {
+        wss.emit('connection', ws, req)
+      })
+    })
   }
 
   wss.on('connection', (socket) => {