96 lines
2.5 KiB
JavaScript
96 lines
2.5 KiB
JavaScript
import http from 'http';
|
|
import fs from 'fs';
|
|
import path from 'path';
|
|
import { fileURLToPath } from 'url';
|
|
|
|
const __dirname = path.dirname(fileURLToPath(import.meta.url));
|
|
const DIST_DIR = path.join(__dirname, 'dist');
|
|
const PORT = 5175;
|
|
const API_TARGET = 'http://localhost:8080';
|
|
|
|
const MIME_TYPES = {
|
|
'.html': 'text/html',
|
|
'.js': 'application/javascript',
|
|
'.css': 'text/css',
|
|
'.json': 'application/json',
|
|
'.png': 'image/png',
|
|
'.jpg': 'image/jpeg',
|
|
'.svg': 'image/svg+xml',
|
|
'.ico': 'image/x-icon',
|
|
};
|
|
|
|
function proxyRequest(req, res) {
|
|
const url = API_TARGET + req.url;
|
|
console.log(`[Proxy] ${req.method} ${req.url} -> ${url}`);
|
|
|
|
const options = {
|
|
hostname: 'localhost',
|
|
port: 8080,
|
|
path: req.url,
|
|
method: req.method,
|
|
headers: req.headers,
|
|
};
|
|
|
|
const proxyReq = http.request(options, (proxyRes) => {
|
|
res.writeHead(proxyRes.statusCode, proxyRes.headers);
|
|
proxyRes.pipe(res);
|
|
});
|
|
|
|
proxyReq.on('error', (err) => {
|
|
console.error(`[Proxy Error] ${err.message}`);
|
|
res.writeHead(502, { 'Content-Type': 'application/json' });
|
|
res.end(JSON.stringify({ error: 'Proxy error', message: err.message }));
|
|
});
|
|
|
|
req.pipe(proxyReq);
|
|
}
|
|
|
|
const server = http.createServer((req, res) => {
|
|
console.log(`${new Date().toISOString()} ${req.method} ${req.url}`);
|
|
|
|
// CORS headers
|
|
res.setHeader('Access-Control-Allow-Origin', '*');
|
|
res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
|
res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');
|
|
|
|
if (req.method === 'OPTIONS') {
|
|
res.writeHead(204);
|
|
res.end();
|
|
return;
|
|
}
|
|
|
|
// Proxy API requests
|
|
if (req.url.startsWith('/api')) {
|
|
proxyRequest(req, res);
|
|
return;
|
|
}
|
|
|
|
let filePath = path.join(DIST_DIR, req.url === '/' ? 'index.html' : req.url);
|
|
|
|
// SPA fallback - 如果文件不存在,返回 index.html
|
|
if (!fs.existsSync(filePath) || fs.statSync(filePath).isDirectory()) {
|
|
filePath = path.join(DIST_DIR, 'index.html');
|
|
}
|
|
|
|
const ext = path.extname(filePath);
|
|
const contentType = MIME_TYPES[ext] || 'application/octet-stream';
|
|
|
|
try {
|
|
const content = fs.readFileSync(filePath);
|
|
res.writeHead(200, {
|
|
'Content-Type': contentType,
|
|
'Cache-Control': 'no-cache'
|
|
});
|
|
res.end(content);
|
|
} catch (err) {
|
|
res.writeHead(404);
|
|
res.end('Not Found');
|
|
}
|
|
});
|
|
|
|
server.listen(PORT, '127.0.0.1', () => {
|
|
console.log(`Dev server running at http://127.0.0.1:${PORT}/`);
|
|
console.log(`Serving: ${DIST_DIR}`);
|
|
console.log(`API proxy: -> ${API_TARGET}`);
|
|
});
|