/* * 支持 Range 请求的静态文件服务器(测试用) * python3 -m http.server 不支持 Range,会导致 mp4 无法 seek,故用此替代 * 用法:node scripts/serve.js [端口] */ const http = require('http'); const fs = require('fs'); const path = require('path'); const root = path.resolve(__dirname, '..'); const port = parseInt(process.argv[2] || '8931', 10); const mime = { '.html': 'text/html', '.js': 'text/javascript', '.css': 'text/css', '.png': 'image/png', '.mp4': 'video/mp4', '.json': 'application/json', '.map': 'application/json', '.ico': 'image/x-icon' }; http.createServer((req, res) => { const urlPath = decodeURIComponent(req.url.split('?')[0]); let file = path.join(root, urlPath === '/' ? 'index.html' : urlPath); if (!file.startsWith(root)) { res.writeHead(403); res.end(); return; } fs.stat(file, (err, stat) => { if (err || !stat.isFile()) { res.writeHead(404); res.end('404'); return; } const type = mime[path.extname(file).toLowerCase()] || 'application/octet-stream'; const range = req.headers.range; if (range) { const m = /bytes=(\d*)-(\d*)/.exec(range); let start = m && m[1] ? parseInt(m[1], 10) : 0; let end = m && m[2] ? parseInt(m[2], 10) : stat.size - 1; end = Math.min(end, stat.size - 1); res.writeHead(206, { 'Content-Type': type, 'Content-Range': `bytes ${start}-${end}/${stat.size}`, 'Accept-Ranges': 'bytes', 'Content-Length': end - start + 1 }); fs.createReadStream(file, { start, end }).pipe(res); } else { res.writeHead(200, { 'Content-Type': type, 'Accept-Ranges': 'bytes', 'Content-Length': stat.size }); fs.createReadStream(file).pipe(res); } }); }).listen(port, () => console.log(`静态服务器(支持 Range): http://localhost:${port}`));