// Servidor estático mínimo (sin dependencias) para la suite e2e. // Sirve la raíz del proyecto (carpeta padre de tests/) por HTTP. // Uso: node serve.mjs [puerto] (defecto: env PORT o 4173) import http from "node:http"; import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; const RAIZ = path.resolve(path.dirname(fileURLToPath(import.meta.url)), ".."); const PUERTO = Number(process.argv[2] || process.env.PORT || 4173); const TIPOS = { ".html": "text/html; charset=utf-8", ".css": "text/css; charset=utf-8", ".js": "text/javascript; charset=utf-8", ".mjs": "text/javascript; charset=utf-8", ".json": "application/json; charset=utf-8", ".svg": "image/svg+xml", ".png": "image/png", ".jpg": "image/jpeg", ".jpeg": "image/jpeg", ".webp": "image/webp", ".gif": "image/gif", ".ico": "image/x-icon", ".mp4": "video/mp4", ".mp3": "audio/mpeg", ".ogg": "audio/ogg", ".pdf": "application/pdf", ".txt": "text/plain; charset=utf-8", ".md": "text/markdown; charset=utf-8", }; const servidor = http.createServer((req, res) => { let ruta; try { ruta = decodeURIComponent(new URL(req.url, "http://x").pathname); } catch { res.writeHead(400).end("Petición inválida"); return; } if (ruta.endsWith("/")) ruta += "index.html"; const archivo = path.resolve(RAIZ, "." + ruta); // Evita salir de la raíz (path traversal) if (archivo !== RAIZ && !archivo.startsWith(RAIZ + path.sep)) { res.writeHead(403).end("Prohibido"); return; } fs.stat(archivo, (err, st) => { if (err || !st.isFile()) { res.writeHead(404, { "Content-Type": "text/plain; charset=utf-8" }).end("No encontrado"); return; } res.writeHead(200, { "Content-Type": TIPOS[path.extname(archivo).toLowerCase()] || "application/octet-stream", "Content-Length": st.size, "Cache-Control": "no-store", }); if (req.method === "HEAD") return res.end(); fs.createReadStream(archivo).pipe(res); }); }); servidor.listen(PUERTO, "127.0.0.1", () => { console.log(`WAM mockup servido en http://127.0.0.1:${PUERTO}/ (raíz: ${RAIZ})`); });