/** * 开发环境代理服务器 * 用于解决跨域问题和统一 API 请求 */ const express = require('express'); const { createProxyMiddleware } = require('http-proxy-middleware'); const cors = require('cors'); const app = express(); const PORT = 8086; // 启用 CORS app.use(cors({ origin: '*', // 允许所有源,开发环境使用 credentials: true, methods: ['GET', 'POST', 'PUT', 'DELETE', 'OPTIONS', 'PATCH'], allowedHeaders: [ 'Content-Type', 'Authorization', 'X-Requested-With', 'Accept', // 自定义请求头 'cmdId', 'datetime', 'pwds', 'aseqId', 'nc', 'apiName', 'tid', 'custId', 'reqId', 'isMobileOpen', 'languageNum', 'project', 'platform', 'checkOr', 'tbc', 'reqKey', 'signature', 'authorization', ], exposedHeaders: ['cmdId', 'datetime', 'pwds', 'aseqId', 'nc', 'checkOr', 'checkor'], })); // 目标 API 服务器地址 const API_TARGET = process.env.API_TARGET || 'https://51zhh5.notbug.org'; // 代理路径列表 const PROXY_PATHS = ['/api/v1', '/api/v2', '/api/v3']; // 为每个路径配置代理 PROXY_PATHS.forEach((path) => { app.use( path, createProxyMiddleware({ target: API_TARGET, changeOrigin: true, secure: false, // 如果目标服务器使用自签名证书,设置为 false pathRewrite: (pathStr, req) => { // Express 会自动去掉匹配的前缀,所以需要加回来 const fullPath = path + pathStr; console.log(`[Proxy] Path rewrite: ${pathStr} → ${fullPath}`); return fullPath; }, onProxyReq: (proxyReq, req, res) => { const fullPath = path + req.url; console.log(`[Proxy] ${req.method} ${fullPath} → ${API_TARGET}${fullPath}`); }, onProxyRes: (proxyRes, req, res) => { const fullPath = path + req.url; console.log(`[Proxy] ${req.method} ${fullPath} ← ${proxyRes.statusCode}`); // 确保 CORS 头被正确设置 res.setHeader('Access-Control-Allow-Origin', '*'); res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS, PATCH'); res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With, Accept, cmdId, datetime, pwds, aseqId, nc, apiName, tid, custId, reqId, isMobileOpen, languageNum, project, platform, checkOr, tbc, reqKey, signature, authorization'); res.setHeader('Access-Control-Expose-Headers', 'cmdId, datetime, pwds, aseqId, nc, checkOr, checkor'); res.setHeader('Access-Control-Allow-Credentials', 'true'); }, onError: (err, req, res) => { console.error('[Proxy Error]', err.message); res.status(500).json({ error: 'Proxy Error', message: err.message, }); }, }) ); }); // 健康检查 app.get('/health', (req, res) => { res.json({ status: 'ok', proxy: API_TARGET, timestamp: new Date().toISOString(), }); }); app.listen(PORT, () => { console.log(` ╔════════════════════════════════════════════════════════╗ ║ 🚀 Proxy Server Running ║ ╠════════════════════════════════════════════════════════╣ ║ Local: http://localhost:${PORT} ║ ║ Target: ${API_TARGET.padEnd(40)} ║ ║ Health: http://localhost:${PORT}/health ║ ╚════════════════════════════════════════════════════════╝ `); });