123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293 |
- // server.js —— 零依赖反向代理版
- const http = require('http');
- const https = require('https');
- const fs = require('fs');
- const path = require('path');
- const url = require('url');
- // 读取配置
- const configPath = process.env.CONFIG_PATH || './runtime-config.json';
- const config = JSON.parse(fs.readFileSync(configPath, 'utf8'));
- //const ROOT = path.join(__dirname, 'dist', 'h5');
- const PORT = config["local-port"];
- const REMOTE = config["remote-host"];//'http://101.43.219.60:7700';
- const mime = { '.html': 'text/html', '.js': 'application/javascript', '.css': 'text/css', '.json': 'application/json', '.png': 'image/png', '.jpg': 'image/jpeg', '.gif': 'image/gif', '.svg': 'image/svg+xml', '.ico': 'image/x-icon' };
- /* ------- 代理函数 ------- */
- function proxyToRemote(req, res) {
- const parsed = url.parse(req.url); // /dr/xxx?query
- const path = parsed.path;
- const target = url.parse(REMOTE);
- const options = {
- hostname: target.hostname,
- port: target.port || (target.protocol === 'https:' ? 443 : 80),
- path: path + (parsed.search || ''),
- method: req.method,
- headers: { ...req.headers } // 原样带过去
- };
- // 删除本地头,避免 host 不匹配
- delete options.headers.host;
- delete options.headers.origin;
- delete options.headers.referer;
- console.log('Options:', options);
- console.log('Path:', options.path);
- const proxyReq = (target.protocol === 'https:' ? https : http).request(options, (proxyRes) => {
- // 把远端响应头原样写给浏览器
- res.writeHead(proxyRes.statusCode, proxyRes.headers);
- proxyRes.pipe(res);
- }).on('error', e => {
- console.error('[proxy error]', e.message);
- res.writeHead(502).end('Bad Gateway');
- });
- req.pipe(proxyReq); // 把浏览器发来的 body 也转发过去
- }
- /* ------- 静态文件服务函数 ------- */
- function serveStatic(req, res) {
- const parsed = url.parse(req.url, true);
- let pathname = parsed.pathname;
- // 默认索引
- if (pathname === '/') pathname = '/index.html';
- // 安全限制:禁止跳出 static
- const safePath = path.normalize(decodeURIComponent(pathname));
- const STATIC_DIR = path.resolve(config.staticPath || './static');
- const filePath = path.join(STATIC_DIR, safePath);
- if (!filePath.startsWith(STATIC_DIR)) {
- res.statusCode = 403;
- res.end('Forbidden');
- return;
- }
- fs.readFile(filePath, (err, data) => {
- if (err) {
- if (err.code === 'ENOENT') {
- res.statusCode = 404;
- res.end('Not Found');
- } else {
- res.statusCode = 500;
- res.end('Internal Server Error');
- }
- return;
- }
- const ext = path.extname(filePath).toLowerCase();
- res.setHeader('Content-Type', mime[ext] || 'application/octet-stream');
- res.end(data);
- });
- }
- /* ------- 主入口 ------- */
- http.createServer((req, res) => {
- // 1. 预检直接 200
- if (req.method === 'OPTIONS') { res.writeHead(200); res.end(); return; }
- // 2. 路径以 /dr 开头 → 代理
- if (req.url.startsWith('/dr')) { proxyToRemote(req, res); return; }
- // 3. 其它 → 静态文件
- serveStatic(req, res);
- }).listen(PORT, () => console.log(`> H5 running at http://localhost:${PORT}`));
|