import type { IncomingMessage } from 'node:http' import { loadEnv, mergeConfig, type ConfigEnv, type ProxyOptions } from 'vite' // import eslint from 'vite-plugin-eslint' import baseConfig from './vite.config.base' const HIKVISION_PROXY_TIMEOUT = 8000 const proxyTarget = (port: number) => ({ target: `http://127.0.0.1:${port}`, changeOrigin: true, }) /** 读取海康 WebSDK 写入的代理目标 Cookie。 */ function getProxyCookie(request: IncomingMessage, name: string): string { const cookie = request.headers.cookie || '' const matched = cookie.match(new RegExp(`(?:^|;\\s*)${name}=([^;]+)`)) if (!matched) return '' try { return decodeURIComponent(matched[1]) } catch (_error) { return '' } } /** 从 SDK Cookie 解析 WebSocket 端口,并限制只能代理到已配置的录像机。 */ function resolveHikvisionWebSocketTarget(request: IncomingMessage, allowedHost: string, fallbackTarget: string): string { const secureAddress = getProxyCookie(request, 'webVideoCtrlProxyWss') const address = secureAddress || getProxyCookie(request, 'webVideoCtrlProxyWs') if (!address) return fallbackTarget try { const target = new URL(`${secureAddress ? 'wss' : 'ws'}://${address}`) return target.hostname.toLowerCase() === allowedHost.toLowerCase() ? target.toString() : fallbackTarget } catch (_error) { return fallbackTarget } } /** 创建开发环境 Vite 配置。 */ export default ({ mode }: ConfigEnv) => { const env = loadEnv(mode, process.cwd(), '') const apiProxyTarget = env.VITE_API_PROXY_TARGET || 'https://ops-api.apinb.com' const proxy: Record = { '/api': { target: apiProxyTarget, changeOrigin: true, ws: true, rewrite: (path) => path.replace(/^\/api/, ''), }, '/rbac2': proxyTarget(10001), '/Alert': proxyTarget(12427), '/alert': proxyTarget(12427), '/DC-Control': proxyTarget(3031), '/dc-control': proxyTarget(3031), '/dc-network': proxyTarget(12429), '/DC-Hardware': proxyTarget(12450), '/dc-hardware': proxyTarget(12450), '/dc-host': proxyTarget(9030), '/dc-middleware': proxyTarget(12428), '/dc-database': proxyTarget(12580), '/Feedback': proxyTarget(12432), '/feedback': proxyTarget(12432), '/Assets': proxyTarget(12430), '/assets': proxyTarget(12430), '/Logs': proxyTarget(12440), '/logs': proxyTarget(12440), '/Kb': proxyTarget(12434), '/kb': proxyTarget(12434), '/Mgt': proxyTarget(12436), '/mgt': proxyTarget(12436), '/Visual': proxyTarget(12438), '/visual': proxyTarget(12438), } if (env.VITE_HIKVISION_PROXY_TARGET) { const hikvisionHttpTarget = new URL(env.VITE_HIKVISION_PROXY_TARGET) const hikvisionWebSocketTarget = env.VITE_HIKVISION_WS_PROXY_TARGET || `${hikvisionHttpTarget.protocol === 'https:' ? 'wss' : 'ws'}://${hikvisionHttpTarget.host}` proxy['/ISAPI'] = { target: env.VITE_HIKVISION_PROXY_TARGET, changeOrigin: true, secure: false, timeout: HIKVISION_PROXY_TIMEOUT, proxyTimeout: HIKVISION_PROXY_TIMEOUT, } proxy['/SDK'] = { target: env.VITE_HIKVISION_PROXY_TARGET, changeOrigin: true, secure: false, timeout: HIKVISION_PROXY_TIMEOUT, proxyTimeout: HIKVISION_PROXY_TIMEOUT, } proxy['/webSocketVideoCtrlProxy'] = { target: hikvisionWebSocketTarget, changeOrigin: true, secure: false, ws: true, timeout: HIKVISION_PROXY_TIMEOUT, proxyTimeout: HIKVISION_PROXY_TIMEOUT, router: env.VITE_HIKVISION_WS_PROXY_TARGET ? undefined : (request) => resolveHikvisionWebSocketTarget(request, hikvisionHttpTarget.hostname, hikvisionWebSocketTarget), rewrite: (path) => path.replace(/^\/webSocketVideoCtrlProxy/, '/'), } } return mergeConfig( { mode: 'development', server: { open: true, host: '0.0.0.0', headers: { 'Cross-Origin-Embedder-Policy': 'require-corp', 'Cross-Origin-Opener-Policy': 'same-origin', 'Cross-Origin-Resource-Policy': 'cross-origin', }, fs: { strict: true, }, proxy, }, plugins: [ // eslint({ // cache: false, // include: ['src/**/*.ts', 'src/**/*.tsx', 'src/**/*.vue'], // exclude: ['node_modules'], // }), ], }, baseConfig ) }