diff --git a/assistant-module/src/config/index.ts b/assistant-module/src/config/index.ts index 4cbf773..e1c9a66 100644 --- a/assistant-module/src/config/index.ts +++ b/assistant-module/src/config/index.ts @@ -4,7 +4,6 @@ import fs from 'fs'; import { checkFileExists, createDir } from '../file/index.ts'; import { ProxyInfo } from '../proxy/proxy.ts'; -export const kevisualUrl = 'https://kevisual.xiongxiao.me'; const configDir = createDir(path.join(homedir(), '.config/envision')); export const configPath = path.join(configDir, 'assistant-config.json'); export const appConfigPath = path.join(configDir, 'assistant-app-config.json'); @@ -51,8 +50,8 @@ export const setConfig = (config?: AssistantConfig) => { if (!config) { return assistantConfig; } - assistantConfig = config; - fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); + assistantConfig = { ...assistantConfig, ...config }; + fs.writeFileSync(configPath, JSON.stringify(assistantConfig, null, 2)); return assistantConfig; }; type AppConfig = { @@ -71,9 +70,11 @@ export const getAppConfig = (): AppConfig => { return JSON.parse(fs.readFileSync(appConfigPath, 'utf8')); }; -export const setAppConfig = (config: AppConfig) => { - fs.writeFileSync(appConfigPath, JSON.stringify(config, null, 2)); - return config; +export const setAppConfig = (config: AppConfig) => { + const _config = getAppConfig(); + const _saveConfig = { ..._config, ...config }; + fs.writeFileSync(appConfigPath, JSON.stringify(_saveConfig, null, 2)); + return _saveConfig; }; export const addAppConfig = (app: any) => { diff --git a/assistant-module/src/https/cookie-rewrite.ts b/assistant-module/src/https/cookie-rewrite.ts new file mode 100644 index 0000000..cdfda22 --- /dev/null +++ b/assistant-module/src/https/cookie-rewrite.ts @@ -0,0 +1,27 @@ +export function rewriteCookieDomain(cookie: string, domainRewrite: string | Record) { + if (!domainRewrite) return cookie; + + // 解析 Cookie 的属性 + const parts = cookie.split(';').map((part) => part.trim()); + const nameValue = parts[0]; + const attributes = parts.slice(1); + + // 查找并替换 Domain 属性 + const newAttributes = attributes.map((attr) => { + if (attr.startsWith('Domain=')) { + const originalDomain = attr.slice(7); // 去掉 "Domain=" + let newDomain = domainRewrite; + + // 如果 domainRewrite 是对象,根据映射关系替换 + if (typeof domainRewrite === 'object') { + newDomain = domainRewrite[originalDomain] || originalDomain; + } + + return `Domain=${newDomain}`; + } + return attr; + }); + + // 重新组合 Cookie + return [nameValue, ...newAttributes].join('; '); +} diff --git a/assistant-module/src/proxy/api-proxy.ts b/assistant-module/src/proxy/api-proxy.ts index 5a5c5e2..56381d8 100644 --- a/assistant-module/src/proxy/api-proxy.ts +++ b/assistant-module/src/proxy/api-proxy.ts @@ -1,6 +1,6 @@ import http from 'http'; import https from 'https'; - +import { rewriteCookieDomain } from '../https/cookie-rewrite.ts'; import { ProxyInfo } from './proxy.ts'; export const defaultApiProxy = [ { @@ -29,7 +29,8 @@ export const createApiProxy = (api: string, paths: string[] = ['/api', '/v1', '/ }; export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => { - const _u = new URL(req.url, `${proxyApi.target}`); + const { target } = proxyApi; + const _u = new URL(req.url, `${target}`); console.log('proxyApi', req.url, _u.href); // 设置代理请求的目标 URL 和请求头 let header: any = {}; @@ -40,16 +41,16 @@ export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, pr const headers = Object.keys(req.headers).filter((item) => item && item.toLowerCase() !== 'host'); headers.forEach((item) => { if (item.toLowerCase() === 'origin') { - header.origin = new URL(proxyApi.target).origin; + header.origin = new URL(target).origin; return; } if (item.toLowerCase() === 'referer') { - header.referer = new URL(req.url, proxyApi.target).href; + header.referer = new URL(req.url, target).href; return; } header[item] = req.headers[item]; }); - const options = { + const options: http.RequestOptions = { host: _u.hostname, path: req.url, method: req.method, @@ -57,7 +58,7 @@ export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, pr ...header, }, }; - console.log('options', JSON.stringify(options, null, 2)); + // console.log('options', JSON.stringify(options, null, 2)); if (_u.port) { // @ts-ignore options.port = _u.port; @@ -65,6 +66,12 @@ export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, pr const httpProxy = _u.protocol === 'https:' ? https : http; // 创建代理请求 const proxyReq = httpProxy.request(options, (proxyRes) => { + // Modify the 'set-cookie' headers using rewriteCookieDomain + if (proxyRes.headers['set-cookie']) { + proxyRes.headers['set-cookie'] = proxyRes.headers['set-cookie'].map((cookie) => + rewriteCookieDomain(cookie, 'localhost') + ); + } // 将代理服务器的响应头和状态码返回给客户端 res.writeHead(proxyRes.statusCode, proxyRes.headers); // 将代理响应流写入客户端响应 diff --git a/assistant-module/src/proxy/file-proxy.ts b/assistant-module/src/proxy/file-proxy.ts index c96af8c..48d01b4 100644 --- a/assistant-module/src/proxy/file-proxy.ts +++ b/assistant-module/src/proxy/file-proxy.ts @@ -35,7 +35,7 @@ export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, p if (ext === '.html') { maxAge = 0; } - let sendFilePath = filePath.replace(rootPath + '/', ''); + let sendFilePath = path.relative(rootPath, filePath); const file = send(req, sendFilePath, { root: rootPath, maxAge, diff --git a/assistant-module/src/proxy/proxy.ts b/assistant-module/src/proxy/proxy.ts index a7a3c0e..449ae7f 100644 --- a/assistant-module/src/proxy/proxy.ts +++ b/assistant-module/src/proxy/proxy.ts @@ -1,6 +1,12 @@ export type ProxyInfo = { path?: string; + /** + * 目标地址 + */ target?: string; + /** + * 类型 + */ type?: 'static' | 'dynamic' | 'minio'; /** * 首要文件,比如index.html, 设置了首要文件,如果文件不存在,则访问首要文件 diff --git a/package.json b/package.json index 9bf460d..24fbf47 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "assistant-center", - "version": "0.0.1", + "version": "0.0.4", "description": "", "main": "index.js", "app": { @@ -74,5 +74,6 @@ "tsx": "^4.19.3", "typescript": "^5.8.2" }, - "pnpm": {} -} \ No newline at end of file + "pnpm": {}, + "packageManager": "pnpm@9.14.4" +} diff --git a/src/dev.ts b/src/dev.ts index 8145c94..078043d 100644 --- a/src/dev.ts +++ b/src/dev.ts @@ -12,7 +12,7 @@ app console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); app.listen(51016, () => { - console.log('Router App is running on https://localhost:51015'); + console.log('Router App is running on https://localhost:51016'); }); app.server.on(proxyRoute); diff --git a/src/main.ts b/src/main.ts index 0420112..332e309 100644 --- a/src/main.ts +++ b/src/main.ts @@ -1,7 +1,6 @@ import { app } from './index.ts'; import { proxyRoute } from './proxy-route/index.ts'; import getPort, { portNumbers } from 'get-port'; -console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); // 检车端口可用性 const isPortAvailable = await getPort({ port: portNumbers(51015, 52000) }); if (!isPortAvailable) { diff --git a/src/modules/config/index.ts b/src/modules/config/index.ts index 06673a7..488f7cf 100644 --- a/src/modules/config/index.ts +++ b/src/modules/config/index.ts @@ -1,78 +1,20 @@ -import path from 'path'; -import { homedir } from 'os'; -import fs from 'fs'; -import { checkFileExists, createDir } from '../file/index.ts'; +import { + getCacheAssistantConfig, + setConfig, + getConfig, + getAppConfig, + setAppConfig, + configPath, + appConfigPath, + appDir, + LocalElectronAppUrl, +} from '@kevisual/assistant-module/assistant-config'; -export const kevisualUrl = 'https://kevisual.xiongxiao.me'; -const configDir = createDir(path.join(homedir(), '.config/envision')); -export const configPath = path.join(configDir, 'assistant-config.json'); -export const appConfigPath = path.join(configDir, 'assistant-app-config.json'); -export const appDir = createDir(path.join(configDir, 'assistant-app/frontend')); -export const LocalElectronAppUrl = 'https://assistant.app/user/tiptap/'; +export const kevisualUrl = process.env.KEVISUAL_URL || 'https://kevisual.xiongxiao.me'; -type AssistantConfig = { - pageApi?: string; // https://kevisual.silkyai.cn - loadURL?: string; // https://assistant.app/user/tiptap/ - proxy?: { user: string; key: string; path: string }[]; -}; -let assistantConfig: AssistantConfig; -export const getConfig = () => { - try { - if (!checkFileExists(configPath)) { - fs.writeFileSync(configPath, JSON.stringify({ proxy: [] }, null, 2)); - return { - loadURL: LocalElectronAppUrl, - pageApi: '', - proxy: [], - }; - } - assistantConfig = JSON.parse(fs.readFileSync(configPath, 'utf8')); - return assistantConfig; - } catch (error) { - console.error(error); - return { - loadURL: LocalElectronAppUrl, - pageApi: '', - proxy: [], - }; - } -}; -export const getCacheAssistantConfig = () => { - if (assistantConfig) { - return assistantConfig; - } - return getConfig(); -}; +export { configPath, appConfigPath, appDir, LocalElectronAppUrl }; -export const setConfig = (config?: AssistantConfig) => { - if (!config) { - return assistantConfig; - } - assistantConfig = { ...assistantConfig, ...config }; - fs.writeFileSync(configPath, JSON.stringify(assistantConfig, null, 2)); - return assistantConfig; -}; -type AppConfig = { - list: any[]; -}; -/** - * 应用配置 - * @returns - */ -export const getAppConfig = (): AppConfig => { - if (!checkFileExists(appConfigPath)) { - return { - list: [], - }; - } - return JSON.parse(fs.readFileSync(appConfigPath, 'utf8')); -}; - -export const setAppConfig = (config: AppConfig) => { - const _config = getAppConfig(); - fs.writeFileSync(appConfigPath, JSON.stringify({ ..._config, ...config }, null, 2)); - return config; -}; +export { getCacheAssistantConfig, setConfig, getConfig, getAppConfig, setAppConfig }; export const addAppConfig = (app: any) => { const config = getAppConfig(); diff --git a/src/modules/parent-msg.ts b/src/modules/parent-msg.ts new file mode 100644 index 0000000..beb789b --- /dev/null +++ b/src/modules/parent-msg.ts @@ -0,0 +1,13 @@ +// process.send({ +// type: 'fork', +// data: { +// port: isPortAvailable, +// }, +// }); + +export const reload = () => { + process.send({ + type: 'reload', + data: {}, + }); +}; diff --git a/src/proxy-route/index.ts b/src/proxy-route/index.ts index 90a2ec4..aa32da0 100644 --- a/src/proxy-route/index.ts +++ b/src/proxy-route/index.ts @@ -19,7 +19,7 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp } // client, api, v1, serve 开头的拦截 const apiProxyList = assistantConfig?.apiProxyList || []; - const defaultApiProxy = createApiProxy(assistantConfig?.pageApi || 'https://kevisual.xiongxiao.me'); + const defaultApiProxy = createApiProxy(assistantConfig?.pageApi || 'https://kevisual.silkyai.cn'); const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path)); if (apiBackendProxy) { console.log('apiBackendProxy', apiBackendProxy, req.url); @@ -63,6 +63,11 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp console.log('handle by router 404', req.url); res.statusCode = 404; res.end('Not Found Proxy'); + // console.log('getCacheAssistantConfig().pageApi', getCacheAssistantConfig().pageApi); + // return apiProxy(req, res, { + // path: url.pathname, + // target: getCacheAssistantConfig().pageApi, + // }); }; const localProxyProxyList = [ { diff --git a/src/route/config/index.ts b/src/route/config/index.ts index 6afd088..b0f1207 100644 --- a/src/route/config/index.ts +++ b/src/route/config/index.ts @@ -1,5 +1,6 @@ import { app } from '@/app.ts'; import { getCacheAssistantConfig, setConfig } from '@/modules/config/index.ts'; +import { reload } from '@/modules/parent-msg.ts'; app .route({ @@ -19,6 +20,7 @@ app }) .define(async (ctx) => { const { data } = ctx.query; + reload(); ctx.body = setConfig(data); })