feat: 重构代理功能,添加文件代理支持并优化相关逻辑
This commit is contained in:
@@ -6,19 +6,19 @@ import inquirer from 'inquirer';
|
|||||||
import chalk from 'chalk';
|
import chalk from 'chalk';
|
||||||
|
|
||||||
type InitCommandOptions = {
|
type InitCommandOptions = {
|
||||||
path?: string;
|
workspace?: string;
|
||||||
};
|
};
|
||||||
const Init = new Command('init')
|
const Init = new Command('init')
|
||||||
.description('初始化一个助手客户端,生成配置文件。')
|
.description('初始化一个助手客户端,生成配置文件。')
|
||||||
.option('-p --path <path>', '助手路径,默认为执行命令的目录,如果助手路径不存在则创建。')
|
.option('-w --workspace <workspace>', '助手路径,默认为执行命令的目录,如果助手路径不存在则创建。')
|
||||||
.action((opts: InitCommandOptions) => {
|
.action((opts: InitCommandOptions) => {
|
||||||
// 如果path参数存在,检测path是否是相对路径,如果是相对路径,则转换为绝对路径
|
// 如果workspace参数存在,检测workspace是否是相对路径,如果是相对路径,则转换为绝对路径
|
||||||
if (opts.path && !opts.path.startsWith('/')) {
|
if (opts.workspace && !opts.workspace.startsWith('/')) {
|
||||||
opts.path = path.join(process.cwd(), opts.path);
|
opts.workspace = path.join(process.cwd(), opts.workspace);
|
||||||
} else if (opts.path) {
|
} else if (opts.workspace) {
|
||||||
opts.path = path.resolve(opts.path);
|
opts.workspace = path.resolve(opts.workspace);
|
||||||
}
|
}
|
||||||
const configDir = AssistantInit.detectConfigDir(opts.path);
|
const configDir = AssistantInit.detectConfigDir(opts.workspace);
|
||||||
console.log('configDir', configDir);
|
console.log('configDir', configDir);
|
||||||
const assistantInit = new AssistantInit({
|
const assistantInit = new AssistantInit({
|
||||||
path: configDir,
|
path: configDir,
|
||||||
|
|||||||
@@ -4,12 +4,13 @@ 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';
|
||||||
import dotenv from 'dotenv';
|
import dotenv from 'dotenv';
|
||||||
|
import { logger } from '@/module/logger.ts';
|
||||||
|
|
||||||
let kevisualDir = path.join(homedir(), 'kevisual');
|
let kevisualDir = path.join(homedir(), 'kevisual');
|
||||||
const envKevisualDir = process.env.ASSISTANT_CONFIG_DIR
|
const envKevisualDir = process.env.ASSISTANT_CONFIG_DIR
|
||||||
if (envKevisualDir) {
|
if (envKevisualDir) {
|
||||||
kevisualDir = envKevisualDir;
|
kevisualDir = envKevisualDir;
|
||||||
console.log('使用环境变量 ASSISTANT_CONFIG_DIR 作为 kevisual 目录:', kevisualDir);
|
logger.debug('使用环境变量 ASSISTANT_CONFIG_DIR 作为 kevisual 目录:', kevisualDir);
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
* 助手配置文件路径, 全局配置文件目录
|
* 助手配置文件路径, 全局配置文件目录
|
||||||
@@ -191,10 +192,11 @@ export class AssistantConfig {
|
|||||||
}
|
}
|
||||||
return this.#configPath;
|
return this.#configPath;
|
||||||
}
|
}
|
||||||
init() {
|
init(configDir?: string) {
|
||||||
this.configPath = initConfig(this.configDir);
|
this.configPath = initConfig(configDir || this.configDir);
|
||||||
this.isMountedConfig = true;
|
this.isMountedConfig = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
checkMounted() {
|
checkMounted() {
|
||||||
if (!this.isMountedConfig) {
|
if (!this.isMountedConfig) {
|
||||||
this.init();
|
this.init();
|
||||||
@@ -356,7 +358,7 @@ type AppConfig = {
|
|||||||
list: any[];
|
list: any[];
|
||||||
};
|
};
|
||||||
export function parseArgs(args: string[]) {
|
export function parseArgs(args: string[]) {
|
||||||
const result: { root?: string; home?: boolean; help?: boolean } = {};
|
const result: { root?: string; home?: boolean; help?: boolean } = { home: true };
|
||||||
for (let i = 0; i < args.length; i++) {
|
for (let i = 0; i < args.length; i++) {
|
||||||
const arg = args[i];
|
const arg = args[i];
|
||||||
// 处理 root 参数
|
// 处理 root 参数
|
||||||
@@ -366,14 +368,13 @@ export function parseArgs(args: string[]) {
|
|||||||
i++; // 跳过下一个参数,因为它是值
|
i++; // 跳过下一个参数,因为它是值
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// 处理 home 参数
|
|
||||||
// if (arg === '--home') {
|
|
||||||
result.home = true;
|
|
||||||
// }
|
|
||||||
if (arg === '--help' || arg === '-h') {
|
if (arg === '--help' || arg === '-h') {
|
||||||
result.help = true;
|
result.help = true;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (result.root) {
|
||||||
|
result.home = false;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
/**
|
/**
|
||||||
|
|||||||
@@ -35,7 +35,8 @@ export const checkFileDir = (filePath: string, create = true) => {
|
|||||||
return exist;
|
return exist;
|
||||||
};
|
};
|
||||||
|
|
||||||
export const createDir = (dirPath: string) => {
|
export const createDir = (dirPath: string, isCreate = true) => {
|
||||||
|
if (!isCreate) return dirPath;
|
||||||
if (!checkFileExists(dirPath)) {
|
if (!checkFileExists(dirPath)) {
|
||||||
fs.mkdirSync(dirPath, { recursive: true });
|
fs.mkdirSync(dirPath, { recursive: true });
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -5,7 +5,8 @@ import path from 'node:path';
|
|||||||
import { ProxyInfo } from './proxy.ts';
|
import { ProxyInfo } from './proxy.ts';
|
||||||
import { checkFileExists } from '../file/index.ts';
|
import { checkFileExists } from '../file/index.ts';
|
||||||
import { log } from '@/module/logger.ts';
|
import { log } from '@/module/logger.ts';
|
||||||
|
import { pipeFileStream } from './pipe.ts';
|
||||||
|
import { getContentType } from './module/mime.ts';
|
||||||
export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
|
export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
|
||||||
// url开头的文件
|
// url开头的文件
|
||||||
const url = new URL(req.url, 'http://localhost');
|
const url = new URL(req.url, 'http://localhost');
|
||||||
@@ -51,3 +52,37 @@ export const fileProxy = (req: http.IncomingMessage, res: http.ServerResponse, p
|
|||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
export const fileProxy2 = (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
|
||||||
|
res.statusCode = 501;
|
||||||
|
const url = new URL(req.url, 'http://localhost');
|
||||||
|
const { rootPath, indexPath = '' } = proxyApi?.file || {}
|
||||||
|
if (!rootPath) {
|
||||||
|
res.end(`系统未配置根路径 rootPath id:[${proxyApi?.file?.id}]`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
const pathname = url.pathname;
|
||||||
|
let targetFilepath = pathname.replace(proxyApi.path || '', '');
|
||||||
|
if (targetFilepath.endsWith('/')) {
|
||||||
|
// 没有指定文件,访问index.html
|
||||||
|
targetFilepath += 'index.html';
|
||||||
|
}
|
||||||
|
const filePath = path.join(rootPath || process.cwd(), targetFilepath);
|
||||||
|
const indexTargetPath = path.join(rootPath || process.cwd(), indexPath);
|
||||||
|
let sendPath = filePath;
|
||||||
|
if (!checkFileExists(filePath)) {
|
||||||
|
res.setHeader('X-Proxy-File', 'false');
|
||||||
|
if (indexPath && checkFileExists(indexTargetPath)) {
|
||||||
|
sendPath = indexTargetPath;
|
||||||
|
} else {
|
||||||
|
res.statusCode = 404;
|
||||||
|
res.end(`文件不存在, 路径: ${filePath}`);
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
res.setHeader('X-Proxy-File', 'true');
|
||||||
|
}
|
||||||
|
const contentType = getContentType(sendPath);
|
||||||
|
res.setHeader('Content-Type', contentType);
|
||||||
|
pipeFileStream(sendPath, res);
|
||||||
|
};
|
||||||
50
assistant/src/module/assistant/proxy/module/mime.ts
Normal file
50
assistant/src/module/assistant/proxy/module/mime.ts
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import path from 'path';
|
||||||
|
// 获取文件的 content-type
|
||||||
|
export const getContentType = (filePath: string) => {
|
||||||
|
const extname = path.extname(filePath);
|
||||||
|
const contentType = {
|
||||||
|
'.html': 'text/html; charset=utf-8',
|
||||||
|
'.js': 'text/javascript; charset=utf-8',
|
||||||
|
'.mjs': 'text/javascript; charset=utf-8',
|
||||||
|
'.css': 'text/css; charset=utf-8',
|
||||||
|
'.txt': 'text/plain; charset=utf-8',
|
||||||
|
'.json': 'application/json; charset=utf-8',
|
||||||
|
'.png': 'image/png',
|
||||||
|
'.jpg': 'image/jpg',
|
||||||
|
'.gif': 'image/gif',
|
||||||
|
'.svg': 'image/svg+xml',
|
||||||
|
'.wav': 'audio/wav',
|
||||||
|
'.mp4': 'video/mp4',
|
||||||
|
'.md': 'text/markdown; charset=utf-8', // utf-8配置
|
||||||
|
'.ico': 'image/x-icon', // Favicon 图标
|
||||||
|
'.webp': 'image/webp', // WebP 图像格式
|
||||||
|
'.webm': 'video/webm', // WebM 视频格式
|
||||||
|
'.ogg': 'audio/ogg', // Ogg 音频格式
|
||||||
|
'.mp3': 'audio/mpeg', // MP3 音频格式
|
||||||
|
'.m4a': 'audio/mp4', // M4A 音频格式
|
||||||
|
'.m3u8': 'application/vnd.apple.mpegurl', // HLS 播放列表
|
||||||
|
'.ts': 'video/mp2t', // MPEG Transport Stream
|
||||||
|
'.pdf': 'application/pdf', // PDF 文档
|
||||||
|
'.doc': 'application/msword', // Word 文档
|
||||||
|
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', // Word 文档 (新版)
|
||||||
|
'.ppt': 'application/vnd.ms-powerpoint', // PowerPoint 演示文稿
|
||||||
|
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', // PowerPoint (新版)
|
||||||
|
'.xls': 'application/vnd.ms-excel', // Excel 表格
|
||||||
|
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', // Excel 表格 (新版)
|
||||||
|
'.csv': 'text/csv; charset=utf-8', // CSV 文件
|
||||||
|
'.xml': 'application/xml; charset=utf-8', // XML 文件
|
||||||
|
'.rtf': 'application/rtf', // RTF 文本文件
|
||||||
|
'.eot': 'application/vnd.ms-fontobject', // Embedded OpenType 字体
|
||||||
|
'.ttf': 'font/ttf', // TrueType 字体
|
||||||
|
'.woff': 'font/woff', // Web Open Font Format 1.0
|
||||||
|
'.woff2': 'font/woff2', // Web Open Font Format 2.0
|
||||||
|
'.otf': 'font/otf', // OpenType 字体
|
||||||
|
'.wasm': 'application/wasm', // WebAssembly 文件
|
||||||
|
'.pem': 'application/x-pem-file', // PEM 证书文件
|
||||||
|
'.crt': 'application/x-x509-ca-cert', // CRT 证书文件
|
||||||
|
'.yaml': 'application/x-yaml; charset=utf-8', // YAML 文件
|
||||||
|
'.yml': 'application/x-yaml; charset=utf-8', // YAML 文件(别名)
|
||||||
|
'.zip': 'application/octet-stream',
|
||||||
|
};
|
||||||
|
return contentType[extname] || 'application/octet-stream';
|
||||||
|
};
|
||||||
@@ -2,6 +2,7 @@ import * as http from 'http';
|
|||||||
import * as fs from 'fs';
|
import * as fs from 'fs';
|
||||||
import { isBun } from './utils.ts';
|
import { isBun } from './utils.ts';
|
||||||
import { Readable } from 'stream';
|
import { Readable } from 'stream';
|
||||||
|
import { logger } from '@/module/logger.ts';
|
||||||
/**
|
/**
|
||||||
* 文件流管道传输函数
|
* 文件流管道传输函数
|
||||||
* 将指定文件的内容通过流的方式传输给客户端响应
|
* 将指定文件的内容通过流的方式传输给客户端响应
|
||||||
@@ -99,7 +100,7 @@ export const pipeProxyReq = async (req: http.IncomingMessage, proxyReq: http.Cli
|
|||||||
proxyReq.end();
|
proxyReq.end();
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
console.log('Bun pipeProxyReq content-type', contentType);
|
logger.debug('Bun pipeProxyReq content-type', contentType);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const bodyString = req.body;
|
const bodyString = req.body;
|
||||||
bodyString && proxyReq.write(bodyString);
|
bodyString && proxyReq.write(bodyString);
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import http from 'node:http';
|
import http from 'node:http';
|
||||||
import { httpProxy } from './http-proxy.ts';
|
import { httpProxy } from './http-proxy.ts';
|
||||||
import { s3Proxy } from './s3.ts';
|
import { s3Proxy } from './s3.ts';
|
||||||
|
import { fileProxy2 } from './file-proxy.ts';
|
||||||
export type ProxyInfo = {
|
export type ProxyInfo = {
|
||||||
/**
|
/**
|
||||||
* 代理路径, 比如/root/home, 匹配的路径
|
* 代理路径, 比如/root/home, 匹配的路径
|
||||||
@@ -45,6 +46,11 @@ export type ProxyInfo = {
|
|||||||
accessKeyId?: string;
|
accessKeyId?: string;
|
||||||
secretAccessKey?: string;
|
secretAccessKey?: string;
|
||||||
endpoint?: string;
|
endpoint?: string;
|
||||||
|
},
|
||||||
|
file?: {
|
||||||
|
id?: string;
|
||||||
|
indexPath?: string;
|
||||||
|
rootPath?: string;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
@@ -56,4 +62,7 @@ export const proxy = (req: http.IncomingMessage, res: http.ServerResponse, proxy
|
|||||||
if (proxyApi.type === 's3') {
|
if (proxyApi.type === 's3') {
|
||||||
return s3Proxy(req, res, proxyApi);
|
return s3Proxy(req, res, proxyApi);
|
||||||
}
|
}
|
||||||
|
if (proxyApi.type === 'file') {
|
||||||
|
return fileProxy2(req, res, proxyApi);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
@@ -17,8 +17,11 @@ type ProxyType = {
|
|||||||
user: string;
|
user: string;
|
||||||
key: string;
|
key: string;
|
||||||
path: string;
|
path: string;
|
||||||
indexPath: string;
|
type?: 'file';
|
||||||
absolutePath?: string;
|
file: {
|
||||||
|
indexPath: string;
|
||||||
|
absolutePath: string;
|
||||||
|
};
|
||||||
};
|
};
|
||||||
export type LocalProxyOpts = {
|
export type LocalProxyOpts = {
|
||||||
watch?: boolean; // 是否监听文件变化
|
watch?: boolean; // 是否监听文件变化
|
||||||
@@ -79,8 +82,10 @@ export class LocalProxy {
|
|||||||
user: user,
|
user: user,
|
||||||
key: app,
|
key: app,
|
||||||
path: `/${user}/${app}/`,
|
path: `/${user}/${app}/`,
|
||||||
indexPath: `${user}/${app}/index.html`,
|
file: {
|
||||||
absolutePath: appPath,
|
indexPath: `${user}/${app}/index.html`,
|
||||||
|
absolutePath: appPath,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|||||||
@@ -69,6 +69,7 @@ program
|
|||||||
.option('-n, --name <name>', '服务名称', 'assistant-server')
|
.option('-n, --name <name>', '服务名称', 'assistant-server')
|
||||||
.option('-p, --port <port>', '服务端口')
|
.option('-p, --port <port>', '服务端口')
|
||||||
.option('-s, --start', '是否启动服务')
|
.option('-s, --start', '是否启动服务')
|
||||||
|
.option('-r, --root <root>', '工作空间路径')
|
||||||
.option('-e, --interpreter <interpreter>', '指定使用的解释器', 'bun')
|
.option('-e, --interpreter <interpreter>', '指定使用的解释器', 'bun')
|
||||||
.action(async (options) => {
|
.action(async (options) => {
|
||||||
// console.log('当前执行路径:', execPath, inte);
|
// console.log('当前执行路径:', execPath, inte);
|
||||||
@@ -99,7 +100,9 @@ program
|
|||||||
if (port) {
|
if (port) {
|
||||||
pm2Command += ` -p ${port}`;
|
pm2Command += ` -p ${port}`;
|
||||||
}
|
}
|
||||||
|
if (options.root) {
|
||||||
|
pm2Command += ` --root ${options.root}`;
|
||||||
|
}
|
||||||
console.log(chalk.gray('执行命令:'), pm2Command);
|
console.log(chalk.gray('执行命令:'), pm2Command);
|
||||||
console.log(chalk.gray('脚本路径:'), runPath);
|
console.log(chalk.gray('脚本路径:'), runPath);
|
||||||
|
|
||||||
|
|||||||
@@ -27,13 +27,16 @@ export class AssistantInit extends AssistantConfig {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
async init() {
|
async init(configDir?: string) {
|
||||||
|
if (configDir) {
|
||||||
|
this.configDir = configDir;
|
||||||
|
}
|
||||||
// 1. 检查助手路径是否存在
|
// 1. 检查助手路径是否存在
|
||||||
if (!this.checkConfigPath()) {
|
if (!this.checkConfigPath()) {
|
||||||
console.log(chalk.blue('助手路径不存在,正在创建...'));
|
console.log(chalk.blue('助手路径不存在,正在创建...'));
|
||||||
super.init();
|
super.init(configDir);
|
||||||
} else {
|
} else {
|
||||||
super.init();
|
super.init(configDir);
|
||||||
const assistantConfig = this;
|
const assistantConfig = this;
|
||||||
console.log(chalk.yellow('助手路径已存在'), chalk.green(assistantConfig.configDir));
|
console.log(chalk.yellow('助手路径已存在'), chalk.green(assistantConfig.configDir));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
import { fileProxy, httpProxy, createApiProxy, ProxyInfo, proxy } from '@/module/assistant/index.ts';
|
import { fileProxy, httpProxy, createApiProxy, ProxyInfo, proxy, fileProxy2 } from '@/module/assistant/index.ts';
|
||||||
import http from 'node:http';
|
import http from 'node:http';
|
||||||
import { LocalProxy } from './local-proxy.ts';
|
import { LocalProxy } from './local-proxy.ts';
|
||||||
import { assistantConfig, app, simpleRouter } from '@/app.ts';
|
import { assistantConfig, app, simpleRouter } from '@/app.ts';
|
||||||
@@ -116,27 +116,37 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
|||||||
const defaultApiProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn');
|
const defaultApiProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn');
|
||||||
const allProxy = [...apiProxy, ...defaultApiProxy];
|
const allProxy = [...apiProxy, ...defaultApiProxy];
|
||||||
const apiBackendProxy = allProxy.find((item) => pathname.startsWith(item.path));
|
const apiBackendProxy = allProxy.find((item) => pathname.startsWith(item.path));
|
||||||
// console.log('apiBackendProxy', allProxy, apiBackendProxy, pathname, apiProxy[0].path);
|
const proxyFn = async (req: http.IncomingMessage, res: http.ServerResponse, proxyApi: ProxyInfo) => {
|
||||||
if (apiBackendProxy) {
|
log.debug('proxyApi', { proxyApi, url: req.url });
|
||||||
log.debug('apiBackendProxy', { apiBackendProxy, url: req.url });
|
|
||||||
// 设置 CORS 头
|
// 设置 CORS 头
|
||||||
// res.setHeader('Access-Control-Allow-Origin', '*');
|
// res.setHeader('Access-Control-Allow-Origin', '*');
|
||||||
// res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
// res.setHeader('Access-Control-Allow-Methods', 'GET, POST, PUT, DELETE, OPTIONS');
|
||||||
// res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
|
// res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization, X-Requested-With');
|
||||||
if (apiBackendProxy.s3?.id) {
|
if (proxyApi.s3?.id) {
|
||||||
const storage = _assistantConfig?.storage || []
|
const storage = _assistantConfig?.storage || []
|
||||||
const storageConfig = storage.find((item) => item.id === apiBackendProxy.s3?.id);
|
const storageConfig = storage.find((item) => item.id === proxyApi.s3?.id);
|
||||||
apiBackendProxy.s3 = {
|
proxyApi.s3 = {
|
||||||
...storageConfig,
|
...storageConfig,
|
||||||
...apiBackendProxy.s3,
|
...proxyApi.s3,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (proxyApi.file?.id) {
|
||||||
|
const storage = _assistantConfig?.storage || []
|
||||||
|
const storageConfig = storage.find((item) => item.id === proxyApi.file?.id);
|
||||||
|
proxyApi.file = {
|
||||||
|
...storageConfig,
|
||||||
|
...proxyApi.file,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return proxy(req, res, {
|
return proxy(req, res, {
|
||||||
path: apiBackendProxy.path,
|
path: proxyApi.path,
|
||||||
target: apiBackendProxy.target,
|
target: proxyApi.target,
|
||||||
...apiBackendProxy,
|
...proxyApi,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
if (apiBackendProxy) {
|
||||||
|
return proxyFn(req, res, apiBackendProxy);
|
||||||
|
}
|
||||||
logger.debug('proxyRoute handle by router', { url: req.url }, noAdmin);
|
logger.debug('proxyRoute handle by router', { url: req.url }, noAdmin);
|
||||||
const urls = pathname.split('/');
|
const urls = pathname.split('/');
|
||||||
const [_, _user, _app] = urls;
|
const [_, _user, _app] = urls;
|
||||||
@@ -157,27 +167,9 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
|||||||
}
|
}
|
||||||
const proxyApiList = _assistantConfig?.proxy || [];
|
const proxyApiList = _assistantConfig?.proxy || [];
|
||||||
const proxyApi = proxyApiList.find((item) => pathname.startsWith(item.path));
|
const proxyApi = proxyApiList.find((item) => pathname.startsWith(item.path));
|
||||||
if (proxyApi && proxyApi.type === 'file') {
|
if (proxyApi) {
|
||||||
log.debug('proxyApi', { proxyApi, pathname });
|
log.debug('proxyPage', { proxyApi, pathname });
|
||||||
const _indexPath = proxyApi.indexPath || `${_user}/${_app}/index.html`;
|
return proxyFn(req, res, proxyApi);
|
||||||
const _rootPath = proxyApi.rootPath;
|
|
||||||
if (!_rootPath) {
|
|
||||||
log.error('Not Found rootPath', { proxyApi, pathname });
|
|
||||||
return res.end(`Not Found [${proxyApi.path}] rootPath`);
|
|
||||||
}
|
|
||||||
return fileProxy(req, res, {
|
|
||||||
path: proxyApi.path, // 代理路径, 比如/root/home
|
|
||||||
rootPath: proxyApi.rootPath,
|
|
||||||
...proxyApi,
|
|
||||||
indexPath: _indexPath, // 首页路径
|
|
||||||
});
|
|
||||||
} else if (proxyApi && proxyApi.type === 'http') {
|
|
||||||
log.debug('proxyApi http', { proxyApi, pathname });
|
|
||||||
return httpProxy(req, res, {
|
|
||||||
path: proxyApi.path,
|
|
||||||
target: proxyApi.target,
|
|
||||||
type: 'http',
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
const filter = await authFilter(req, res);
|
const filter = await authFilter(req, res);
|
||||||
if (filter.code !== 200) {
|
if (filter.code !== 200) {
|
||||||
@@ -189,16 +181,19 @@ export const proxyRoute = async (req: http.IncomingMessage, res: http.ServerResp
|
|||||||
const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path));
|
const localProxyProxy = localProxyProxyList.find((item) => pathname.startsWith(item.path));
|
||||||
if (localProxyProxy) {
|
if (localProxyProxy) {
|
||||||
log.log('localProxyProxy', { localProxyProxy, url: req.url });
|
log.log('localProxyProxy', { localProxyProxy, url: req.url });
|
||||||
return fileProxy(req, res, {
|
return proxyFn(req, res, {
|
||||||
path: localProxyProxy.path,
|
path: localProxyProxy.path,
|
||||||
rootPath: localProxy.pagesDir,
|
"type": 'file',
|
||||||
indexPath: localProxyProxy.indexPath,
|
file: {
|
||||||
|
rootPath: localProxy.pagesDir,
|
||||||
|
indexPath: localProxyProxy.file.indexPath,
|
||||||
|
}
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
const creatCenterProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn', ['/root', '/' + _user]);
|
const creatCenterProxy = createApiProxy(_assistantConfig?.app?.url || 'https://kevisual.cn', ['/root', '/' + _user]);
|
||||||
const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path));
|
const centerProxy = creatCenterProxy.find((item) => pathname.startsWith(item.path));
|
||||||
if (centerProxy) {
|
if (centerProxy) {
|
||||||
return httpProxy(req, res, {
|
return proxyFn(req, res, {
|
||||||
path: centerProxy.path,
|
path: centerProxy.path,
|
||||||
target: centerProxy.target,
|
target: centerProxy.target,
|
||||||
type: 'http',
|
type: 'http',
|
||||||
|
|||||||
Reference in New Issue
Block a user