| 214 | } |
| 215 | |
| 216 | function handleRequest(req, res) { |
| 217 | let urlPath = req.url.split("?")[0]; |
| 218 | if (urlPath === "/") urlPath = "/index.html"; |
| 219 | const relative = path.normalize(urlPath).replace(/^\/+/, ""); |
| 220 | const filePath = path.join(WWW, relative); |
| 221 | if (!filePath.startsWith(WWW + path.sep) && filePath !== WWW) { |
| 222 | res.writeHead(403); |
| 223 | res.end("Forbidden"); |
| 224 | return; |
| 225 | } |
| 226 | |
| 227 | const ext = path.extname(filePath).toLowerCase(); |
| 228 | const contentType = MIME[ext] || "application/octet-stream"; |
| 229 | |
| 230 | fs.readFile(filePath, (err, data) => { |
| 231 | if (err) { |
| 232 | res.writeHead(404); |
| 233 | res.end("Not found"); |
| 234 | return; |
| 235 | } |
| 236 | res.writeHead(200, { |
| 237 | "Content-Type": contentType, |
| 238 | "Access-Control-Allow-Origin": "*", |
| 239 | "Cache-Control": "no-cache, no-store, must-revalidate", |
| 240 | }); |
| 241 | res.end(data); |
| 242 | }); |
| 243 | } |
| 244 | |
| 245 | function broadcast(wss, message) { |
| 246 | if (typeof message !== "string") { |