generated from tailored/router-template
	fix: 添加rewriteCookieDomain
This commit is contained in:
		| @@ -4,7 +4,6 @@ import fs from 'fs'; | |||||||
| import { checkFileExists, createDir } from '../file/index.ts'; | import { checkFileExists, createDir } from '../file/index.ts'; | ||||||
| import { ProxyInfo } from '../proxy/proxy.ts'; | import { ProxyInfo } from '../proxy/proxy.ts'; | ||||||
|  |  | ||||||
| export const kevisualUrl = 'https://kevisual.xiongxiao.me'; |  | ||||||
| const configDir = createDir(path.join(homedir(), '.config/envision')); | const configDir = createDir(path.join(homedir(), '.config/envision')); | ||||||
| export const configPath = path.join(configDir, 'assistant-config.json'); | export const configPath = path.join(configDir, 'assistant-config.json'); | ||||||
| export const appConfigPath = path.join(configDir, 'assistant-app-config.json'); | export const appConfigPath = path.join(configDir, 'assistant-app-config.json'); | ||||||
| @@ -51,8 +50,8 @@ export const setConfig = (config?: AssistantConfig) => { | |||||||
|   if (!config) { |   if (!config) { | ||||||
|     return assistantConfig; |     return assistantConfig; | ||||||
|   } |   } | ||||||
|   assistantConfig = config; |   assistantConfig = { ...assistantConfig, ...config }; | ||||||
|   fs.writeFileSync(configPath, JSON.stringify(config, null, 2)); |   fs.writeFileSync(configPath, JSON.stringify(assistantConfig, null, 2)); | ||||||
|   return assistantConfig; |   return assistantConfig; | ||||||
| }; | }; | ||||||
| type AppConfig = { | type AppConfig = { | ||||||
| @@ -72,8 +71,10 @@ export const getAppConfig = (): AppConfig => { | |||||||
| }; | }; | ||||||
|  |  | ||||||
| export const setAppConfig = (config: AppConfig) => {   | export const setAppConfig = (config: AppConfig) => {   | ||||||
|   fs.writeFileSync(appConfigPath, JSON.stringify(config, null, 2)); |   const _config = getAppConfig(); | ||||||
|   return config; |   const _saveConfig = { ..._config, ...config }; | ||||||
|  |   fs.writeFileSync(appConfigPath, JSON.stringify(_saveConfig, null, 2)); | ||||||
|  |   return _saveConfig; | ||||||
| }; | }; | ||||||
|  |  | ||||||
| export const addAppConfig = (app: any) => { | export const addAppConfig = (app: any) => { | ||||||
|   | |||||||
							
								
								
									
										27
									
								
								assistant-module/src/https/cookie-rewrite.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										27
									
								
								assistant-module/src/https/cookie-rewrite.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,27 @@ | |||||||
|  | export function rewriteCookieDomain(cookie: string, domainRewrite: string | Record<string, string>) { | ||||||
|  |   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('; '); | ||||||
|  | } | ||||||
| @@ -1,6 +1,6 @@ | |||||||
| import http from 'http'; | import http from 'http'; | ||||||
| import https from 'https'; | import https from 'https'; | ||||||
|  | import { rewriteCookieDomain } from '../https/cookie-rewrite.ts'; | ||||||
| import { ProxyInfo } from './proxy.ts'; | import { ProxyInfo } from './proxy.ts'; | ||||||
| export const defaultApiProxy = [ | 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) => { | 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); |   console.log('proxyApi', req.url, _u.href); | ||||||
|   // 设置代理请求的目标 URL 和请求头 |   // 设置代理请求的目标 URL 和请求头 | ||||||
|   let header: any = {}; |   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'); |   const headers = Object.keys(req.headers).filter((item) => item && item.toLowerCase() !== 'host'); | ||||||
|   headers.forEach((item) => { |   headers.forEach((item) => { | ||||||
|     if (item.toLowerCase() === 'origin') { |     if (item.toLowerCase() === 'origin') { | ||||||
|       header.origin = new URL(proxyApi.target).origin; |       header.origin = new URL(target).origin; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     if (item.toLowerCase() === 'referer') { |     if (item.toLowerCase() === 'referer') { | ||||||
|       header.referer = new URL(req.url, proxyApi.target).href; |       header.referer = new URL(req.url, target).href; | ||||||
|       return; |       return; | ||||||
|     } |     } | ||||||
|     header[item] = req.headers[item]; |     header[item] = req.headers[item]; | ||||||
|   }); |   }); | ||||||
|   const options = { |   const options: http.RequestOptions = { | ||||||
|     host: _u.hostname, |     host: _u.hostname, | ||||||
|     path: req.url, |     path: req.url, | ||||||
|     method: req.method, |     method: req.method, | ||||||
| @@ -57,7 +58,7 @@ export const apiProxy = (req: http.IncomingMessage, res: http.ServerResponse, pr | |||||||
|       ...header, |       ...header, | ||||||
|     }, |     }, | ||||||
|   }; |   }; | ||||||
|   console.log('options', JSON.stringify(options, null, 2)); |   // console.log('options', JSON.stringify(options, null, 2)); | ||||||
|   if (_u.port) { |   if (_u.port) { | ||||||
|     // @ts-ignore |     // @ts-ignore | ||||||
|     options.port = _u.port; |     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 httpProxy = _u.protocol === 'https:' ? https : http; | ||||||
|   // 创建代理请求 |   // 创建代理请求 | ||||||
|   const proxyReq = httpProxy.request(options, (proxyRes) => { |   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); |     res.writeHead(proxyRes.statusCode, proxyRes.headers); | ||||||
|     // 将代理响应流写入客户端响应 |     // 将代理响应流写入客户端响应 | ||||||
|   | |||||||
| @@ -35,7 +35,7 @@ export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, p | |||||||
|     if (ext === '.html') { |     if (ext === '.html') { | ||||||
|       maxAge = 0; |       maxAge = 0; | ||||||
|     } |     } | ||||||
|     let sendFilePath = filePath.replace(rootPath + '/', ''); |     let sendFilePath = path.relative(rootPath, filePath); | ||||||
|     const file = send(req, sendFilePath, { |     const file = send(req, sendFilePath, { | ||||||
|       root: rootPath, |       root: rootPath, | ||||||
|       maxAge, |       maxAge, | ||||||
|   | |||||||
| @@ -1,6 +1,12 @@ | |||||||
| export type ProxyInfo = { | export type ProxyInfo = { | ||||||
|   path?: string; |   path?: string; | ||||||
|  |   /** | ||||||
|  |    * 目标地址 | ||||||
|  |    */ | ||||||
|   target?: string; |   target?: string; | ||||||
|  |   /** | ||||||
|  |    * 类型 | ||||||
|  |    */ | ||||||
|   type?: 'static' | 'dynamic' | 'minio'; |   type?: 'static' | 'dynamic' | 'minio'; | ||||||
|   /** |   /** | ||||||
|    * 首要文件,比如index.html, 设置了首要文件,如果文件不存在,则访问首要文件 |    * 首要文件,比如index.html, 设置了首要文件,如果文件不存在,则访问首要文件 | ||||||
|   | |||||||
| @@ -1,6 +1,6 @@ | |||||||
| { | { | ||||||
|   "name": "assistant-center", |   "name": "assistant-center", | ||||||
|   "version": "0.0.1", |   "version": "0.0.4", | ||||||
|   "description": "", |   "description": "", | ||||||
|   "main": "index.js", |   "main": "index.js", | ||||||
|   "app": { |   "app": { | ||||||
| @@ -74,5 +74,6 @@ | |||||||
|     "tsx": "^4.19.3", |     "tsx": "^4.19.3", | ||||||
|     "typescript": "^5.8.2" |     "typescript": "^5.8.2" | ||||||
|   }, |   }, | ||||||
|   "pnpm": {} |   "pnpm": {}, | ||||||
|  |   "packageManager": "pnpm@9.14.4" | ||||||
| } | } | ||||||
| @@ -12,7 +12,7 @@ app | |||||||
|  |  | ||||||
| console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); | console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); | ||||||
| app.listen(51016, () => { | 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); | app.server.on(proxyRoute); | ||||||
|   | |||||||
| @@ -1,7 +1,6 @@ | |||||||
| import { app } from './index.ts'; | import { app } from './index.ts'; | ||||||
| import { proxyRoute } from './proxy-route/index.ts'; | import { proxyRoute } from './proxy-route/index.ts'; | ||||||
| import getPort, { portNumbers } from 'get-port'; | import getPort, { portNumbers } from 'get-port'; | ||||||
| console.log('httpsConfig', `https://localhost:51015/client/router?path=demo`); |  | ||||||
| // 检车端口可用性 | // 检车端口可用性 | ||||||
| const isPortAvailable = await getPort({ port: portNumbers(51015, 52000) }); | const isPortAvailable = await getPort({ port: portNumbers(51015, 52000) }); | ||||||
| if (!isPortAvailable) { | if (!isPortAvailable) { | ||||||
|   | |||||||
| @@ -1,78 +1,20 @@ | |||||||
| import path from 'path'; | import { | ||||||
| import { homedir } from 'os'; |   getCacheAssistantConfig, | ||||||
| import fs from 'fs'; |   setConfig, | ||||||
| import { checkFileExists, createDir } from '../file/index.ts'; |   getConfig, | ||||||
|  |   getAppConfig, | ||||||
|  |   setAppConfig, | ||||||
|  |   configPath, | ||||||
|  |   appConfigPath, | ||||||
|  |   appDir, | ||||||
|  |   LocalElectronAppUrl, | ||||||
|  | } from '@kevisual/assistant-module/assistant-config'; | ||||||
|  |  | ||||||
| export const kevisualUrl = 'https://kevisual.xiongxiao.me'; | export const kevisualUrl = process.env.KEVISUAL_URL || '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/'; |  | ||||||
|  |  | ||||||
| type AssistantConfig = { | export { configPath, appConfigPath, appDir, LocalElectronAppUrl }; | ||||||
|   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 const setConfig = (config?: AssistantConfig) => { | export { getCacheAssistantConfig, setConfig, getConfig, getAppConfig, setAppConfig }; | ||||||
|   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 const addAppConfig = (app: any) => { | export const addAppConfig = (app: any) => { | ||||||
|   const config = getAppConfig(); |   const config = getAppConfig(); | ||||||
|   | |||||||
							
								
								
									
										13
									
								
								src/modules/parent-msg.ts
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										13
									
								
								src/modules/parent-msg.ts
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,13 @@ | |||||||
|  | // process.send({ | ||||||
|  | //   type: 'fork', | ||||||
|  | //   data: { | ||||||
|  | //     port: isPortAvailable, | ||||||
|  | //   }, | ||||||
|  | // }); | ||||||
|  |  | ||||||
|  | export const reload = () => { | ||||||
|  |   process.send({ | ||||||
|  |     type: 'reload', | ||||||
|  |     data: {}, | ||||||
|  |   }); | ||||||
|  | }; | ||||||
| @@ -19,7 +19,7 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp | |||||||
|   } |   } | ||||||
|   // client, api, v1, serve 开头的拦截 |   // client, api, v1, serve 开头的拦截 | ||||||
|   const apiProxyList = assistantConfig?.apiProxyList || []; |   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)); |   const apiBackendProxy = [...apiProxyList, ...defaultApiProxy].find((item) => pathname.startsWith(item.path)); | ||||||
|   if (apiBackendProxy) { |   if (apiBackendProxy) { | ||||||
|     console.log('apiBackendProxy', apiBackendProxy, req.url); |     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); |   console.log('handle by router 404', req.url); | ||||||
|   res.statusCode = 404; |   res.statusCode = 404; | ||||||
|   res.end('Not Found Proxy'); |   res.end('Not Found Proxy'); | ||||||
|  |   // console.log('getCacheAssistantConfig().pageApi', getCacheAssistantConfig().pageApi); | ||||||
|  |   // return apiProxy(req, res, { | ||||||
|  |   //   path: url.pathname, | ||||||
|  |   //   target: getCacheAssistantConfig().pageApi, | ||||||
|  |   // }); | ||||||
| }; | }; | ||||||
| const localProxyProxyList = [ | const localProxyProxyList = [ | ||||||
|   { |   { | ||||||
|   | |||||||
| @@ -1,5 +1,6 @@ | |||||||
| import { app } from '@/app.ts'; | import { app } from '@/app.ts'; | ||||||
| import { getCacheAssistantConfig, setConfig } from '@/modules/config/index.ts'; | import { getCacheAssistantConfig, setConfig } from '@/modules/config/index.ts'; | ||||||
|  | import { reload } from '@/modules/parent-msg.ts'; | ||||||
|  |  | ||||||
| app | app | ||||||
|   .route({ |   .route({ | ||||||
| @@ -19,6 +20,7 @@ app | |||||||
|   }) |   }) | ||||||
|   .define(async (ctx) => { |   .define(async (ctx) => { | ||||||
|     const { data } = ctx.query; |     const { data } = ctx.query; | ||||||
|  |     reload(); | ||||||
|  |  | ||||||
|     ctx.body = setConfig(data); |     ctx.body = setConfig(data); | ||||||
|   }) |   }) | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user