Files
segnapunti/vite-plugin-websocket.js
davide3011 917850502d fix(dev): evita problemi IPv6 di localhost su ws e proxy controller
Usa fallback a 127.0.0.1 quando l'hostname è localhost/::1 nei client websocket display/controller.

Instrada il proxy del controller dev verso Vite tramite DEV_PROXY_HOST (default 127.0.0.1).

Mostra gli URL locali del server con 127.0.0.1 per una diagnostica coerente su Raspberry/Linux.
2026-02-11 00:52:06 +01:00

132 lines
4.0 KiB
JavaScript

import { WebSocketServer } from 'ws'
import { createServer as createHttpServer, request as httpRequest } from 'http'
import { setupWebSocketHandler } from './src/websocket-handler.js'
import { printServerInfo } from './src/server-utils.js'
const CONTROLLER_PORT = 3001
const DEV_PROXY_HOST = process.env.DEV_PROXY_HOST || '127.0.0.1'
/**
* Plugin Vite che integra un server WebSocket per la gestione dello stato di gioco
* e un server separato sulla porta 3001 per il controller.
* @returns {import('vite').Plugin}
*/
export default function websocketPlugin() {
return {
name: 'vite-plugin-websocket',
configureServer(server) {
// Inizializza un server WebSocket collegato al server HTTP di Vite.
const wss = new WebSocketServer({ noServer: true })
// Registra i gestori WebSocket con la logica di gioco.
setupWebSocketHandler(wss)
// Intercetta le richieste di upgrade WebSocket solo sul path /ws.
server.httpServer.on('upgrade', (request, socket, head) => {
const pathname = new URL(request.url, `http://${request.headers.host}`).pathname
if (pathname === '/ws') {
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request)
})
}
})
// Avvia un server separato per il controller sulla porta 3001.
server.httpServer.once('listening', () => {
const viteAddr = server.httpServer.address()
const vitePort = viteAddr.port
startControllerDevServer(vitePort, wss)
setTimeout(() => printServerInfo(vitePort, CONTROLLER_PORT), 100)
})
}
}
}
/**
* Avvia il server di sviluppo per il controller.
* Fa da proxy verso il dev server di Vite per moduli ES, HMR, e asset.
*/
function startControllerDevServer(vitePort, wss) {
const controllerServer = createHttpServer((req, res) => {
// Se richiesta alla root, riscrive verso controller.html
let targetPath = req.url
if (targetPath === '/' || targetPath === '') {
targetPath = '/controller.html'
}
// Proxy verso il dev server di Vite
const proxyReq = httpRequest(
{
hostname: DEV_PROXY_HOST,
port: vitePort,
path: targetPath,
method: req.method,
headers: {
...req.headers,
host: `${DEV_PROXY_HOST}:${vitePort}`,
},
},
(proxyRes) => {
res.writeHead(proxyRes.statusCode, proxyRes.headers)
proxyRes.pipe(res, { end: true })
}
)
proxyReq.on('error', (err) => {
console.error('[Controller Proxy] Error:', err.message)
if (!res.headersSent) {
res.writeHead(502)
res.end('Proxy error')
}
})
req.pipe(proxyReq, { end: true })
})
// Gestisce l'upgrade WebSocket anche sulla porta del controller
controllerServer.on('upgrade', (request, socket, head) => {
const pathname = new URL(request.url, `http://${request.headers.host}`).pathname
if (pathname === '/ws') {
wss.handleUpgrade(request, socket, head, (ws) => {
wss.emit('connection', ws, request)
})
} else {
// Per l'HMR di Vite, proxare l'upgrade WebSocket verso Vite
const proxyReq = httpRequest({
hostname: DEV_PROXY_HOST,
port: vitePort,
path: request.url,
method: 'GET',
headers: request.headers,
})
proxyReq.on('upgrade', (proxyRes, proxySocket, proxyHead) => {
socket.write(
`HTTP/1.1 101 Switching Protocols\r\n` +
Object.entries(proxyRes.headers)
.map(([k, v]) => `${k}: ${v}`)
.join('\r\n') +
'\r\n\r\n'
)
proxySocket.pipe(socket)
socket.pipe(proxySocket)
})
proxyReq.on('error', (err) => {
console.error('[Controller Proxy] WS upgrade error:', err.message)
socket.destroy()
})
proxyReq.end()
}
})
controllerServer.listen(CONTROLLER_PORT, '0.0.0.0', () => {
console.log(`[Controller] Dev server running on port ${CONTROLLER_PORT}`)
})
}