Delegate non-/ws/runs upgrade requests to Next instead of dropping them

Our upgrade handler on the shared httpServer was destroying every socket
that wasn't for /ws/runs, which silently killed Next's own dev-mode HMR
websocket (/_next/hmr) too - breaking hot reload with no useful error,
just a failed WebSocket connection in the browser console. Delegate to
app.getUpgradeHandler() instead, which must be called after prepare().

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
This commit is contained in:
2026-08-15 19:46:41 +02:00
co-authored by Claude Sonnet 5
parent d3e3360d6e
commit 9dc45f751a
+4 -1
View File
@@ -23,6 +23,8 @@ const app = next({ dev, hostname, port });
const handle = app.getRequestHandler(); const handle = app.getRequestHandler();
app.prepare().then(() => { app.prepare().then(() => {
const nextUpgradeHandler = app.getUpgradeHandler();
const httpServer = createServer((req, res) => { const httpServer = createServer((req, res) => {
handle(req, res); handle(req, res);
}); });
@@ -33,7 +35,8 @@ app.prepare().then(() => {
httpServer.on("upgrade", (req, socket, head) => { httpServer.on("upgrade", (req, socket, head) => {
const { pathname } = new URL(req.url ?? "/", "http://internal"); const { pathname } = new URL(req.url ?? "/", "http://internal");
if (pathname !== "/ws/runs") { if (pathname !== "/ws/runs") {
socket.destroy(); // Anything else (e.g. Next's own dev-mode HMR websocket at /_next/hmr) is Next's to handle.
nextUpgradeHandler(req, socket, head).catch(() => socket.destroy());
return; return;
} }